instruction.h

00001 /***************************************************************************
00002  *   Copyright (C) 2004-2005 by Daniel Clarke <daniel.jc@gmail.com>        *
00003  *                      2005 by David Saxton <david@bluehaze.org>          *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00021 #ifndef INSTRUCTION_H
00022 #define INSTRUCTION_H
00023 
00024 #include <qmap.h>
00025 #include <qstring.h>
00026 #include <qstringlist.h>
00027 #include <qvaluelist.h>
00028 
00029 class Code;
00030 class CodeIterator;
00031 class CodeConstIterator;
00032 class Instruction;
00033 class PIC14;
00034 
00035 typedef QValueList<Instruction*> InstructionList;
00036 
00037 
00045 class Register
00046 {
00047         public:
00048                 enum Type
00049                 {
00050                         TMR0,
00051                         OPTION_REG,
00052                         PCL,
00053                         STATUS,
00054                         FSR,
00055                         PORTA,
00056                         TRISA,
00057                         PORTB,
00058                         TRISB,
00059                         EEDATA,
00060                         EECON1,
00061                         EEADR,
00062                         EECON2,
00063                         PCLATH,
00064                         INTCON,
00065                         
00066                         // The following three are "special"
00067                         WORKING, // Not a register that is addressable by an address
00068                         GPR, // Refers to the collection of General Purpose Registers
00069                         none, // used in default constructor
00070                 };
00071                 
00072                 // These banks are used for ORing together in the banks() function
00073                 enum Banks
00074                 {
00075                         Bank0 = 1 << 0,
00076                         Bank1 = 1 << 1,
00077                 };
00078                 
00083                 Register( Type type = none );
00088                 Register( const QString & name );
00093                 Register( const char * name );
00098                 bool operator < ( const Register & reg ) const;
00103                 bool operator == ( const Register & reg ) const;
00108                 uchar banks() const;
00113                 bool bankDependent() const;
00117                 QString name() const { return m_name; }
00121                 Type type() const { return m_type; }
00129                 bool affectsExternal() const;
00130                 
00131         protected:
00132                 QString m_name;
00133                 Type m_type;
00134 };
00135 
00136 
00137 
00138 class RegisterBit
00139 {
00140         public:
00141                 enum STATUS_bits
00142                 {
00143                         C                       = 0, // Carry
00144                         DC                      = 1, // Digit carry
00145                         Z                       = 2, // Zero
00146                         NOT_PD          = 3, // Power-down
00147                         NOT_TO          = 4, // Time-out
00148                         RP0                     = 5, // Bank Select
00149                         RP1                     = 6,
00150                         IRP                     = 7,
00151                 };
00152                 
00153                 enum INTCON_bits
00154                 {
00155                         RBIF            = 0,
00156                         INTF            = 1,
00157                         T0IF            = 2,
00158                         RBIE            = 3,
00159                         INTE            = 4,
00160                         T0IE            = 5,
00161                         EEIE            = 6,
00162                         GIE                     = 7,
00163                 };
00164                 
00165                 enum OPTION_bits
00166                 {
00167                         PS0                     = 0,
00168                         PS1                     = 1,
00169                         PS2                     = 2,
00170                         PSA                     = 3,
00171                         T0SE            = 4,
00172                         T0CS            = 5,
00173                         INTEDG          = 6,
00174                         NOT_RBPU        = 7,
00175                 };
00176                 
00177                 enum EECON1_bits
00178                 {
00179                         RD                      = 0,
00180                         WR                      = 1,
00181                         WREN            = 2,
00182                         WRERR           = 3,
00183                         EEIF            = 4,
00184                 };
00188                 RegisterBit( uchar bitPos = 0, Register::Type reg = Register::none );
00192                 RegisterBit( const QString & name );
00196                 RegisterBit( const char * name );
00202                 Register::Type registerType() const { return m_registerType; }
00206                 uchar bitPos() const { return m_bitPos; }
00210                 uchar bit() const { return (1 << m_bitPos); }
00214                 QString name() const { return m_name; }
00215                 
00216                 
00217         protected:
00221                 void initFromName();
00222                 
00223                 Register::Type m_registerType;
00224                 uchar m_bitPos:3;
00225                 QString m_name;
00226 };
00227 
00228 
00229 
00230 
00241 class RegisterState
00242 {
00243         public:
00244                 RegisterState();
00245                 
00250                 void merge( const RegisterState & state );
00254                 void reset();
00258                 uchar definiteZeros() const { return (~value) & known; }
00262                 uchar definiteOnes() const { return value & known; }
00266                 uchar unknown() const { return ~known; }
00271                 uchar maxValue() const { return (value & known) | (~known); }
00276                 uchar minValue() const { return (value & known); }
00280                 bool operator == ( const RegisterState & state ) const;
00284                 bool operator != ( const RegisterState & state ) const { return !( *this == state ); }
00288                 void print();
00289                 
00291                 uchar known;
00292                 
00294                 uchar value;
00295 };
00296 
00297 
00304 class RegisterBehaviour
00305 {
00306         public:
00307                 RegisterBehaviour();
00311                 void reset();
00312                 
00321                 uchar depends;
00322                 
00330                 uchar indep;
00331 };
00332 
00333 
00334 
00340 class ProcessorState
00341 {
00342         public:
00343                 ProcessorState();
00347                 void merge( const ProcessorState & state );
00351                 void reset();
00355                 RegisterState & reg( const Register & reg );
00359                 RegisterState reg( const Register & reg ) const;
00363                 bool operator == ( const ProcessorState & state ) const;
00367                 bool operator != ( const ProcessorState & state ) const { return !( *this == state ); }
00371                 void print();
00372                 
00374                 RegisterState working;
00375                 
00377                 RegisterState status;
00378                 
00379         protected:
00380                 typedef QMap< Register, RegisterState > RegisterMap;
00385                 RegisterMap m_registers;
00386 };
00387 
00388 
00394 class ProcessorBehaviour
00395 {
00396         public:
00397                 ProcessorBehaviour();
00401                 void reset();
00405                 RegisterBehaviour & reg( const Register & reg );
00406                 
00408                 RegisterBehaviour working;
00409                 
00411                 RegisterBehaviour status;
00412                 
00413         protected:
00414                 typedef QMap< Register, RegisterBehaviour > RegisterMap;
00419                 RegisterMap m_registers;
00420 };
00421 
00422 
00431 class RegisterDepends
00432 {
00433         public:
00434                 RegisterDepends();
00438                 void reset();
00442                 uchar & reg( const Register & reg );
00443                 
00445                 uchar working;
00446                 
00448                 uchar status;
00449                 
00450         protected:
00451                 typedef QMap< Register, uchar > RegisterMap;
00456                 RegisterMap m_registers;
00457 };
00458 
00459 
00460 
00468 class Code
00469 {
00470         public:
00471                 Code();
00472                 
00473                 typedef CodeIterator iterator;
00474                 typedef CodeConstIterator const_iterator;
00475                 
00476                 enum InstructionPosition
00477                 {
00478                         InterruptHandler        = 0,
00479                         LookupTable                     = 1,
00480                         Middle                          = 2, 
00481                         Subroutine                      = 3, 
00482                         
00483                         PositionCount           = 4, 
00484                 };
00485                 
00486                 CodeIterator begin();
00487                 CodeIterator end();
00488                 CodeConstIterator begin() const;
00489                 CodeConstIterator end() const;
00490                 
00495                 void queueLabel( const QString & label, InstructionPosition position = Middle );
00500                 QStringList queuedLabels( InstructionPosition position ) const { return m_queuedLabels[position]; }
00504                 void append( Instruction * instruction, InstructionPosition position = Middle );
00509                 Instruction * instruction( const QString & label ) const;
00515                 iterator find( Instruction * instruction );
00522                 void removeInstruction( Instruction * instruction );
00527                 QString generateCode( PIC14 * pic ) const;
00533                 void merge( Code * code, InstructionPosition middleInsertionPosition = Middle );
00537                 InstructionList * instructionList( InstructionPosition position ) { return & m_instructionLists[position]; }
00541                 const InstructionList * instructionList( InstructionPosition position ) const { return & m_instructionLists[position]; }
00545                 void generateLinksAndStates();
00549                 void setAllUnused();
00555                 void postCompileConstruct();
00556                 
00557         protected:
00562                 QStringList findVariables() const;
00563                 
00564                 InstructionList m_instructionLists[ PositionCount ]; 
00565                 QStringList m_queuedLabels[ PositionCount ]; 
00566                 
00567         private: // Disable copy constructor and operator=
00568                 Code( const Code & );
00569                 Code &operator=( const Code & );
00570 };
00571 
00572 
00579 class CodeIterator
00580 {
00581         public:
00582                 bool operator != ( const CodeIterator & i ) const { return it != i.it; }
00583                 bool operator == ( const CodeIterator & i ) const { return it == i.it; }
00584                 CodeIterator & operator ++ ();
00585                 Instruction * & operator * () { return *it; }
00591                 CodeIterator & removeAndIncrement();
00596                 void insertBefore( Instruction * ins );
00597                 
00598                 InstructionList::iterator it;
00599                 InstructionList::iterator listEnd;
00600                 Code::InstructionPosition pos;
00601                 Code * code;
00602                 InstructionList * list;
00603 };
00604 
00605 
00611 class CodeConstIterator
00612 {
00613         public:
00614                 bool operator != ( const CodeConstIterator & i ) const { return it != i.it; }
00615                 bool operator == ( const CodeConstIterator & i ) const { return it == i.it; }
00616                 CodeConstIterator & operator ++ ();
00617                 const Instruction * operator * () const { return *it; }
00618                 
00619                 InstructionList::const_iterator it;
00620                 InstructionList::const_iterator listEnd;
00621                 Code::InstructionPosition pos;
00622                 const Code * code;
00623                 const InstructionList * list;
00624 };
00625 
00626 
00631 class Instruction
00632 {
00633         public:
00634                 enum InstructionType
00635                 {
00636                         Assembly,
00637                         Raw, // User-inserted assembly
00638                         Comment,
00639                 };
00644                 enum AssemblyType
00645                 {
00649                         FileOriented,
00650                         
00654                         BitOriented,
00655                         
00660                         WorkingOriented,
00661                         
00666                         Other,
00667                         
00671                         None,
00672                 };
00673 
00674                 Instruction();
00675                 virtual ~Instruction();
00676                 void setCode( Code * code ) { m_pCode = code; }
00677                 
00682                 virtual InstructionType type() const { return Assembly; }
00686                 virtual AssemblyType assemblyType() const = 0;
00690                 virtual QString code() const = 0;
00695                 void setInputState( const ProcessorState & processorState ) { m_inputState = processorState; }
00706                 virtual void generateLinksAndStates( Code::iterator instruction );
00710                 virtual ProcessorBehaviour behaviour() const;
00715                 void addInputLink( Instruction * inputLink );
00720                 void addOutputLink( Instruction * inputLink );
00726                 InstructionList inputLinks() const { return m_inputLinks; }
00732                 InstructionList outputLinks() const { return m_outputLinks; }
00736                 void removeInputLink( Instruction * ins );
00740                 void removeOutputLink( Instruction * ins );
00745                 void clearLinks();
00751                 QStringList labels() const { return m_labels; }
00755                 void addLabels( const QStringList & labels );
00759                 void setLabels( const QStringList & labels );
00763                 void setUsed( bool used ) { m_bUsed = used; }
00768                 bool isUsed() const { return m_bUsed; }
00773                 void setRegisterDepends( uchar depends, const Register & reg ) { m_registerDepends.reg(reg) = depends; }
00777                 uchar registerDepends( const Register & reg ) { return m_registerDepends.reg(reg); }
00781                 void resetRegisterDepends() { m_registerDepends.reset(); }
00786                 ProcessorState inputState() const { return m_inputState; }
00791                 ProcessorState outputState() const { return m_outputState; }
00795                 Register file() const { return m_file; }
00799                 RegisterBit bit() const { return m_bit; }
00804                 uchar literal() const { return m_literal; }
00809                 Register outputReg() const { return (m_dest == 0) ? Register::WORKING : m_file; }
00813                 unsigned dest() const { return m_dest; }
00814                 
00815         protected:
00822                 void makeOutputLinks( Code::iterator current, bool firstOutput = true, bool secondOutput = false );
00827                 void makeLabelOutputLink( const QString & label );
00828                 
00829                 RegisterDepends m_registerDepends;
00830                 bool m_bInputStateChanged;
00831                 bool m_bUsed;
00832                 bool m_bPositionAffectsBranching;
00833                 InstructionList m_inputLinks;
00834                 InstructionList m_outputLinks;
00835                 QStringList m_labels;
00836                 Code * m_pCode;
00837                 
00838                 // Commonly needed member variables for assembly instructions
00839                 Register m_file;
00840                 RegisterBit m_bit;
00841                 QString m_raw; // Used by source code, raw asm, etc
00842                 uchar m_literal;
00843                 unsigned m_dest:1; // is 0 (W) or 1 (file).
00844                 ProcessorState m_inputState;
00845                 ProcessorState m_outputState;
00846                 
00847         private: // Disable copy constructor and operator=
00848                 Instruction( const Instruction & );
00849                 Instruction &operator=( const Instruction & );
00850 };
00851 
00852 
00853 
00854 //BEGIN Byte-Oriented File Register Operations
00855 class Instr_addwf : public Instruction
00856 {
00857         public:
00858                 Instr_addwf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00859                 virtual QString code() const;
00860                 virtual void generateLinksAndStates( Code::iterator current );
00861                 virtual ProcessorBehaviour behaviour() const;
00862                 virtual AssemblyType assemblyType() const { return FileOriented; }
00863 };
00864 
00865 
00866 class Instr_andwf : public Instruction
00867 {
00868         public:
00869                 Instr_andwf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00870                 virtual QString code() const;
00871                 virtual void generateLinksAndStates( Code::iterator current );
00872                 virtual ProcessorBehaviour behaviour() const;
00873                 virtual AssemblyType assemblyType() const { return FileOriented; }
00874 };
00875 
00876 
00877 class Instr_clrf : public Instruction
00878 {
00879         public:
00880                 Instr_clrf( const Register & file ) { m_file = file; m_dest = 1; }
00881                 virtual QString code() const;
00882                 virtual void generateLinksAndStates( Code::iterator current );
00883                 virtual ProcessorBehaviour behaviour() const;
00884                 virtual AssemblyType assemblyType() const { return FileOriented; }
00885 };
00886 
00887 
00888 //TODO CLRW
00889 //TODO COMF
00890 
00891 
00892 class Instr_decf : public Instruction
00893 {
00894         public:
00895                 Instr_decf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00896                 virtual QString code() const;
00897                 virtual void generateLinksAndStates( Code::iterator current );
00898                 virtual ProcessorBehaviour behaviour() const;
00899                 virtual AssemblyType assemblyType() const { return FileOriented; }
00900 };
00901 
00902 
00903 class Instr_decfsz : public Instruction
00904 {
00905         public:
00906                 Instr_decfsz( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00907                 virtual QString code() const;
00908                 virtual void generateLinksAndStates( Code::iterator current );
00909                 virtual ProcessorBehaviour behaviour() const;
00910                 virtual AssemblyType assemblyType() const { return FileOriented; }
00911 };
00912 
00913 
00914 class Instr_incf : public Instruction
00915 {
00916         public:
00917                 Instr_incf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00918                 virtual QString code() const;
00919                 virtual void generateLinksAndStates( Code::iterator current );
00920                 virtual ProcessorBehaviour behaviour() const;
00921                 virtual AssemblyType assemblyType() const { return FileOriented; }
00922 };
00923 
00924 
00925 //TODO INCFSZ
00926 
00927 
00928 class Instr_iorwf : public Instruction
00929 {
00930         public:
00931                 Instr_iorwf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00932                 virtual QString code() const;
00933                 virtual void generateLinksAndStates( Code::iterator current );
00934                 virtual ProcessorBehaviour behaviour() const;
00935                 virtual AssemblyType assemblyType() const { return FileOriented; }
00936 };
00937 
00938 
00939 class Instr_movf : public Instruction
00940 {
00941         public:
00942                 Instr_movf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00943                 virtual QString code() const;
00944                 virtual void generateLinksAndStates( Code::iterator current );
00945                 virtual ProcessorBehaviour behaviour() const;
00946                 virtual AssemblyType assemblyType() const { return FileOriented; }
00947 };
00948 
00949 
00950 class Instr_movwf : public Instruction
00951 {
00952         public:
00953                 Instr_movwf( const Register & file ) { m_file = file; m_dest = 1; }
00954                 virtual QString code() const;
00955                 virtual void generateLinksAndStates( Code::iterator current );
00956                 virtual ProcessorBehaviour behaviour() const;
00957                 virtual AssemblyType assemblyType() const { return FileOriented; }
00958 };
00959 
00960 
00961 //TODO NOP
00962 
00963 
00964 class Instr_rlf : public Instruction
00965 {
00966         public:
00967                 Instr_rlf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00968                 virtual QString code() const;
00969                 virtual void generateLinksAndStates( Code::iterator current );
00970                 virtual ProcessorBehaviour behaviour() const;
00971                 virtual AssemblyType assemblyType() const { return FileOriented; }
00972 };
00973 
00974 
00975 class Instr_rrf : public Instruction
00976 {
00977         public:
00978                 Instr_rrf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00979                 virtual QString code() const;
00980                 virtual void generateLinksAndStates( Code::iterator current );
00981                 virtual ProcessorBehaviour behaviour() const;
00982                 virtual AssemblyType assemblyType() const { return FileOriented; }
00983 };
00984 
00985 
00986 class Instr_subwf : public Instruction
00987 {
00988         public:
00989                 Instr_subwf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
00990                 virtual QString code() const;
00991                 virtual void generateLinksAndStates( Code::iterator current );
00992                 virtual ProcessorBehaviour behaviour() const;
00993                 virtual AssemblyType assemblyType() const { return FileOriented; }
00994 };
00995 
00996 
00997 class Instr_swapf : public Instruction
00998 {
00999         public:
01000                 Instr_swapf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
01001                 virtual QString code() const;
01002                 virtual void generateLinksAndStates( Code::iterator current );
01003                 virtual ProcessorBehaviour behaviour() const;
01004                 virtual AssemblyType assemblyType() const { return FileOriented; }
01005 };
01006 
01007 
01008 class Instr_xorwf : public Instruction
01009 {
01010         public:
01011                 Instr_xorwf( const Register & file, int dest ) { m_file = file; m_dest = dest; }
01012                 virtual QString code() const;
01013                 virtual void generateLinksAndStates( Code::iterator current );
01014                 virtual ProcessorBehaviour behaviour() const;
01015                 virtual AssemblyType assemblyType() const { return FileOriented; }
01016 };
01017 //END Byte-Oriented File Register Operations
01018 
01019 
01020 
01021 //BEGIN Bit-Oriented File Register Operations
01022 class Instr_bcf : public Instruction
01023 {
01024         public:
01025                 Instr_bcf( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; }
01026                 virtual QString code() const;
01027                 virtual void generateLinksAndStates( Code::iterator current );
01028                 virtual ProcessorBehaviour behaviour() const;
01029                 virtual AssemblyType assemblyType() const { return BitOriented; }
01030 };
01031 
01032 
01033 class Instr_bsf : public Instruction
01034 {
01035         public:
01036                 Instr_bsf( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; }
01037                 virtual QString code() const;
01038                 virtual void generateLinksAndStates( Code::iterator current );
01039                 virtual ProcessorBehaviour behaviour() const;
01040                 virtual AssemblyType assemblyType() const { return BitOriented; }
01041 };
01042 
01043 
01044 class Instr_btfsc : public Instruction
01045 {
01046         public:
01047                 Instr_btfsc( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; }
01048                 virtual QString code() const;
01049                 virtual void generateLinksAndStates( Code::iterator current );
01050                 virtual ProcessorBehaviour behaviour() const;
01051                 virtual AssemblyType assemblyType() const { return Other; }
01052 };
01053 
01054 
01055 class Instr_btfss : public Instruction
01056 {
01057         public:
01058                 Instr_btfss( const Register & file, const RegisterBit & bit ) { m_file = file; m_bit = bit; }
01059                 virtual QString code() const;
01060                 virtual void generateLinksAndStates( Code::iterator current );
01061                 virtual ProcessorBehaviour behaviour() const;
01062                 virtual AssemblyType assemblyType() const { return Other; }
01063 };
01064 //END Bit-Oriented File Register Operations
01065 
01066 
01067 
01068 //BEGIN Literal and Control Operations
01069 class Instr_addlw : public Instruction
01070 {
01071         public:
01072                 Instr_addlw( int literal ) { m_literal = literal; }
01073                 virtual QString code() const;
01074                 virtual void generateLinksAndStates( Code::iterator current );
01075                 virtual ProcessorBehaviour behaviour() const;
01076                 virtual AssemblyType assemblyType() const { return WorkingOriented; }
01077 };
01078 
01079 
01080 
01081 class Instr_andlw : public Instruction
01082 {
01083         public:
01084                 Instr_andlw( int literal ) { m_literal = literal; }
01085                 virtual QString code() const;
01086                 virtual void generateLinksAndStates( Code::iterator current );
01087                 virtual ProcessorBehaviour behaviour() const;
01088                 virtual AssemblyType assemblyType() const { return WorkingOriented; }
01089 };
01090 
01091 
01092 class Instr_call : public Instruction
01093 {
01094         public:
01095                 Instr_call( const QString & label ) { m_label = label; }
01096                 virtual QString code() const;
01097                 virtual void generateLinksAndStates( Code::iterator current );
01098                 virtual ProcessorBehaviour behaviour() const;
01099                 virtual AssemblyType assemblyType() const { return Other; }
01108                 void makeReturnLinks( Instruction * next );
01109                 
01110                 QString label() const { return m_label; }
01111                 void setLabel( const QString & label ) { m_label = label; }
01112                 
01113         protected:
01122                 void linkReturns( Instruction * current, Instruction * returnPoint );
01123                 
01124                 QString m_label;
01125 };
01126 
01127 
01128 //TODO CLRWDT
01129 
01130 
01131 class Instr_goto : public Instruction
01132 {
01133         public:
01134