1 /*-------------------------------------------------------------------------
2 genarith.c - source file for code generation - arithmetic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
40 #define __FUNCTION__ __FILE__
43 #ifdef HAVE_SYS_ISA_DEFS_H
44 #include <sys/isa_defs.h>
49 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__)
50 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
51 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
57 #include "SDCCpeeph.h"
62 /*-----------------------------------------------------------------*/
63 /* genPlusIncr :- does addition with increment if possible */
64 /*-----------------------------------------------------------------*/
65 bool genPlusIncr (iCode *ic)
68 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
70 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
71 DEBUGpic14_emitcode ("; ","result %d, left %d, right %d",
72 AOP_TYPE(IC_RESULT(ic)),
73 AOP_TYPE(IC_LEFT(ic)),
74 AOP_TYPE(IC_RIGHT(ic)));
76 /* will try to generate an increment */
77 /* if the right side is not a literal
79 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
82 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
83 /* if the literal value of the right hand side
84 is greater than 1 then it is faster to add */
85 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
88 /* if increment 16 bits in register */
89 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
94 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
95 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
99 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
100 //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
106 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
107 /* if left is in accumulator - probably a bit operation*/
108 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
109 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
111 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
112 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
113 AOP(IC_RESULT(ic))->aopu.aop_dir,
114 AOP(IC_RESULT(ic))->aopu.aop_dir);
116 emitpcode(POC_XORLW,popGetLit(1));
117 //pic14_emitcode("xorlw","1");
119 emitpcode(POC_ANDLW,popGetLit(1));
120 //pic14_emitcode("andlw","1");
123 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
124 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
125 AOP(IC_RESULT(ic))->aopu.aop_dir,
126 AOP(IC_RESULT(ic))->aopu.aop_dir);
133 /* if the sizes are greater than 1 then we cannot */
134 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
135 AOP_SIZE(IC_LEFT(ic)) > 1 )
138 /* If we are incrementing the same register by two: */
140 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
143 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
144 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
149 DEBUGpic14_emitcode ("; ","couldn't increment result-%s left-%s",
150 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
151 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
155 /*-----------------------------------------------------------------*/
156 /* pic14_outBitAcc - output a bit in acc */
157 /*-----------------------------------------------------------------*/
158 void pic14_outBitAcc(operand *result)
160 symbol *tlbl = newiTempLabel(NULL);
161 /* if the result is a bit */
162 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
164 if (AOP_TYPE(result) == AOP_CRY){
165 aopPut(AOP(result),"a",0);
168 pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
169 pic14_emitcode("mov","a,#01");
170 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
171 pic14_outAcc(result);
175 /*-----------------------------------------------------------------*/
176 /* genPlusBits - generates code for addition of two bits */
177 /*-----------------------------------------------------------------*/
178 void genPlusBits (iCode *ic)
181 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
183 The following block of code will add two bits.
184 Note that it'll even work if the destination is
185 the carry (C in the status register).
186 It won't work if the 'Z' bit is a source or destination.
189 /* If the result is stored in the accumulator (w) */
190 //if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
191 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
192 //emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
193 // popGet(AOP(result),0,FALSE,FALSE));
195 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
196 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
197 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
198 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
199 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
200 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
202 pic14_emitcode("movlw","(1 << (%s & 7))",
203 AOP(IC_RESULT(ic))->aopu.aop_dir,
204 AOP(IC_RESULT(ic))->aopu.aop_dir);
205 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
206 AOP(IC_RESULT(ic))->aopu.aop_dir,
207 AOP(IC_RESULT(ic))->aopu.aop_dir);
208 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
209 AOP(IC_RIGHT(ic))->aopu.aop_dir,
210 AOP(IC_RIGHT(ic))->aopu.aop_dir);
211 pic14_emitcode("xorwf","(%s >>3),f",
212 AOP(IC_RESULT(ic))->aopu.aop_dir);
213 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
214 AOP(IC_LEFT(ic))->aopu.aop_dir,
215 AOP(IC_LEFT(ic))->aopu.aop_dir);
216 pic14_emitcode("xorwf","(%s>>3),f",
217 AOP(IC_RESULT(ic))->aopu.aop_dir);
220 emitpcode(POC_CLRW, NULL);
221 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
222 emitpcode(POC_XORLW, popGetLit(1));
223 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
224 emitpcode(POC_XORLW, popGetLit(1));
226 pic14_emitcode("clrw","");
227 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
228 AOP(IC_RIGHT(ic))->aopu.aop_dir,
229 AOP(IC_RIGHT(ic))->aopu.aop_dir);
230 pic14_emitcode("xorlw","1");
231 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
232 AOP(IC_LEFT(ic))->aopu.aop_dir,
233 AOP(IC_LEFT(ic))->aopu.aop_dir);
234 pic14_emitcode("xorlw","1");
240 /* This is the original version of this code.
242 * This is being kept around for reference,
243 * because I am not entirely sure I got it right...
245 static void adjustArithmeticResult(iCode *ic)
247 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
248 AOP_SIZE(IC_LEFT(ic)) == 3 &&
249 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
250 aopPut(AOP(IC_RESULT(ic)),
251 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
254 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
255 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
256 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
257 aopPut(AOP(IC_RESULT(ic)),
258 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
261 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
262 AOP_SIZE(IC_LEFT(ic)) < 3 &&
263 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
264 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
265 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
267 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
268 aopPut(AOP(IC_RESULT(ic)),buffer,2);
272 /* This is the pure and virtuous version of this code.
273 * I'm pretty certain it's right, but not enough to toss the old
276 static void adjustArithmeticResult(iCode *ic)
278 if (opIsGptr(IC_RESULT(ic)) &&
279 opIsGptr(IC_LEFT(ic)) &&
280 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
282 aopPut(AOP(IC_RESULT(ic)),
283 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
287 if (opIsGptr(IC_RESULT(ic)) &&
288 opIsGptr(IC_RIGHT(ic)) &&
289 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
291 aopPut(AOP(IC_RESULT(ic)),
292 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
296 if (opIsGptr(IC_RESULT(ic)) &&
297 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
298 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
299 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
300 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
302 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
303 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
308 /*-----------------------------------------------------------------*/
309 /* genPlus - generates code for addition */
310 /*-----------------------------------------------------------------*/
311 void genPlus (iCode *ic)
313 int size, offset = 0;
315 /* special cases :- */
316 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
318 aopOp (IC_LEFT(ic),ic,FALSE);
319 aopOp (IC_RIGHT(ic),ic,FALSE);
320 aopOp (IC_RESULT(ic),ic,TRUE);
322 /* if literal, literal on the right or
323 if left requires ACC or right is already
326 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
327 operand *t = IC_RIGHT(ic);
328 IC_RIGHT(ic) = IC_LEFT(ic);
332 /* if both left & right are in bit space */
333 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
334 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
339 /* if left in bit space & right literal */
340 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
341 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
342 /* if result in bit space */
343 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
344 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
345 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
346 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
347 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
348 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
351 size = pic14_getDataSize(IC_RESULT(ic));
353 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
354 pic14_emitcode("addc","a,#00 ;%d",__LINE__);
355 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
361 /* if I can do an increment instead
362 of add then GOOD for ME */
363 if (genPlusIncr (ic) == TRUE)
366 size = pic14_getDataSize(IC_RESULT(ic));
368 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
369 /* Add a literal to something else */
371 unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
375 DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
378 DEBUGpic14_emitcode(";","size %d",size);
380 switch (lit & 0xff) {
384 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
385 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
388 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
389 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
390 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
394 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
395 emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
398 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
399 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
400 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
404 if( !know_W || ( (lit&0xff) != l1) ) {
406 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
408 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
409 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
412 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
413 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
416 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
426 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
428 pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
429 pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
430 pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
432 /* here we are adding a bit to a char or int */
434 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
436 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
437 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
439 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
440 AOP(IC_RIGHT(ic))->aopu.aop_dir,
441 AOP(IC_RIGHT(ic))->aopu.aop_dir);
442 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
445 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
446 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
447 emitpcode(POC_XORLW , popGetLit(1));
449 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
450 AOP(IC_RIGHT(ic))->aopu.aop_dir,
451 AOP(IC_RIGHT(ic))->aopu.aop_dir);
452 pic14_emitcode(" xorlw","1");
454 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
455 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
456 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
458 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
459 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
460 AOP(IC_RIGHT(ic))->aopu.aop_dir,
461 AOP(IC_RIGHT(ic))->aopu.aop_dir);
462 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
465 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
467 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
468 emitpcode(POC_ANDLW , popGetLit(1));
469 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
471 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
473 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
474 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
482 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
484 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
485 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
487 pic14_emitcode("clrz","");
489 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
490 AOP(IC_RIGHT(ic))->aopu.aop_dir,
491 AOP(IC_RIGHT(ic))->aopu.aop_dir);
492 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
496 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
497 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
498 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
499 emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
502 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
503 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
504 AOP(IC_RIGHT(ic))->aopu.aop_dir,
505 AOP(IC_RIGHT(ic))->aopu.aop_dir);
506 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
507 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
513 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
514 //pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
521 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
522 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
523 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
526 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
527 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
528 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
529 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
532 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
534 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
535 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
537 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
538 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
539 emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
541 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
542 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
543 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
553 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
554 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
555 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
557 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
558 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
561 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
563 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
564 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
567 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
569 pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
570 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
578 //adjustArithmeticResult(ic);
581 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
582 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
583 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
586 /*-----------------------------------------------------------------*/
587 /* genMinusDec :- does subtraction with decrement if possible */
588 /*-----------------------------------------------------------------*/
589 bool genMinusDec (iCode *ic)
591 unsigned int icount ;
592 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
594 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
595 /* will try to generate an increment */
596 /* if the right side is not a literal
598 if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) ||
599 (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) ||
600 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
603 DEBUGpic14_emitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
605 /* if the literal value of the right hand side
606 is greater than 4 then it is not worth it */
607 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
610 /* if decrement 16 bits in register */
611 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
616 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
617 emitpcode(POC_INCFSZW, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
618 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
620 pic14_emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
621 pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
622 pic14_emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
625 emitpcode(POC_MOVLW, popGetLit(0xff));
626 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
628 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
630 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
632 pic14_emitcode("movlw","0xff");
633 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
636 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
638 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
642 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
644 pic14_emitcode("skpnc","");
646 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
655 /* if the sizes are greater than 1 then we cannot */
656 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
657 AOP_SIZE(IC_LEFT(ic)) > 1 )
660 /* we can if the aops of the left & result match or
661 if they are in registers and the registers are the
663 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
666 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
668 //pic14_emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
673 DEBUGpic14_emitcode ("; returning"," result=%s, left=%s",
674 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
675 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
678 pic14_emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
679 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
681 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
682 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
690 /*-----------------------------------------------------------------*/
691 /* addSign - complete with sign */
692 /*-----------------------------------------------------------------*/
693 void addSign(operand *result, int offset, int sign)
695 int size = (pic14_getDataSize(result) - offset);
696 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
699 pic14_emitcode("rlc","a");
700 pic14_emitcode("subb","a,acc");
702 aopPut(AOP(result),"a",offset++);
705 aopPut(AOP(result),"#0",offset++);
709 /*-----------------------------------------------------------------*/
710 /* genMinusBits - generates code for subtraction of two bits */
711 /*-----------------------------------------------------------------*/
712 void genMinusBits (iCode *ic)
714 symbol *lbl = newiTempLabel(NULL);
715 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
716 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
717 pic14_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
718 pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
719 pic14_emitcode("cpl","c");
720 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
721 pic14_outBitC(IC_RESULT(ic));
724 pic14_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
725 pic14_emitcode("subb","a,acc");
726 pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
727 pic14_emitcode("inc","a");
728 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
729 aopPut(AOP(IC_RESULT(ic)),"a",0);
730 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
734 /*-----------------------------------------------------------------*/
735 /* genMinus - generates code for subtraction */
736 /*-----------------------------------------------------------------*/
737 void genMinus (iCode *ic)
739 int size, offset = 0;
740 unsigned long lit = 0L;
742 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
743 aopOp (IC_LEFT(ic),ic,FALSE);
744 aopOp (IC_RIGHT(ic),ic,FALSE);
745 aopOp (IC_RESULT(ic),ic,TRUE);
747 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
748 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
749 operand *t = IC_RIGHT(ic);
750 IC_RIGHT(ic) = IC_LEFT(ic);
754 /* special cases :- */
755 /* if both left & right are in bit space */
756 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
757 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
762 /* if I can do an decrement instead
763 of subtract then GOOD for ME */
764 if (genMinusDec (ic) == TRUE)
767 size = pic14_getDataSize(IC_RESULT(ic));
769 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
770 /* Add a literal to something else */
772 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
775 /* add the first byte: */
776 pic14_emitcode("movlw","0x%x", lit & 0xff);
777 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
778 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
779 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
791 if((lit & 0xff) == 0xff) {
792 emitpcode(POC_MOVLW, popGetLit(0xff));
794 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
796 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
798 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
799 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
803 /* do the rlf known zero trick here */
804 emitpcode(POC_MOVLW, popGetLit(1));
806 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
811 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
814 pic14_emitcode(";bitsub","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
815 pic14_emitcode(";bitsub","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
816 pic14_emitcode(";bitsub","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
818 /* here we are subtracting a bit from a char or int */
820 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
822 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
823 emitpcode(POC_DECF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
825 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
826 AOP(IC_RIGHT(ic))->aopu.aop_dir,
827 AOP(IC_RIGHT(ic))->aopu.aop_dir);
828 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
831 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
832 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
833 emitpcode(POC_XORLW , popGetLit(1));
834 }else if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
835 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
837 lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
839 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
840 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
842 emitpcode(POC_MOVLW , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
843 emitpcode(POC_XORWF , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
846 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
848 emitpcode(POC_BTFSS , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
850 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
851 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
855 emitpcode(POC_MOVLW , popGetLit(lit & 0xff));
856 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
857 emitpcode(POC_MOVLW , popGetLit((lit-1) & 0xff));
858 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
863 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
864 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
865 emitpcode(POC_DECFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
868 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
870 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
873 emitpcode(POC_ANDLW , popGetLit(1));
875 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
877 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
886 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
887 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
888 emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
889 emitpcode(POC_SUBLW, popGetLit(0));
890 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
893 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
894 emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
895 emitpcode(POC_SUBLW, popGetLit(0));
896 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
897 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
900 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
901 if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)
902 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
904 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
905 emitpcode(POC_SUBWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
907 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
908 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
909 emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
911 emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
913 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
914 if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
915 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
917 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
919 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
926 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
928 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
929 emitpcode(POC_SUBFW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
931 emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
932 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
939 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
940 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
941 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
943 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
945 emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
946 emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
954 // adjustArithmeticResult(ic);
957 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
958 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
959 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);