You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1274 lines
35 KiB
1274 lines
35 KiB
/***************************************************************************
|
|
* Copyright (C) 2004-2005 by Daniel Clarke <daniel.jc@gmail.com> *
|
|
* 2005 by David Saxton <david@bluehaze.org> *
|
|
* *
|
|
* 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 <tqmap.h>
|
|
#include <tqstring.h>
|
|
#include <tqstringlist.h>
|
|
#include <tqvaluelist.h>
|
|
|
|
class Code;
|
|
class CodeIterator;
|
|
class CodeConstIterator;
|
|
class Instruction;
|
|
class PIC14;
|
|
|
|
typedef TQValueList<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 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 tqfind( 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
|