pic14.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2004-2005 by Daniel Clarke                              *
00003  *   daniel.jc@gmail.com                                                   *
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 
00022 #include "instruction.h"
00023 #include "parser.h"
00024 #include "pic14.h"
00025 
00026 #include <cassert>
00027 #include <kdebug.h>
00028 #include <iostream>
00029 using namespace std;
00030 
00031 bool LEDSegTable[][7] = {
00032 { 1, 1, 1, 1, 1, 1, 0 },
00033 { 0, 1, 1, 0, 0, 0, 0 }, // 1
00034 { 1, 1, 0, 1, 1, 0, 1 }, // 2
00035 { 1, 1, 1, 1, 0, 0, 1 }, // 3
00036 { 0, 1, 1, 0 ,0, 1, 1 }, // 4
00037 { 1, 0, 1, 1, 0, 1, 1 }, // 5
00038 { 1, 0, 1, 1, 1, 1, 1 }, // 6
00039 { 1, 1, 1, 0, 0, 0, 0 }, // 7
00040 { 1, 1, 1, 1, 1, 1, 1 }, // 8
00041 { 1, 1, 1, 0, 0, 1, 1 }, // 9
00042 { 1, 1, 1, 0, 1, 1, 1 }, // A
00043 { 0, 0, 1, 1, 1, 1, 1 }, // b
00044 { 1, 0, 0, 1, 1, 1, 0 }, // C
00045 { 0, 1, 1, 1, 1, 0, 1 }, // d
00046 { 1, 0, 0, 1, 1, 1, 1 }, // E
00047 { 1, 0, 0, 0, 1, 1, 1 }  // F
00048 };
00049 
00050 
00051 
00052 PIC14::PIC14( Microbe * master, Type type )
00053 {
00054         mb = master;
00055         m_pCode = 0;
00056         m_type = type;
00057         
00058 }
00059 
00060 
00061 PIC14::~PIC14()
00062 {
00063 }
00064 
00065 PortPin PIC14::toPortPin( const QString & portPinString )
00066 {
00067         QString port;
00068         int pin = -1;
00069         
00070         // In form e.g. RB3
00071         if ( portPinString.length() == 3 )
00072         {
00073                 port = QString("PORT%1").arg( portPinString[1].upper() );
00074                 pin = QString( portPinString[2] ).toInt();
00075         }
00076         else
00077         {
00078                 int dotpos = portPinString.find(".");
00079                 if ( dotpos == -1 )
00080                         return PortPin();
00081                 
00082                 port = portPinString.left(dotpos);
00083                 pin = portPinString.mid(dotpos+1).toInt();
00084         }
00085         
00086         PortPin portPin( port, pin );
00087         
00088         if ( isValidPortPin( portPin ) )
00089                 return portPin;
00090         else
00091                 return PortPin();
00092 }
00093 
00094 
00095 void PIC14::mergeCode( Code * code )
00096 {
00097         m_pCode->merge( code );
00098 }
00099 
00100 
00101 uchar PIC14::gprStart() const
00102 {
00103         switch ( m_type )
00104         {
00105                 case P16C84:
00106                 case P16F84:
00107                         return 0xc;
00108                         
00109                 case P16F627:
00110                 case P16F628:
00111                         return 0x20;
00112                         
00113                 case unknown:
00114                         break;
00115         }
00116         
00117         kdError() << k_funcinfo << "Unknown PIC type = " << m_type << endl;
00118         return 0xc;
00119 }
00120 
00121 
00122 PIC14::Type PIC14::toType( const QString & _text )
00123 {
00124         QString text = _text.upper().simplifyWhiteSpace().remove('P');
00125         
00126         if ( text == "16C84" )
00127                 return P16C84;
00128         
00129         if ( text == "16F84" )
00130                 return P16F84;
00131         
00132         if ( text == "16F627" )
00133                 return P16F627;
00134         
00135         if ( text == "16F628" )
00136                 return P16F628;
00137         
00138         cerr << QString("%1 is not a known PIC identifier\n").arg(_text);
00139         return unknown;
00140 }
00141 
00142 
00143 QString PIC14::minimalTypeString() const
00144 {
00145         switch ( m_type )
00146         {
00147                 case P16C84:
00148                         return "16C84";
00149                         
00150                 case P16F84:
00151                         return "16F84";
00152                         
00153                 case P16F627:
00154                         return "16F627";
00155                         
00156                 case P16F628:
00157                         return "16F628";
00158                         
00159                 case unknown:
00160                         break;
00161         }
00162         
00163         kdError() << k_funcinfo << "Unknown PIC type = " << m_type << endl;
00164         return 0;;
00165 }
00166 
00167 
00168 void PIC14::postCompileConstruct( const QStringList &interrupts )
00169 {
00170         m_pCode->append( new Instr_raw("\n\tEND\n"), Code::Subroutine );
00171         
00172         if ( interrupts.isEmpty() )
00173         {
00174                 // If there are no ISRs then we don't need to put in any handler code.
00175                 // Instead, just insert the goto start instruction in case we need to
00176                 // jump past any lookup tabes (and if there are none, then the optimizer
00177                 // will remove the goto instruction).
00178                 m_pCode->append(new Instr_goto("_start"), Code::InterruptHandler);
00179                 m_pCode->queueLabel( "_start", Code::LookupTable );
00180                 return;
00181         }
00182         
00183         /*
00184                 INTCON register:
00185                 7 --- GIE EEIE T0IE INTE RBIE T0IF INTF RBIF --- 0
00186 
00187                 E: enable
00188                 F: flag
00189                 Flag bits must be cleared manually before reactivating GIE,
00190                 but we do this in each individual interrupt handler
00191         */
00192 
00193         // The bizarre dance with swap is to ensure the status bits
00194         // are preserved properly
00195         m_pCode->append(new Instr_goto("_start"), Code::InterruptHandler);
00196         
00197         m_pCode->append(new Instr_raw("ORG 0x4"), Code::InterruptHandler);
00198         // When we arrive here:
00199         // Return address on stack,
00200         // GIE flag cleared (globally interrupts disabled)
00201         // W or STATUS not preserved by processor.
00202         m_pCode->append(new Instr_movwf("W_TEMP"), Code::InterruptHandler);
00203         m_pCode->append(new Instr_swapf("STATUS",0), Code::InterruptHandler);
00204         m_pCode->append(new Instr_movwf("STATUS_TEMP"), Code::InterruptHandler);
00205         
00206         QStringList::ConstIterator interruptsEnd = interrupts.end();
00207         for( QStringList::ConstIterator it = interrupts.begin(); it != interruptsEnd; ++it )
00208         {
00209                 // Is the interrupt's flag bit set?
00210                 m_pCode->append(new Instr_btfsc("INTCON",QString::number(interruptNameToBit((*it), true))), Code::InterruptHandler);
00211                 m_pCode->append(new Instr_goto("_interrupt_" + (*it)), Code::InterruptHandler); // Yes, do its handler routine
00212                 // Otherwise fall through to the next.
00213         }
00214         
00215         // If there was "somehow" a suprious interrupt there isn't really
00216         // much we can do about that (??) so just fall through and hope for the worst.
00217         
00218         m_pCode->queueLabel( "_interrupt_end", Code::InterruptHandler );
00219         m_pCode->append(new Instr_swapf("STATUS_TEMP",0), Code::InterruptHandler );
00220         m_pCode->append(new Instr_movwf("STATUS"), Code::InterruptHandler );
00221         m_pCode->append(new Instr_swapf("W_TEMP",1), Code::InterruptHandler );
00222         m_pCode->append(new Instr_swapf("W_TEMP",0), Code::InterruptHandler );
00223         m_pCode->append(new Instr_retfie()); // Returns and renables globally interrupts.
00224         
00225         m_pCode->queueLabel( "_start", Code::LookupTable );
00226 }
00227 
00228 int PIC14::interruptNameToBit(const QString &name, bool flag)
00229 {
00230         // 7 --- GIE EEIE T0IE INTE RBIE T0IF INTF RBIF --- 0
00231 
00232         if( name == "change" ) // RB
00233         {
00234                 if(flag) return 0;
00235                 else return 3;
00236         }
00237         else if( name == "timer" )
00238         {
00239                 if(flag) return 2;
00240                 else return 5;
00241         }
00242         else if( name == "external" )
00243         {
00244                 if(flag) return 1;
00245                 else return 4;
00246         }
00247         
00248         return -1;
00249 }
00250 
00251 
00252 bool PIC14::isValidPort( const QString & portName ) const
00253 {
00254         return ( portName == "PORTA" || portName == "porta" ||
00255                          portName == "PORTB" || portName == "portb" );
00256 }
00257 
00258 
00259 bool PIC14::isValidPortPin( const PortPin & portPin ) const
00260 {
00261         if ( portPin.port() == "PORTA" )
00262                 return (portPin.pin() >= 0) && (portPin.pin() <= 4);
00263         
00264         if ( portPin.port() == "PORTB" )
00265                 return (portPin.pin() >= 0) && (portPin.pin() <= 7);
00266         
00267         return false;
00268 }
00269 
00270 
00271 bool PIC14::isValidTris( const QString & trisName ) const
00272 {
00273         return ( trisName == "TRISA" || trisName == "trisa" ||
00274                          trisName == "TRISB" || trisName == "trisb" );
00275 }
00276 
00277 
00278 bool PIC14::isValidInterrupt( const QString & interruptName ) const
00279 {
00280         if(m_type == "P16F84" || m_type =="P16C84")
00281         {
00282                 return ( interruptName == "change" ||
00283                                  interruptName == "timer" ||
00284                                  interruptName == "external" );
00285         }
00286         return false;
00287 }
00288 
00289 
00290 void PIC14::setConditionalCode( Code * ifCode, Code * elseCode )
00291 {
00292         m_ifCode = ifCode;
00293         m_elseCode = elseCode;
00294 }
00295 
00296 void PIC14::Sgoto(const QString &label)
00297 {
00298         m_pCode->append( new Instr_goto(label) );
00299 }
00300 
00301 void PIC14::Slabel(const QString &label)
00302 {
00303 //      std::cout << k_funcinfo << "label="<<label<<'\n';
00304         m_pCode->queueLabel( label, Code::Middle );
00305 }
00306 
00307 void PIC14::Send()
00308 {
00309         m_pCode->append( new Instr_sleep() );
00310 }
00311 
00312 void PIC14::Ssubroutine( const QString &procName, Code * subCode )
00313 {
00314         m_pCode->queueLabel( procName, Code::Subroutine );
00315         m_pCode->merge( subCode, Code::Subroutine );
00316         m_pCode->append( new Instr_return(), Code::Subroutine );
00317 }
00318 
00319 void PIC14::Sinterrupt( const QString &procName, Code * subCode )
00320 {
00321         m_pCode->queueLabel( "_interrupt_" + procName, Code::Subroutine );
00322         
00323         // Clear the interrupt flag for this particular interrupt source
00324         m_pCode->append( new Instr_bcf("INTCON",QString::number(interruptNameToBit(procName,true))) );
00325         m_pCode->merge( subCode, Code::Subroutine );
00326         
00327         m_pCode->append( new Instr_goto("_interrupt_end"), Code::Subroutine );
00328 }
00329 
00330 
00331 void PIC14::Scall(const QString &name)
00332 {
00333         m_pCode->append( new Instr_call(name) );
00334 }
00335 
00336 
00337 void PIC14::Ssetlh( const PortPin & portPin, bool high)
00338 {
00339         if(high)
00340                 m_pCode->append( new Instr_bsf( portPin.port(),QString::number(portPin.pin()) ) );
00341         else
00342                 m_pCode->append( new Instr_bcf( portPin.port(), QString::number(portPin.pin()) ) );
00343 }
00344 
00345 void PIC14::rearrangeOpArguments( QString * val1, QString * val2, LocationType * val1Type, LocationType * val2Type)
00346 {
00347         if( *val2Type == work && *val1Type != work )
00348         {
00349                 LocationType tempType = *val2Type;
00350                 QString tempVal = *val2;
00351                 
00352                 *val2Type = *val1Type;
00353                 *val2 = *val1;
00354                 
00355                 *val1Type = tempType;
00356                 *val1 = tempVal;
00357         }
00358 }
00359 
00360 void PIC14::add( QString val1, QString val2, LocationType val1Type, LocationType val2Type )
00361 {
00362         rearrangeOpArguments( &val1, &val2, &val1Type, &val2Type );
00363 
00364         switch(val1Type)
00365         {
00366                 case num:  m_pCode->append(new Instr_movlw( val1.toInt( 0, 0 ) )); break;
00367                 case work: break;
00368                 case var: m_pCode->append(new Instr_movf(val1,0)); break;
00369         }
00370         
00371         switch(val2Type)
00372         {
00373                 case num: m_pCode->append(new Instr_addlw(val2.toInt( 0, 0 ))); break;
00374                 case work: break;
00375                 case var: m_pCode->append(new Instr_addwf(val2,0)); break;
00376         }
00377 }
00378 
00379 void PIC14::subtract( const QString & val1, const QString & val2, LocationType val1Type, LocationType val2Type )
00380 {
00381         switch(val2Type)
00382         {
00383                 case num:  m_pCode->append(new Instr_movlw( val2.toInt( 0, 0 ) )); break;
00384                 case work: break;
00385                 case var: m_pCode->append(new Instr_movf(val2,0)); break;
00386         }
00387         switch(val1Type)
00388         {
00389                 case num: m_pCode->append(new Instr_sublw(val1.toInt( 0, 0 ))); break;
00390                 case work: break;
00391                 case var: m_pCode->append(new Instr_subwf(val1,0)); break;
00392         }
00393 }
00394 
00395 void PIC14::assignNum(const QString & val)
00396 {
00397         m_pCode->append(new Instr_movlw(val.toInt( 0, 0 )));
00398 }
00399 
00400 void PIC14::assignVar(const QString &val)
00401 {
00402         m_pCode->append(new Instr_movf(val,0));
00403 }
00404 
00405 void PIC14::saveToReg(const QString &dest)
00406 {
00407         m_pCode->append(new Instr_movwf(dest));
00408 }
00409 
00410 void PIC14::saveResultToVar( const QString & var )
00411 {
00412         m_pCode->append( new Instr_movwf( var ) );
00413 }
00414 
00415 void PIC14::mul(QString val1, QString val2, LocationType val1Type, LocationType val2Type)
00416 {
00417         multiply();
00418         
00419         rearrangeOpArguments( &val1, &val2, &val1Type, &val2Type );
00420         
00421         // First, set _i argument
00422         switch(val1Type)
00423         {
00424                 case num: m_pCode->append(new Instr_movlw(val1.toInt( 0, 0 ))); break;
00425                 case work: break;
00426                 case var: m_pCode->append(new Instr_movf(val1,0)); break;
00427         }
00428         
00429         m_pCode->append(new Instr_movwf("__i"));
00430         
00431         // Then set _j argument
00432         switch(val2Type)
00433         {
00434                 case num: m_pCode->append(new Instr_movlw(val2.toInt( 0, 0 ))); break;
00435                 case work: break;
00436                 case var: m_pCode->append(new Instr_movf(val2,0)); break;
00437         }
00438         
00439         m_pCode->append(new Instr_movwf("__j"));
00440         m_pCode->append(new Instr_call("__picfunc_multiply"));
00441         m_pCode->append(new Instr_movf("__result",0));
00442 }
00443 
00444 
00445 void PIC14::multiply()
00446 {
00447         if ( m_pCode->instruction("__picfunc_multiply") )
00448                 return;
00449         
00450         m_pCode->queueLabel( "__picfunc_multiply", Code::Subroutine );
00451         m_pCode->append(new Instr_clrf("__result"), Code::Subroutine ); //result+=m_pCode->appenduction("clrf __result");
00452         
00453         m_pCode->queueLabel( "__picfunc_multiply_loop", Code::Subroutine );
00454         m_pCode->append(new Instr_movf("__i",0), Code::Subroutine ); //result+=m_pCode->appenduction("movf __i,0");
00455         m_pCode->append(new Instr_btfsc("__j","0"), Code::Subroutine ); //result+=m_pCode->appenduction("btfsc __j,0");
00456         m_pCode->append(new Instr_addwf("__result",1), Code::Subroutine ); //result+=m_pCode->appenduction("addwf __result,1");
00457         m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); //result+=m_pCode->appenduction("bcf STATUS,C");
00458         m_pCode->append(new Instr_rrf("__j",1), Code::Subroutine ); //result+=m_pCode->appenduction("rrf __j,1");
00459         m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); //result+=m_pCode->appenduction("bcf STATUS,C");
00460         m_pCode->append(new Instr_rlf("__i",1), Code::Subroutine ); //result+=m_pCode->appenduction("rlf __i,1");
00461         m_pCode->append(new Instr_movf("__j",1), Code::Subroutine ); //result+=m_pCode->appenduction("movf __j,1");
00462         m_pCode->append(new Instr_btfss("STATUS","Z"), Code::Subroutine ); //result+=m_pCode->appenduction("btfss STATUS,Z");
00463         m_pCode->append(new Instr_goto("__picfunc_multiply_loop"), Code::Subroutine ); //result+=m_pCode->appenduction("goto __picfunc_multiply_loop");
00464         m_pCode->append(new Instr_return(), Code::Subroutine ); //result+=m_pCode->appenduction("return");
00465 }
00466 
00467 
00468 void PIC14::div( const QString & val1, const QString & val2, LocationType val1Type, LocationType val2Type)
00469 {
00470         divide();
00471         
00472         // NOO - "x / 2" is NOT the same as "2 / x"
00473 //      rearrangeOpArguments( val1, val2, val1Type, val2Type );
00474         
00475         // First, set _i argument
00476         switch(val1Type)
00477         {
00478                 case num: m_pCode->append(new Instr_movlw(val1.toInt( 0, 0 ))); break;
00479                 case work: break;
00480                 case var: m_pCode->append(new Instr_movf(val1,0)); break;
00481         }
00482         
00483         m_pCode->append(new Instr_movwf("__i"));
00484         
00485         // Then set _j argument
00486         switch(val2Type)
00487         {
00488                 case num: m_pCode->append(new Instr_movlw(val2.toInt( 0, 0 ))); break;
00489                 case work: break;
00490                 case var: m_pCode->append(new Instr_movf(val2,0)); break;
00491         }
00492         
00493         m_pCode->append(new Instr_movwf("__j"));
00494 
00495         m_pCode->append(new Instr_call("__picfunc_divide"));//result+=instruction("call __picfunc_divide");
00496         m_pCode->append(new Instr_movf("__result",0));//result+=instruction("movf __result,0");
00497 }
00498 
00499 void PIC14::divide()
00500 {
00501         m_pCode->queueLabel( "__picfunc_divide", Code::Subroutine );
00502         m_pCode->append(new Instr_movf("__j",1), Code::Subroutine );
00503         m_pCode->append(new Instr_btfsc("STATUS","2"), Code::Subroutine );
00504         m_pCode->append(new Instr_return(), Code::Subroutine );
00505         m_pCode->append(new Instr_clrf("__result"), Code::Subroutine );
00506         m_pCode->append(new Instr_movlw(1), Code::Subroutine );
00507         m_pCode->append(new Instr_movwf("__k"), Code::Subroutine );
00508         
00509         m_pCode->queueLabel( "__divide_shift", Code::Subroutine );
00510         m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
00511         m_pCode->append(new Instr_rlf("__k",1), Code::Subroutine );
00512         m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
00513         m_pCode->append(new Instr_rlf("__j",1), Code::Subroutine );
00514         m_pCode->append(new Instr_btfss("__j","7"), Code::Subroutine );
00515         m_pCode->append(new Instr_goto("__divide_shift"), Code::Subroutine );
00516         
00517         m_pCode->queueLabel( "__divide_loop", Code::Subroutine );
00518         m_pCode->append(new Instr_movf("__j",0), Code::Subroutine );
00519         m_pCode->append(new Instr_subwf("__i",1), Code::Subroutine );
00520         m_pCode->append(new Instr_btfsc("STATUS","C"), Code::Subroutine );
00521         m_pCode->append(new Instr_goto("__divide_count"), Code::Subroutine );
00522         m_pCode->append(new Instr_addwf("__i",1), Code::Subroutine );
00523         m_pCode->append(new Instr_goto("__divide_final"), Code::Subroutine );
00524         
00525         m_pCode->queueLabel( "__divide_count", Code::Subroutine );
00526         m_pCode->append(new Instr_movf("__k",0), Code::Subroutine );
00527         m_pCode->append(new Instr_addwf("__result",1), Code::Subroutine );
00528         
00529         m_pCode->queueLabel( "__divide_final", Code::Subroutine );
00530         m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
00531         m_pCode->append(new Instr_rrf("__j",1), Code::Subroutine );
00532         m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
00533         m_pCode->append(new Instr_rrf("__k",1), Code::Subroutine );
00534         m_pCode->append(new Instr_btfss("STATUS","C"), Code::Subroutine );
00535         m_pCode->append(new Instr_goto("__divide_loop"), Code::Subroutine );
00536         m_pCode->append(new Instr_return(), Code::Subroutine );
00537 }
00538 
00539 
00540 Code * PIC14::ifCode()
00541 {
00542         return m_ifCode;
00543 }
00544 
00545 
00546 Code * PIC14::elseCode()
00547 {
00548         return m_elseCode;
00549 }
00550 
00551 
00552 void PIC14::ifInitCode( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
00553 {
00554         // NOO - "x < 2" is NOT the same as "2 < x"
00555 //      rearrangeOpArguments( val1, val2, val1Type, val2Type );
00556         
00557         switch(val1Type)
00558         {
00559                 case num:
00560                         m_pCode->append(new Instr_movlw(val1.toInt( 0, 0 )));
00561                         break;
00562                         
00563                 case work:
00564                         break; // Nothing to do
00565                         
00566                 case var:
00567                         m_pCode->append(new Instr_movf(val1,0));
00568                         break;
00569         }
00570         
00571         switch(val2Type)
00572         {
00573                 case num:
00574                         m_pCode->append(new Instr_sublw(val2.toInt( 0, 0 )));
00575                         break;
00576                         
00577                 case work:
00578                         kdError() << k_funcinfo << "Cannot subtract working from working!" << endl;
00579                         break;
00580                         
00581                 case var:
00582                         m_pCode->append(new Instr_subwf(val2,0));
00583                         break;
00584         }
00585 }
00586 
00587 void PIC14::equal( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
00588 {
00589         ifInitCode( val1, val2, val1Type, val2Type );
00590         const QString labelEnd = mb->uniqueLabel()+"_endif";
00591         const QString labelFalse = mb->uniqueLabel()+"_case_false";
00592         
00593         m_pCode->append(new Instr_btfss("STATUS","2"));
00594         m_pCode->append(new Instr_goto(labelFalse));
00595         
00596         mergeCode( ifCode() );
00597         
00598         m_pCode->append(new Instr_goto(labelEnd));
00599         
00600         m_pCode->queueLabel( labelFalse );
00601         mergeCode( elseCode() );
00602         m_pCode->queueLabel( labelEnd );
00603 }
00604 
00605 void PIC14::notEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
00606 {
00607         ifInitCode( val1, val2, val1Type, val2Type );
00608         const QString labelEnd = mb->uniqueLabel()+"_endif";
00609         const QString labelFalse = mb->uniqueLabel()+"_case_false";
00610         
00611         m_pCode->append(new Instr_btfsc("STATUS","2"));
00612         m_pCode->append(new Instr_goto(labelFalse));
00613         
00614         mergeCode( ifCode() );
00615         
00616         m_pCode->append(new Instr_goto(labelEnd));
00617         
00618         m_pCode->queueLabel( labelFalse );
00619         mergeCode( elseCode() );
00620         m_pCode->queueLabel( labelEnd );
00621 }
00622 
00623 void PIC14::greaterThan( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
00624 {
00625         ifInitCode( val1, val2, val1Type, val2Type );
00626         const QString labelEnd = mb->uniqueLabel()+"_endif";
00627         const QString labelFalse = mb->uniqueLabel()+"_case_false";
00628         
00629         m_pCode->append(new Instr_btfsc("STATUS","0"));
00630         m_pCode->append(new Instr_goto(labelFalse));
00631         
00632         mergeCode( ifCode() );
00633         m_pCode->append(new Instr_goto(labelEnd));
00634         
00635         m_pCode->queueLabel( labelFalse );
00636         mergeCode( elseCode() );
00637         m_pCode->queueLabel( labelEnd );
00638 }
00639 
00640 void PIC14::lessThan( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
00641 {
00642         cout << k_funcinfo << endl;
00643         ifInitCode( val1, val2, val1Type, val2Type );
00644         const QString labelEnd = mb->uniqueLabel()+"_endif";
00645         const QString labelFalse = mb->uniqueLabel()+"_case_false";
00646         
00647         m_pCode->append(new Instr_btfss("STATUS","0"));
00648         m_pCode->append(new Instr_goto(labelFalse));
00649         m_pCode->append(new Instr_btfsc("STATUS","2"));
00650         m_pCode->append(new Instr_goto(labelFalse));
00651         
00652         mergeCode( ifCode() );
00653         
00654         m_pCode->append(new Instr_goto(labelEnd));
00655         
00656         m_pCode->queueLabel( labelFalse );
00657         mergeCode( elseCode() );
00658         m_pCode->queueLabel( labelEnd );
00659 }
00660 
00661 void PIC14::greaterOrEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
00662 {
00663         ifInitCode( val1, val2, val1Type, val2Type );
00664         const QString labelEnd = mb->uniqueLabel()+"_endif";
00665         const QString labelTrue = mb->uniqueLabel()+"_case_true"; // Note that unlike the others, this is labelTrue, not labelFalse
00666         
00667         m_pCode->append(new Instr_btfsc("STATUS","2"));
00668         m_pCode->append(new Instr_goto(labelTrue));
00669         m_pCode->append(new Instr_btfss("STATUS","0"));
00670         m_pCode->append(new Instr_goto(labelTrue));
00671         
00672         mergeCode( elseCode() );
00673         
00674         m_pCode->append(new Instr_goto(labelEnd));
00675         
00676         m_pCode->queueLabel( labelTrue );
00677         mergeCode( ifCode() );
00678         m_pCode->queueLabel( labelEnd );
00679 }
00680 
00681 void PIC14::lessOrEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
00682 {
00683         ifInitCode( val1, val2, val1Type, val2Type );
00684         const QString labelEnd = mb->uniqueLabel()+"_endif";
00685         const QString labelFalse = mb->uniqueLabel()+"_case_false";
00686         
00687         m_pCode->append(new Instr_btfss("STATUS","0"));
00688         m_pCode->append(new Instr_goto(labelFalse));
00689         
00690         mergeCode( ifCode() );
00691         m_pCode->append(new Instr_goto(labelEnd));
00692         
00693         m_pCode->queueLabel( labelFalse );
00694         mergeCode( elseCode() );
00695         m_pCode->queueLabel( labelEnd );
00696 }
00697 
00698 
00699 void PIC14::Swhile( Code * whileCode, const QString &expression)
00700 {
00701         QString result;
00702         QString ul = mb->uniqueLabel();
00703         
00704         whileCode->append( new Instr_goto(ul) );
00705         
00706         m_pCode->queueLabel( ul, Code::Middle );
00707         
00708         // If the condition is not true, just fall through
00709         m_parser->compileConditionalExpression( expression, whileCode, 0 );
00710 }
00711 
00712 
00713 void PIC14::Srepeat( Code * repeatCode, const QString &expression)
00714 {
00715         QString result;
00716         QString ul = mb->uniqueLabel();
00717         
00718         Code * elseCode = new Code;
00719         elseCode->append( new Instr_goto(ul) );
00720         
00721         m_pCode->queueLabel( ul );
00722         m_pCode->merge( repeatCode );
00723         
00724         // If the condition is true, just fall through
00725         m_parser->compileConditionalExpression( expression, 0, elseCode );
00726 }
00727 
00728 void PIC14::Sif( Code * ifCode, Code * elseCode, const QString &expression)
00729 {
00730         m_parser->compileConditionalExpression( expression, ifCode, elseCode );
00731 }
00732 
00733 
00734 void PIC14::Sfor( Code * forCode, Code * initCode, const QString &expression, const QString &variable, const QString &step, bool stepPositive)
00735 {
00736         QString ul = mb->uniqueLabel();
00737         
00738         if ( step == "1" )
00739         {
00740                 if (stepPositive)
00741                         forCode->append(new Instr_incf(variable,1));
00742                 else
00743                         forCode->append(new Instr_decf(variable,1));
00744         }
00745         else
00746         {
00747                 forCode->append(new Instr_movlw(step.toInt( 0, 0 )));
00748                 if (stepPositive)
00749                         forCode->append(new Instr_addwf(variable,1));
00750                 else
00751                         forCode->append(new Instr_subwf(variable,1));
00752         }
00753         forCode->append(new Instr_goto(ul));
00754         
00755         m_pCode->merge( initCode );
00756         
00757         m_pCode->queueLabel( ul );
00758 
00759         m_parser->compileConditionalExpression( expression, forCode, 0 );
00760 }
00761 
00762 
00763 void PIC14::Spin( const PortPin & portPin, bool NOT)
00764 {
00765         QString lowLabel, highLabel, postLabel;
00766         lowLabel = mb->uniqueLabel();
00767         highLabel = mb->uniqueLabel();
00768         postLabel = mb->uniqueLabel();
00769         /*result += indent + "goto\t" + lowLabel; 
00770         result += indent + "movlw\t1" + "goto\t"+postLabel+;
00771         result += lowLabel +  + indent + "movlw\t0" + indent;
00772         result += postLabel + ;*/
00773         
00774         if(NOT)
00775                 m_pCode->append(new Instr_btfsc( portPin.port(), QString::number( portPin.pin() ) ));
00776         //result +=instruction((QString)(NOT?"btfsc":"btfss")+"\t"+port+","+pin);
00777         else
00778                 m_pCode->append(new Instr_btfss( portPin.port(), QString::number( portPin.pin() ) ));
00779         
00780         m_pCode->append(new Instr_goto(lowLabel));//result += instruction("goto\t" + lowLabel); 
00781         mergeCode( ifCode() );
00782         m_pCode->append(new Instr_goto(postLabel));//result += instruction("goto\t"+postLabel);
00783         
00784         m_pCode->queueLabel( lowLabel );
00785         mergeCode( elseCode() );
00786         
00787         m_pCode->queueLabel( postLabel );
00788 }
00789 
00790 
00791 void PIC14::Sdelay( unsigned length_us, Code::InstructionPosition pos )
00792 {
00793         if ( length_us == 0 )
00794                 return;
00795         
00796         if ( length_us > 50070524 )
00797         {
00798                 length_us += 50267642;
00799                 int l = length_us/50070530;
00800                 length_us -= l * 50070530;
00801                 int k = length_us/196355;
00802                 
00803                 m_pCode->append( new Instr_movlw( l ), pos );
00804                 m_pCode->append( new Instr_movwf( "__l" ), pos );
00805                 m_pCode->append( new Instr_movlw( k ), pos );
00806                 m_pCode->append( new Instr_movwf( "__k" ), pos );
00807                 
00808                 mb->addDelayRoutineWanted( Delay_50S );
00809         }
00810         
00811         else if ( length_us > 196350 )
00812         {
00813                 length_us += 197116;
00814                 int k = length_us/196355;
00815                 length_us -= k * 196355;
00816                 int j = length_us/770;
00817