summaryrefslogtreecommitdiffstats
path: root/microbe/instruction.h
diff options
context:
space:
mode:
Diffstat (limited to 'microbe/instruction.h')
-rw-r--r--microbe/instruction.h1273
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