////////////////////////////////////////////////////////////////////// // Arm.h: declarations for the CArm class. // Part of Tarmac // By David Sharp // http://www.davidsharp.com ////////////////////////////////////////////////////////////////////// #include "TarmacGlobals.h" // define constants // PSR flags #define N_FLAG (1<<31) // negative #define Z_FLAG (1<<30) // zero #define C_FLAG (1<<29) // carry #define V_FLAG (1<<28) // overflow #define I_FLAG (1<<27) // interrupt disable #define F_FLAG (1<<26) // fast interrupt disable #define M1_FLAG (1<<1) // processor mode (bit 1) #define M2_FLAG (1<<0) // processor mode (bit 2) // masks for PSR #define PSR_MASK (N_FLAG | Z_FLAG | C_FLAG | V_FLAG | I_FLAG | F_FLAG | M1_FLAG | M2_FLAG) #define PC_MASK (~PSR_MASK) // processor modes for bits 0-1 of PSR #define USR_MODE 0 // user #define FIQ_MODE 1 // fast interrupt request #define IRQ_MODE 2 // interrupt request #define SVC_MODE 3 // supervisor // hardware vector addresses #define RESET_VECTOR 0x0000000 #define UNDEFINED_INSTRUCTION_VECTOR 0x0000004 #define SOFTWARE_INTERRUPT_VECTOR 0x0000008 #define PREFETCH_ABORT_VECTOR 0x000000c #define DATA_ABORT_VECTOR 0x0000010 #define ADDRESS_EXCEPTION_VECTOR 0x0000014 #define INTERRUPT_REQUEST_VECTOR 0x0000018 #define FAST_INTERRUPT_REQUEST_VECTOR 0x000001c // ARM shift types operand fields #define LSL 0 #define LSR 1 #define ASR 2 #define ROR 3 typedef unsigned int Reg; typedef unsigned int Word; typedef unsigned char Byte; #define MODEFLAGS (M1_FLAG | M2_FLAG) #define INTRFLAGS (I_FLAG | F_FLAG) #define PSRMASK (N_FLAG|Z_FLAG|C_FLAG|V_FLAG | MODEFLAGS | INTRFLAGS) #define PCMASK (~PSRMASK) // signals are a block of flags for RedSquirrel to allow IOC to adjust/examine interrupts // "Each device can call IOC.irqa_interrupt(mask), IOC.irqb_interrupt(mask) or // IOC.firq_interrupt(mask) to tell IOC which interrupt has occurred. IOC then calls // ARM.signal_fast_interrupt(state) or ARM.signal_interrupt(state) as appropriate which // sets or clears a bit in signals word (iff that interrupt is enabled). If any signal is // set the arm will handle the interrupt at the end of the current instruction." - GB union Signals { uint32 all; struct { uint8 step_once; // UI wants to stop uint8 interrupt; // interrupt may have occurred uint8 fast_interrupt; // fast interrupt may have occurred uint8 unused; }; }; // dynamic profiling options const bool dynamicProfilingExceptionFreq = FALSE; const bool dynamicProfilingRegisterUse = FALSE; const bool dynamicProfilingConditionalExecution = FALSE; const bool dynamicProfilingCoprocessorUse = TRUE; extern int Enable_Arm; extern int ArmTube; class CArm { void outputSomeNonsenseCPP(); // functions public: void dynamicProfilingCoprocessorUsage(uint32 currentInstruction); void dynamicProfilingExceptionFrequencyReport(); void dynamicProfilingExceptionFrequency(char *exceptionName, uint32& counter); int GetMode(); Reg GetUserRegister(unsigned int reg); void SetMode(int mode); Reg GetUserReg(int reg); Reg GetFirqReg(int reg); Reg GetIrqReg(int reg); Reg GetSvcReg(int reg); Reg GetReg(int reg); void set_stepping(bool state); Word current_pc(); void stop_at(Word address); void ResetState(); void signal_fast_interrupt(bool state); void signal_interrupt(bool state); uint32 pc; inline void performBranch(); // logic inline uint32 eorOperator(uint32 operand1, uint32 operand2); inline uint32 eorOperatorS(uint32 operand1, uint32 operand2); inline uint32 andOperator(uint32 operand1, uint32 operand2); inline uint32 andOperatorS(uint32 operand1, uint32 operand2); inline uint32 orrOperatorS(uint32 operand1, uint32 operand2); inline uint32 orrOperator(uint32 operand1, uint32 operand2); // arithmetic inline void performMla(); inline void performMlaS(); inline void performMul(); inline void performMulS(); inline uint32 adcOperator(uint32 operand1, uint32 operand2); inline uint32 adcOperatorS(uint32 operand1, uint32 operand2); inline uint32 addOperator(uint32 operand1, uint32 operand2); inline uint32 addOperatorS(uint32 operand1, uint32 operand2); inline uint32 subOperator(uint32 operand1, uint32 operand2); inline uint32 subOperatorS(uint32 operand1, uint32 operand2); inline uint32 sbcOperatorS(uint32 operand1, uint32 operand2); inline uint32 sbcOperator(uint32 operand1, uint32 operand2); // memory inline bool performDataTransferLoadByte(uint32 address, uint8& location); inline bool performDataTransferStoreByte(uint32 address, uint8 value); inline bool performDataTransferLoadWord(uint32 address, uint32& destination); inline bool performDataTransferStoreWord(uint32 address, uint32 data); inline bool performBlockDataTransferLoadS(uint rn, uint32 initialAddress, uint32 finalAddress); inline bool performBlockDataTransferLoad(uint rn, uint32 initialAddress, uint32 finalAddress); inline bool performBlockDataTransferStoreS(uint rn, uint32 initialAddress, uint32 finalAddress); inline bool performBlockDataTransferStore(uint rn, uint32 initialAddress, uint32 finalAddress); inline void performSingleDataSwapByte(); inline void performSingleDataSwapWord(); inline bool readWord(uint32 address, uint32& destination); inline bool readByte(uint32 address, uint8& destination); inline bool writeByte(uint32 address, uint8 value); inline bool writeWord(uint32 address, uint32 data); inline bool isValidAddress(uint32 address); // condition flags inline void clearTrans(); inline void setTrans(); inline void setProcessorMode(uint newMode); inline void setProcessorStatusFlags(uint32 mask, uint32 value); inline uint getConditionFlag(uint32 flagValue); inline void clearConditionFlags(uint32 flagValue); inline void setConditionFlags(uint32 flagValue); inline void updateNZFlags(uint32 value); inline void updateAddFlags(uint32 operand1, uint32 operand2, uint32 result); inline void updateSubFlags(uint32 operand1, uint32 operand2, uint32 result); inline bool executeConditionally(uint32 instruction); // generic instruction templates inline void setDestinationS(uint32 value); inline void setDestination(uint32 value); inline uint32 getDataTransferValueRegister(); inline uint32 getDataTransferValueImmediate(); // for data processing instructions operands inline uint32 getDataProcessingImmediateOperand1(); // read op1 when op2 is immediate inline uint32 getDataProcessingImmediateOperand2(); // read op2 when op2 is immediate inline uint32 getDataProcessingImmediateOperand2S(); // read op2 when op2 is immediate and S is set inline uint32 getDataProcessingRegisterOperand1(); // read op1 when op2 is register inline uint32 getDataProcessingRegisterOperand2(); // read op2 when op2 is register inline uint32 getDataProcessingRegisterOperand2S(); // read op2 when op2 is register and S is set // register access inline uint32 getRegister(uint regNumber); inline uint32 getRegisterWithPSR(uint regNumber); inline uint32 getRegisterWithPipelining(uint regNumber); inline uint32 getRegisterWithPSRAndPipelining(uint regNumber); inline void setRegister(uint regNumber, uint32 value); inline void setRegisterWithPrefetch(uint regNumber, uint32 value); inline uint32 getProcessorStatusRegister(); inline void setProcessorStatusRegister(uint32 value); inline uint32 getProgramCounter(); // barrel shifter inline uint32 rrxOperator(uint32 value); // coprocessor inline bool coprocessorDataOperation(); inline bool coprocessorRegisterTransferRead(); inline bool coprocessorRegisterTransferWrite(); inline uint32 coprocessorDataTransferOffset(); inline bool coprocessorDataTransferLoad(uint32 address); inline bool coprocessorDataTransferStore(uint32 address); // exceptions inline void exceptionFastInterruptRequest(); inline void exceptionInterruptRequest(); inline void exceptionPrefetchAbort(); inline void exceptionSoftwareInterrupt(); inline void exceptionUndefinedInstruction(); inline void exceptionReset(); inline void exceptionAddress(); inline void exceptionDataAbort(); // control void exec(int count); void run(void); void reset(); // utility static inline bool getNegative(uint32 value); static inline bool getPositive(uint32 value); static inline bool isExtendedInstruction(uint32 instruction); // construct / destruct CArm(); virtual ~CArm(); // variables Signals signals; bool pending_interrupt; bool pending_fast_interrupt; int instr_count; Word stop_address; private: uint32 lastCopro; // num of instructions executed since last copro instruction profiled void dynamicProfilingConditionalExe(uint32 currentInstruction); void dynamicProfilingConditionalExeReport(); void dynamicProfilingRegisterUsageReport(); void dynamicProfilingRegisterUsage(uint regNumber, bool get); // variables uint processorMode; // in bits 0-1 uint interruptDisableFlag; // in bit 26 uint fastInterruptDisableFlag; // in bit 27 uint conditionFlags; // store NZCV flags in bits 0-3 uint trace; bool prefetchInvalid; uint32 prefetchInstruction; uint32 currentInstruction; uint32 r[16]; // current bank of registers uint32 usrR[16]; // user mode registers uint32 svcR[16]; // supervisor mode registers uint32 irqR[16]; // interrupt mode registers uint32 fiqR[16]; // fast interrupt mode registers uint32 *curR[4]; // pointer to current mode's registers // look up tables uint32 immediateCarry[4096]; uint32 immediateValue[4096]; // TEST ENVIRONMENT VARIABLES uint8 romMemory[0x4000]; // 16 KBytes of rom memory uint8 ramMemory[0x400000]; // 4 MBytes of ram memory bool keepRunning; // keep calling run() // CArmDecoder decoder; // create instance of disassembler uint32 executionCount; uint32 executionCountThresh; // executionCount value to start dumping diss at uint32 previousProcessorMode; uint32 modeCounter; uint32 modeTotal[4]; uint32 resetCounter; uint32 undefCounter; uint32 swiCounter; uint32 prefAbortCounter; uint32 dataAbortCounter; uint32 addrExcepCounter; uint32 irqCounter; uint32 fiqCounter; uint32 exceptionLastExecutionCount; uint32 registerSetCounter[16]; uint32 registerGotCounter[16]; uint32 conditionallyExecuted[16]; uint32 conditionallyNotExecuted[16]; int iocounter; // END OF TEST ENVIRONMENT VARIABLES };