/*************************************************************************** * Copyright (C) 2004-2005 by Daniel Clarke * * 2005 by David Saxton * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef INSTRUCTION_H #define INSTRUCTION_H #include #include #include #include class Code; class CodeIterator; class CodeConstIterator; class Instruction; class PIC14; typedef TQValueList InstructionList; /** Abstraction for a Register - should be used instead of a register name. Contains info like whether or not the adressing of the register depends on the bank selection. @author David Saxton */ class Register { public: enum Type { TMR0, OPTION_REG, PCL, STATUS, FSR, PORTA, TRISA, PORTB, TRISB, EEDATA, EECON1, EEADR, EECON2, PCLATH, INTCON, // The following three are "special" WORKING, // Not a register that is addressable by an address GPR, // Refers to the collection of General Purpose Registers none, // used in default constructor }; // These banks are used for ORing together in the banks() function enum Banks { Bank0 = 1 << 0, Bank1 = 1 << 1, }; /** * Creates a register of the given type, giving it the appropriate name. * Note that this constructor should not be used for GPR. */ Register( Type type = none ); /** * Construct a Register with the given name. If the name is not * recognized, then it is assumed to be a GPR register. */ Register( const TQString & name ); /** * Construct a Register with the given name. If the name is not * recognized, then it is assumed to be a GPR register. */ Register( const char * name ); /** * @return less-than-equality between registers; name is only compared * if both registers have type GPR. */ bool operator < ( const Register & reg ) const; /** * @return equality between registers; name is only compared if both * registers have type GPR. */ bool operator == ( const Register & reg ) const; /** * @return 0x1 and 0x2 for being addressable from banks 0 and 1 * respectively, OR'ed together. */ uchar banks() const; /** * Convenience function. * @see banks */ bool bankDependent() const; /** * Returns the name of the register, or the alias for the GPR. */ TQString name() const { return m_name; } /** * @return the type of register. */ Type type() const { return m_type; } /** * From the Optimizer's perspective, it is OK to remove, change or add * any instruction so long as there are no visible external changes that * go against the original intention of the microbe source (a general * guiding principle). Therefore, this function returns true for PORT * and TRIS registers, false for everything else. */ bool affectsExternal() const; protected: TQString m_name; Type m_type; }; class RegisterBit { public: enum STATUS_bits { C = 0, // Carry DC = 1, // Digit carry Z = 2, // Zero NOT_PD = 3, // Power-down NOT_TO = 4, // Time-out RP0 = 5, // Bank Select RP1 = 6, IRP = 7, }; enum INTCON_bits { RBIF = 0, INTF = 1, T0IF = 2, RBIE = 3, INTE = 4, T0IE = 5, EEIE = 6, GIE = 7, }; enum OPTION_bits { PS0 = 0, PS1 = 1, PS2 = 2, PSA = 3, T0SE = 4, T0CS = 5, INTEDG = 6, NOT_RBPU = 7, }; enum EECON1_bits { RD = 0, WR = 1, WREN = 2, WRERR = 3, EEIF = 4, }; /** * Constructs a bit of the given register type at the given position. */ RegisterBit( uchar bitPos = 0, Register::Type reg = Register::none ); /** * Construct a register bit with the given name. */ RegisterBit( const TQString & name ); /** * Construct a register bit with the given name. */ RegisterBit( const char * name ); /** * @warning do not trust this value! actually, this function should be * removed, or the constructors fixed so that this value can be trusted. * @return the register type that the bit belongs to. */ Register::Type registerType() const { return m_registerType; } /** * @return the position of the bit, e.g. "5" for RP0. */ uchar bitPos() const { return m_bitPos; } /** * @return the bit, e.g. "0x20" for Z. */ uchar bit() const { return (1 << m_bitPos); } /** * @return the name of the bit, e.g. "Z" for Z. */ TQString name() const { return m_name; } protected: /** * Determines the register type and bit pos from the bit name (m_name). */ void initFromName(); Register::Type m_registerType; uchar m_bitPos:3; TQString m_name; }; /** Contains information on the state of a register before an instruction is executed. Note that all the "uchar" values in this class should be considered as the 8 bits of a register. So for example, if known=0x2, then only the second bit of the register is known, and its value is given in the second bit of value. @author David Saxton */ class RegisterState { public: RegisterState(); /** * Merges the known and values together, (possibly) reducing what is * known. */ void merge( const RegisterState & state ); /** * Sets known to unknown and value to zero. */ void reset(); /** * Returns the bits that are definitely zero. */ uchar definiteZeros() const { return (~value) & known; } /** * Returns the bits that are definitely one. */ uchar definiteOnes() const { return value & known; } /** * Returns the bits that are unknown. */ uchar unknown() const { return ~known; } /** * @return the largest possible value that this register might be * storing, based on which bits are known and the value of those bits. */ uchar maxValue() const { return (value & known) | (~known); } /** * @return the smallest possible value that this register might be * storing, based on which bits are known and the value of those bits. */ uchar minValue() const { return (value & known); } /** * @return whether the known and value uchars are equal */ bool operator == ( const RegisterState & state ) const; /** * @return whether either of the known and value uchars are not equal. */ bool operator != ( const RegisterState & state ) const { return !( *this == state ); } /** * Prints known and value. */ void print(); /// Whether or not the value is known (for each bit). uchar known; /// The value of the register. uchar value; }; /** Setting and dependency information for register bits. See the respective member descriptions for more information. @author David Saxton */ class RegisterBehaviour { public: RegisterBehaviour(); /** * Sets "depends", "indep" and "changes" to 0x0. */ void reset(); /** * The bits whose value before the instruction is executed will affect * the processor state after execution. So for example, * in MOVLW this will be 0x0; * in ANDLW this will be the bits that are non-zero in the literal; * in BTFSC this will be the bit being tested (if this is the register * being tested). */ uchar depends; /** * The bits whose value after the instruction is executed is independent * of the value before execution. So for example, * in MOVLW, this will be 0xff; * in ANDLW this will be the bits that are zero in the literal; * in BTFSC this will be 0x0. */ uchar indep; }; /** Contains information on the state of a processor; e.g. register values @author David Saxton */ class ProcessorState { public: ProcessorState(); /** * Calls merge for each RegisterState. */ void merge( const ProcessorState & state ); /** * Calls reset() for each RegisterState. */ void reset(); /** * @return state for the given register. */ RegisterState & reg( const Register & reg ); /** * @return state for the given register. */ RegisterState reg( const Register & reg ) const; /** * @return whether all the RegisterStates are identical */ bool operator == ( const ProcessorState & state ) const; /** * @return whether any of the RegisterStates are not equal. */ bool operator != ( const ProcessorState & state ) const { return !( *this == state ); } /** * Displays each register's name and calls RegisterState::print in turn. */ void print(); /// The working register RegisterState working; /// The status register RegisterState status; protected: typedef TQMap< Register, RegisterState > RegisterMap; /** * All registers other than working and status. Entries are created on * calls to reg with a new Register. */ RegisterMap m_registers; }; /** Contains behavioural information for each register. @author David Saxton */ class ProcessorBehaviour { public: ProcessorBehaviour(); /** * Calls reset() for each RegisterBehaviour. */ void reset(); /** * @return behaviour for the given register. */ RegisterBehaviour & reg( const Register & reg ); /// The working register RegisterBehaviour working; /// The status register RegisterBehaviour status; protected: typedef TQMap< Register, RegisterBehaviour > RegisterMap; /** * All registers other than working and status. Entries are created on * calls to reg with a new Register. */ RegisterMap m_registers; }; /** Contains information on whether a register is overwritten before its value is used. Each uchar respresents the 8 bits of the register; if the bit is 1, then the corresponding bit of the register is used by the Instruction or one of its outputs before it is overwritten. @author David Saxton */ class RegisterDepends { public: RegisterDepends(); /** * Sets all the depends values to 0x0. */ void reset(); /** * @return behaviour for the given register. */ uchar & reg( const Register & reg ); /// The working register uchar working; /// The status register uchar status; protected: typedef TQMap< Register, uchar > RegisterMap; /** * All registers other than working and status. Entries are created on * calls to reg with a new Register. */ RegisterMap m_registers; }; /** Holds a program structure; an (ordered) list of blocks of code, each of which contains a list of instructions. The structure is such as to provide easy manipulation of the program, as well as aiding the optimizer. @author David Saxton */ class Code { public: Code(); typedef CodeIterator iterator; typedef CodeConstIterator const_iterator; enum InstructionPosition { InterruptHandler = 0, LookupTable = 1, Middle = 2, ///< Used for main code Subroutine = 3, ///< Used for subroutines PositionCount = 4, ///< This must remain the last item and be the number of valid positions }; CodeIterator begin(); CodeIterator end(); CodeConstIterator begin() const; CodeConstIterator end() const; /** * Queues a label to be given to the next instruction to be added in the * given position */ void queueLabel( const TQString & label, InstructionPosition position = Middle ); /** * Returns the list of queued labels for the given position. This is * used in merging code, as we also need to merge any queued labels. */ TQStringList queuedLabels( InstructionPosition position ) const { return m_queuedLabels[position]; } /** * Adds the Instruction at the given position. */ void append( Instruction * instruction, InstructionPosition position = Middle ); /** * @returns the Instruction with the given label (or null if no such * Instruction). */ Instruction * instruction( const TQString & label ) const; /** * Look for an Assembly instruction (other types are ignored). * @return an iterator to the current instruction, or end if it wasn't * found. */ iterator find( Instruction * instruction ); /** * Removes the Instruction (regardless of position). * @warning You should always use only this function to remove an * instruction as this function handles stuff such as pushing labels * from this instruction onto the next before deletion. */ void removeInstruction( Instruction * instruction ); /** * Merges all the blocks output together with other magic such as adding * variables, gpasm directives, etc. */ TQString generateCode( PIC14 * pic ) const; /** * Appends the InstructionLists to the end of the ones in this instance. * @param middleInsertionPosition is the position where the middle code * blocks of the given code will be merged at. */ void merge( Code * code, InstructionPosition middleInsertionPosition = Middle ); /** * @returns the InstructionList for the given insertion position. */ InstructionList * instructionList( InstructionPosition position ) { return & m_instructionLists[position]; } /** * @returns the InstructionList for the given insertion position. */ const InstructionList * instructionList( InstructionPosition position ) const { return & m_instructionLists[position]; } /** * Calls generateOutputLinks for each Instruction */ void generateLinksAndStates(); /** * Calls setUsed(false) for all instructions. */ void setAllUnused(); /** * Does any work that is needed to the code before it can be passed to * the optimizer (such as flushing out queued labels). This is called * after all the instructions have been added to the code. */ void postCompileConstruct(); protected: /** * Used when generating the code. Finds the list of general purpose * registers that are referenced and returns their aliases. */ TQStringList findVariables() const; InstructionList m_instructionLists[ PositionCount ]; ///< @see InstructionPosition TQStringList m_queuedLabels[ PositionCount ]; ///< @see InstructionPosition private: // Disable copy constructor and operator= Code( const Code & ); Code &operator=( const Code & ); }; /** Iterates over all the instructions, going seamlessly between the different lists and avoiding the non-assembly instructions. @author David Saxton */ class CodeIterator { public: bool operator != ( const CodeIterator & i ) const { return it != i.it; } bool operator == ( const CodeIterator & i ) const { return it == i.it; } CodeIterator & operator ++ (); Instruction * & operator * () { return *it; } /** * Deletes the instruction that this iterator is currently pointing at * (removing it from any lists), and increments the iterator to the next * instruction. */ CodeIterator & removeAndIncrement(); /** * Inserts the given instruction before the instruction pointed at by * this iterator. */ void insertBefore( Instruction * ins ); InstructionList::iterator it; InstructionList::iterator listEnd; Code::InstructionPosition pos; Code * code; InstructionList * list; }; /** A const version of CodeIterator (cannot change instructions). @author David Saxton */ class CodeConstIterator { public: bool operator != ( const CodeConstIterator & i ) const { return it != i.it; } bool operator == ( const CodeConstIterator & i ) const { return it == i.it; } CodeConstIterator & operator ++ (); const Instruction * operator * () const { return *it; } InstructionList::const_iterator it; InstructionList::const_iterator listEnd; Code::InstructionPosition pos; const Code * code; const InstructionList * list; }; /** @author Daniel Clarke @author David Saxton */ class Instruction { public: enum InstructionType { Assembly, Raw, // User-inserted assembly Comment, }; /** * Used in optimization. Note that this follows roughly, but not * exactly, the Microchip classifications of similar categories. */ enum AssemblyType { /** * Writes to a file (which can be obtained by calling outputReg(). */ FileOriented, /** * Writes to a file bit (so BCF or BSF). */ BitOriented, /** * Affects the working register via a literal operation, with no * branching (so excludes retlw). */ WorkingOriented, /** * Assembly instructions that don't come under the above categories * (so control and branching instructions). */ Other, /** * The Instruction is not of Assembly InstructionType. */ None, }; Instruction(); virtual ~Instruction(); void setCode( Code * code ) { m_pCode = code; } /** * This is used to decide how to output the instruction, and which * instructions to avoid while optimizing. */ virtual InstructionType type() const { return Assembly; } /** * @return the AssemblyType (None for non-Assembly instructions). */ virtual AssemblyType assemblyType() const = 0; /** * The text to output to the generated assembly. */ virtual TQString code() const = 0; /** * The input processor state is used to generate the outputlinks and the * output processor state. */ void setInputState( const ProcessorState & processorState ) { m_inputState = processorState; } /** * By using the ProcessorState, the Instruction should: * * Find all instructions that could be executed after this instruction. * * Generate the output ProcessorState. * The default behaviour of this function is to link to the next * sequential instruction, and to generate an unknown ProcessorState. * @warning if your instruction depends on any bits, then it must * reinherit this function and say so. * @param instruction points at this instruction */ virtual void generateLinksAndStates( Code::iterator instruction ); /** * @return the processor behaviour for this instruction. */ virtual ProcessorBehaviour behaviour() const; /** * An input link is an instruction that might be executed immediately * before this Instruction. */ void addInputLink( Instruction * inputLink ); /** * An output link is an instruction that might be executed immediately * after this Instruction. */ void addOutputLink( Instruction * inputLink ); /** * The list of instructions that might be executed immediately before * this instruction. * @see addInputLink */ InstructionList inputLinks() const { return m_inputLinks; } /** * The list of instructions that might be executed immediately after * this instruction. Instruction does not generate these links; instead * the list is generated Code::generateLinksAndStates function. */ InstructionList outputLinks() const { return m_outputLinks; } /** * Remove the given input link from the instruction. */ void removeInputLink( Instruction * ins ); /** * Remove the given output link from the instruction. */ void removeOutputLink( Instruction * ins ); /** * Clears all input and output links from this instruction. This does * not remove references to this instruction from other instructions. */ void clearLinks(); /** * An instruction may have zero, or more than zero labels associated * with it - these will be printed before the instruction in the * assembly output. */ TQStringList labels() const { return m_labels; } /** * @see labels */ void addLabels( const TQStringList & labels ); /** * @see labels */ void setLabels( const TQStringList & labels ); /** * @see used */ void setUsed( bool used ) { m_bUsed = used; } /** * Used for optimization purposes in determining whether the instruction * has been examined yet (to avoid infinite loops). */ bool isUsed() const { return m_bUsed; } /** * Set by the optimizer to indicate whether this instruction or any of * its outputs overwrite any of the bits of the given register. */ void setRegisterDepends( uchar depends, const Register & reg ) { m_registerDepends.reg(reg) = depends; } /** * @see setOutputsOverwriteWorking */ uchar registerDepends( const Register & reg ) { return m_registerDepends.reg(reg); } /** * Resets the overwrites. */ void resetRegisterDepends() { m_registerDepends.reset(); } /** * @return the input processor state to this instruction. * @see setInputState */ ProcessorState inputState() const { return m_inputState; } /** * @return the output processor state from this instruction. * @see generateLinksAndStates. */ ProcessorState outputState() const { return m_outputState; } /** * Only applicable to Instructions that refer to a file. */ Register file() const { return m_file; } /** * Only applicable to Instructions that refer to a bit (such as BCF). */ RegisterBit bit() const { return m_bit; } /** * Only applicable to instructions that refer to a literal (such as * XORLW). */ uchar literal() const { return m_literal; } /** * Applicable only to instructions that save a result to working or file * depending on the destination bit. */ Register outputReg() const { return (m_dest == 0) ? Register::WORKING : m_file; } /** * Applicable only to instructions that use the destination flag. */ unsigned dest() const { return m_dest; } protected: /** * This function is provided for convenience; it creates links to the * first or second instructions after this one, depending on the value * of firstOutput and secondOutput. * @see generateOutputLinks */ void makeOutputLinks( Code::iterator current, bool firstOutput = true, bool secondOutput = false ); /** * This function is provided for instructions that jump to a label (i.e. * call and goto). */ void makeLabelOutputLink( const TQString & label ); RegisterDepends m_registerDepends; bool m_bInputStateChanged; bool m_bUsed; bool m_bPositionAffectsBranching; InstructionList m_inputLinks; InstructionList m_outputLinks; TQStringList m_labels; Code * m_pCode; // Commonly needed member variables for assembly instructions Register m_file; RegisterBit m_bit; TQString m_raw; // Used by source code, raw asm, etc uchar m_literal; unsigned m_dest:1; // is 0 (W) or 1 (file). ProcessorState m_inputState; ProcessorState m_outputState; private: // Disable copy constructor and operator= Instruction( const Instruction & ); Instruction &operator=( const Instruction & ); }; //BEGIN Byte-Oriented File Register Operations class Instr_addwf : public Instruction { public: Instr_addwf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_andwf : public Instruction { public: Instr_andwf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_clrf : public Instruction { public: Instr_clrf( const Register & file ) { m_file = file; m_dest = 1; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; //TODO CLRW //TODO COMF class Instr_decf : public Instruction { public: Instr_decf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_decfsz : public Instruction { public: Instr_decfsz( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_incf : public Instruction { public: Instr_incf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; //TODO INCFSZ class Instr_iorwf : public Instruction { public: Instr_iorwf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_movf : public Instruction { public: Instr_movf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_movwf : public Instruction { public: Instr_movwf( const Register & file ) { m_file = file; m_dest = 1; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; //TODO NOP class Instr_rlf : public Instruction { public: Instr_rlf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_rrf : public Instruction { public: Instr_rrf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_subwf : public Instruction { public: Instr_subwf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_swapf : public Instruction { public: Instr_swapf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; class Instr_xorwf : public Instruction { public: Instr_xorwf( const Register & file, int dest ) { m_file = file; m_dest = dest; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return FileOriented; } }; //END Byte-Oriented File Register Operations //BEGIN Bit-Oriented File Register Operations class Instr_bcf : public Instruction { public: Instr_bcf( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return BitOriented; } }; class Instr_bsf : public Instruction { public: Instr_bsf( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return BitOriented; } }; class Instr_btfsc : public Instruction { public: Instr_btfsc( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } }; class Instr_btfss : public Instruction { public: Instr_btfss( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } }; //END Bit-Oriented File Register Operations //BEGIN Literal and Control Operations class Instr_addlw : public Instruction { public: Instr_addlw( int literal ) { m_literal = literal; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return WorkingOriented; } }; class Instr_andlw : public Instruction { public: Instr_andlw( int literal ) { m_literal = literal; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return WorkingOriented; } }; class Instr_call : public Instruction { public: Instr_call( const TQString & label ) { m_label = label; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } /** * Called from Code after all the output links have been generated. The * instruction that is called has its output links followed, and any * returns encountered are linked back to the instruction after this * one. * @param next the instruction after this one which the return points * will be linked to. */ void makeReturnLinks( Instruction * next ); TQString label() const { return m_label; } void setLabel( const TQString & label ) { m_label = label; } protected: /** * Used by makeReturnLinks. Recursively follows the instruction's output * links, until a return is found - then, link the return point back to * the instruction after this one. Call instructions found while * following the output are ignored. * @param returnPoint the instruction to link back to on finding a * return. */ void linkReturns( Instruction * current, Instruction * returnPoint ); TQString m_label; }; //TODO CLRWDT class Instr_goto : public Instruction { public: Instr_goto( const TQString & label ) { m_label = label; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } TQString label() const { return m_label; } void setLabel( const TQString & label ) { m_label = label; } protected: TQString m_label; }; class Instr_iorlw : public Instruction { public: Instr_iorlw( int literal ) { m_literal = literal; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return WorkingOriented; } }; class Instr_movlw : public Instruction { public: Instr_movlw( int literal ) { m_literal = literal; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return WorkingOriented; } }; class Instr_retfie : public Instruction { public: Instr_retfie() {}; virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } }; class Instr_retlw : public Instruction { public: Instr_retlw( int literal ) { m_literal = literal; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } }; class Instr_return : public Instruction { public: Instr_return() {}; virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } }; class Instr_sleep : public Instruction { public: Instr_sleep() {}; virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return Other; } }; class Instr_sublw : public Instruction { public: Instr_sublw( int literal ) { m_literal = literal; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return WorkingOriented; } }; class Instr_xorlw : public Instruction { public: Instr_xorlw( int literal ) { m_literal = literal; } virtual TQString code() const; virtual void generateLinksAndStates( Code::iterator current ); virtual ProcessorBehaviour behaviour() const; virtual AssemblyType assemblyType() const { return WorkingOriented; } }; //END Literal and Control Operations //BEGIN Microbe (non-assembly) Operations class Instr_sourceCode : public Instruction { public: Instr_sourceCode( const TQString & source ) { m_raw = source; } virtual TQString code() const; virtual InstructionType type() const { return Comment; } virtual AssemblyType assemblyType() const { return None; } }; class Instr_asm : public Instruction { public: Instr_asm( const TQString & raw ) { m_raw = raw; } virtual TQString code() const; virtual InstructionType type() const { return Raw; } virtual AssemblyType assemblyType() const { return None; } }; // Like Instr_asm, but does not put ;asm {} in, used // for internal things like gpasm directives etc... class Instr_raw : public Instruction { public: Instr_raw( const TQString & raw ) { m_raw = raw; } virtual TQString code() const; virtual InstructionType type() const { return Raw; } virtual AssemblyType assemblyType() const { return None; } }; //END Microbe (non-assembly) Operations #endif