diff options
Diffstat (limited to 'microbe/instruction.h')
-rw-r--r-- | microbe/instruction.h | 1273 |
1 files changed, 1273 insertions, 0 deletions
diff --git a/microbe/instruction.h b/microbe/instruction.h new file mode 100644 index 0000000..2d43343 --- /dev/null +++ b/microbe/instruction.h @@ -0,0 +1,1273 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 by Daniel Clarke <[email protected]> * + * 2005 by David Saxton <[email protected]> * + * * + * 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 <qmap.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> + +class Code; +class CodeIterator; +class CodeConstIterator; +class Instruction; +class PIC14; + +typedef QValueList<Instruction*> 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 QString & 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. + */ + QString 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: + QString 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 QString & 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. + */ + QString 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; + QString 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 QMap< 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 QMap< 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 QMap< 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 QString & 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. + */ + QStringList 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 QString & 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. + */ + QString 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. + */ + QStringList findVariables() const; + + InstructionList m_instructionLists[ PositionCount ]; ///< @see InstructionPosition + QStringList 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 QString 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. + */ + QStringList labels() const { return m_labels; } + /** + * @see labels + */ + void addLabels( const QStringList & labels ); + /** + * @see labels + */ + void setLabels( const QStringList & 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 QString & label ); + + RegisterDepends m_registerDepends; + bool m_bInputStateChanged; + bool m_bUsed; + bool m_bPositionAffectsBranching; + InstructionList m_inputLinks; + InstructionList m_outputLinks; + QStringList m_labels; + Code * m_pCode; + + // Commonly needed member variables for assembly instructions + Register m_file; + RegisterBit m_bit; + QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString & label ) { m_label = label; } + virtual QString 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 ); + + QString label() const { return m_label; } + void setLabel( const QString & 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 ); + + QString m_label; +}; + + +//TODO CLRWDT + + +class Instr_goto : public Instruction +{ + public: + Instr_goto( const QString & label ) { m_label = label; } + virtual QString code() const; + virtual void generateLinksAndStates( Code::iterator current ); + virtual ProcessorBehaviour behaviour() const; + virtual AssemblyType assemblyType() const { return Other; } + + QString label() const { return m_label; } + void setLabel( const QString & label ) { m_label = label; } + + protected: + QString m_label; +}; + + +class Instr_iorlw : public Instruction +{ + public: + Instr_iorlw( int literal ) { m_literal = literal; } + virtual QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString 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 QString & source ) { m_raw = source; } + virtual QString code() const; + virtual InstructionType type() const { return Comment; } + virtual AssemblyType assemblyType() const { return None; } +}; + + +class Instr_asm : public Instruction +{ + public: + Instr_asm( const QString & raw ) { m_raw = raw; } + virtual QString 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 QString & raw ) { m_raw = raw; } + virtual QString code() const; + virtual InstructionType type() const { return Raw; } + virtual AssemblyType assemblyType() const { return None; } +}; +//END Microbe (non-assembly) Operations + + + +#endif |