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>
46 #ifdef HAVE_MACHINE_ENDIAN_H
47 #include <machine/endian.h>
52 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
53 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
54 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
61 #include "SDCCpeeph.h"
66 /*-----------------------------------------------------------------*/
67 /* genPlusIncr :- does addition with increment if possible */
68 /*-----------------------------------------------------------------*/
69 bool genPlusIncr (iCode *ic)
72 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
74 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
75 DEBUGpic14_emitcode ("; ","result %d, left %d, right %d",
76 AOP_TYPE(IC_RESULT(ic)),
77 AOP_TYPE(IC_LEFT(ic)),
78 AOP_TYPE(IC_RIGHT(ic)));
80 /* will try to generate an increment */
81 /* if the right side is not a literal
83 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
86 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
87 /* if the literal value of the right hand side
88 is greater than 1 then it is faster to add */
89 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
92 /* if increment 16 bits in register */
93 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
98 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
99 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
103 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
104 //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
110 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
111 /* if left is in accumulator - probably a bit operation*/
112 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
113 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
115 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
116 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
117 AOP(IC_RESULT(ic))->aopu.aop_dir,
118 AOP(IC_RESULT(ic))->aopu.aop_dir);
120 emitpcode(POC_XORLW,popGetLit(1));
121 //pic14_emitcode("xorlw","1");
123 emitpcode(POC_ANDLW,popGetLit(1));
124 //pic14_emitcode("andlw","1");
127 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
128 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
129 AOP(IC_RESULT(ic))->aopu.aop_dir,
130 AOP(IC_RESULT(ic))->aopu.aop_dir);
137 /* if the sizes are greater than 1 then we cannot */
138 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
139 AOP_SIZE(IC_LEFT(ic)) > 1 )
142 /* If we are incrementing the same register by two: */
144 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
147 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
148 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
153 DEBUGpic14_emitcode ("; ","couldn't increment result-%s left-%s",
154 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
155 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
159 /*-----------------------------------------------------------------*/
160 /* pic14_outBitAcc - output a bit in acc */
161 /*-----------------------------------------------------------------*/
162 void pic14_outBitAcc(operand *result)
164 symbol *tlbl = newiTempLabel(NULL);
165 /* if the result is a bit */
166 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
168 if (AOP_TYPE(result) == AOP_CRY){
169 aopPut(AOP(result),"a",0);
172 pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
173 pic14_emitcode("mov","a,#01");
174 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
175 pic14_outAcc(result);
179 /*-----------------------------------------------------------------*/
180 /* genPlusBits - generates code for addition of two bits */
181 /*-----------------------------------------------------------------*/
182 void genPlusBits (iCode *ic)
185 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
187 The following block of code will add two bits.
188 Note that it'll even work if the destination is
189 the carry (C in the status register).
190 It won't work if the 'Z' bit is a source or destination.
193 /* If the result is stored in the accumulator (w) */
194 //if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
195 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
196 //emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
197 // popGet(AOP(result),0,FALSE,FALSE));
199 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
200 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
201 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
202 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
203 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
204 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
206 pic14_emitcode("movlw","(1 << (%s & 7))",
207 AOP(IC_RESULT(ic))->aopu.aop_dir,
208 AOP(IC_RESULT(ic))->aopu.aop_dir);
209 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
210 AOP(IC_RESULT(ic))->aopu.aop_dir,
211 AOP(IC_RESULT(ic))->aopu.aop_dir);
212 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
213 AOP(IC_RIGHT(ic))->aopu.aop_dir,
214 AOP(IC_RIGHT(ic))->aopu.aop_dir);
215 pic14_emitcode("xorwf","(%s >>3),f",
216 AOP(IC_RESULT(ic))->aopu.aop_dir);
217 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
218 AOP(IC_LEFT(ic))->aopu.aop_dir,
219 AOP(IC_LEFT(ic))->aopu.aop_dir);
220 pic14_emitcode("xorwf","(%s>>3),f",
221 AOP(IC_RESULT(ic))->aopu.aop_dir);
224 emitpcode(POC_CLRW, NULL);
225 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
226 emitpcode(POC_XORLW, popGetLit(1));
227 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
228 emitpcode(POC_XORLW, popGetLit(1));
230 pic14_emitcode("clrw","");
231 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
232 AOP(IC_RIGHT(ic))->aopu.aop_dir,
233 AOP(IC_RIGHT(ic))->aopu.aop_dir);
234 pic14_emitcode("xorlw","1");
235 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
236 AOP(IC_LEFT(ic))->aopu.aop_dir,
237 AOP(IC_LEFT(ic))->aopu.aop_dir);
238 pic14_emitcode("xorlw","1");
244 /* This is the original version of this code.
246 * This is being kept around for reference,
247 * because I am not entirely sure I got it right...
249 static void adjustArithmeticResult(iCode *ic)
251 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
252 AOP_SIZE(IC_LEFT(ic)) == 3 &&
253 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
254 aopPut(AOP(IC_RESULT(ic)),
255 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
258 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
259 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
260 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
261 aopPut(AOP(IC_RESULT(ic)),
262 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
265 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
266 AOP_SIZE(IC_LEFT(ic)) < 3 &&
267 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
268 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
269 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
271 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
272 aopPut(AOP(IC_RESULT(ic)),buffer,2);
276 /* This is the pure and virtuous version of this code.
277 * I'm pretty certain it's right, but not enough to toss the old
280 static void adjustArithmeticResult(iCode *ic)
282 if (opIsGptr(IC_RESULT(ic)) &&
283 opIsGptr(IC_LEFT(ic)) &&
284 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
286 aopPut(AOP(IC_RESULT(ic)),
287 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
291 if (opIsGptr(IC_RESULT(ic)) &&
292 opIsGptr(IC_RIGHT(ic)) &&
293 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
295 aopPut(AOP(IC_RESULT(ic)),
296 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
300 if (opIsGptr(IC_RESULT(ic)) &&
301 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
302 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
303 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
304 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
306 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
307 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
312 /*-----------------------------------------------------------------*/
313 /* genPlus - generates code for addition */
314 /*-----------------------------------------------------------------*/
315 void genPlus (iCode *ic)
317 int size, offset = 0;
319 /* special cases :- */
320 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
322 aopOp (IC_LEFT(ic),ic,FALSE);
323 aopOp (IC_RIGHT(ic),ic,FALSE);
324 aopOp (IC_RESULT(ic),ic,TRUE);
326 /* if literal, literal on the right or
327 if left requires ACC or right is already
330 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
331 operand *t = IC_RIGHT(ic);
332 IC_RIGHT(ic) = IC_LEFT(ic);
336 /* if both left & right are in bit space */
337 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
338 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
343 /* if left in bit space & right literal */
344 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
345 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
346 /* if result in bit space */
347 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
348 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
349 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
350 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
351 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
352 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
355 size = pic14_getDataSize(IC_RESULT(ic));
357 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
358 pic14_emitcode("addc","a,#00 ;%d",__LINE__);
359 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
365 /* if I can do an increment instead
366 of add then GOOD for ME */
367 if (genPlusIncr (ic) == TRUE)
370 size = pic14_getDataSize(IC_RESULT(ic));
372 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
373 /* Add a literal to something else */
375 unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
379 DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
382 DEBUGpic14_emitcode(";","size %d",size);
384 switch (lit & 0xff) {
388 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
389 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
392 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
393 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
394 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
398 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
399 emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
402 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
403 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
404 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
408 if( !know_W || ( (lit&0xff) != l1) ) {
410 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
412 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
413 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
416 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
417 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
420 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
430 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
432 pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
433 pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
434 pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
436 /* here we are adding a bit to a char or int */
438 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
440 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
441 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
443 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
444 AOP(IC_RIGHT(ic))->aopu.aop_dir,
445 AOP(IC_RIGHT(ic))->aopu.aop_dir);
446 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
449 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
450 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
451 emitpcode(POC_XORLW , popGetLit(1));
453 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
454 AOP(IC_RIGHT(ic))->aopu.aop_dir,
455 AOP(IC_RIGHT(ic))->aopu.aop_dir);
456 pic14_emitcode(" xorlw","1");
458 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
459 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
460 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
462 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
463 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
464 AOP(IC_RIGHT(ic))->aopu.aop_dir,
465 AOP(IC_RIGHT(ic))->aopu.aop_dir);
466 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
469 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
471 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
472 emitpcode(POC_ANDLW , popGetLit(1));
473 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
475 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
477 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
478 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
486 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
488 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
489 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
491 pic14_emitcode("clrz","");
493 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
494 AOP(IC_RIGHT(ic))->aopu.aop_dir,
495 AOP(IC_RIGHT(ic))->aopu.aop_dir);
496 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
500 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
501 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
502 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
503 emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
506 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
507 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
508 AOP(IC_RIGHT(ic))->aopu.aop_dir,
509 AOP(IC_RIGHT(ic))->aopu.aop_dir);
510 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
511 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
517 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
518 //pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
525 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
526 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
527 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
530 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
531 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
532 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
533 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
536 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
538 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
539 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
541 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
542 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
543 emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
545 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
546 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
547 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
557 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
558 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
559 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
561 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
562 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
565 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
567 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
568 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
571 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
573 pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
574 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
582 //adjustArithmeticResult(ic);
585 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
586 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
587 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
590 /*-----------------------------------------------------------------*/
591 /* genMinusDec :- does subtraction with decrement if possible */
592 /*-----------------------------------------------------------------*/
593 bool genMinusDec (iCode *ic)
595 unsigned int icount ;
596 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
598 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
599 /* will try to generate an increment */
600 /* if the right side is not a literal
602 if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) ||
603 (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) ||
604 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
607 DEBUGpic14_emitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
609 /* if the literal value of the right hand side
610 is greater than 4 then it is not worth it */
611 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
614 /* if decrement 16 bits in register */
615 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
620 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
621 emitpcode(POC_INCFSZW, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
622 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
624 pic14_emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
625 pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
626 pic14_emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
629 emitpcode(POC_MOVLW, popGetLit(0xff));
630 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
632 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
634 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
636 pic14_emitcode("movlw","0xff");
637 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
640 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
642 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
646 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
648 pic14_emitcode("skpnc","");
650 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
659 /* if the sizes are greater than 1 then we cannot */
660 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
661 AOP_SIZE(IC_LEFT(ic)) > 1 )
664 /* we can if the aops of the left & result match or
665 if they are in registers and the registers are the
667 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
670 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
672 //pic14_emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
677 DEBUGpic14_emitcode ("; returning"," result=%s, left=%s",
678 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
679 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
682 pic14_emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
683 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
685 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
686 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
694 /*-----------------------------------------------------------------*/
695 /* addSign - complete with sign */
696 /*-----------------------------------------------------------------*/
697 void addSign(operand *result, int offset, int sign)
699 int size = (pic14_getDataSize(result) - offset);
700 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
703 pic14_emitcode("rlc","a");
704 pic14_emitcode("subb","a,acc");
706 aopPut(AOP(result),"a",offset++);
709 aopPut(AOP(result),"#0",offset++);
713 /*-----------------------------------------------------------------*/
714 /* genMinusBits - generates code for subtraction of two bits */
715 /*-----------------------------------------------------------------*/
716 void genMinusBits (iCode *ic)
718 symbol *lbl = newiTempLabel(NULL);
719 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
720 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
721 pic14_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
722 pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
723 pic14_emitcode("cpl","c");
724 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
725 pic14_outBitC(IC_RESULT(ic));
728 pic14_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
729 pic14_emitcode("subb","a,acc");
730 pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
731 pic14_emitcode("inc","a");
732 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
733 aopPut(AOP(IC_RESULT(ic)),"a",0);
734 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
738 /*-----------------------------------------------------------------*/
739 /* genMinus - generates code for subtraction */
740 /*-----------------------------------------------------------------*/
741 void genMinus (iCode *ic)
743 int size, offset = 0;
744 unsigned long lit = 0L;
746 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
747 aopOp (IC_LEFT(ic),ic,FALSE);
748 aopOp (IC_RIGHT(ic),ic,FALSE);
749 aopOp (IC_RESULT(ic),ic,TRUE);
751 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
752 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
753 operand *t = IC_RIGHT(ic);
754 IC_RIGHT(ic) = IC_LEFT(ic);
758 /* special cases :- */
759 /* if both left & right are in bit space */
760 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
761 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
766 /* if I can do an decrement instead
767 of subtract then GOOD for ME */
768 if (genMinusDec (ic) == TRUE)
771 size = pic14_getDataSize(IC_RESULT(ic));
773 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
774 /* Add a literal to something else */
776 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
779 /* add the first byte: */
780 pic14_emitcode("movlw","0x%x", lit & 0xff);
781 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
782 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
783 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
795 if((lit & 0xff) == 0xff) {
796 emitpcode(POC_MOVLW, popGetLit(0xff));
798 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
800 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
802 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
803 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
807 /* do the rlf known zero trick here */
808 emitpcode(POC_MOVLW, popGetLit(1));
810 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
815 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
818 pic14_emitcode(";bitsub","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
819 pic14_emitcode(";bitsub","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
820 pic14_emitcode(";bitsub","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
822 /* here we are subtracting a bit from a char or int */
824 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
826 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
827 emitpcode(POC_DECF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
829 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
830 AOP(IC_RIGHT(ic))->aopu.aop_dir,
831 AOP(IC_RIGHT(ic))->aopu.aop_dir);
832 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
835 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
836 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
837 emitpcode(POC_XORLW , popGetLit(1));
838 }else if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
839 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
841 lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
843 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
844 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
846 emitpcode(POC_MOVLW , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
847 emitpcode(POC_XORWF , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
850 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
852 emitpcode(POC_BTFSS , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
854 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
855 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
859 emitpcode(POC_MOVLW , popGetLit(lit & 0xff));
860 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
861 emitpcode(POC_MOVLW , popGetLit((lit-1) & 0xff));
862 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
867 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
868 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
869 emitpcode(POC_DECFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
872 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
874 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
877 emitpcode(POC_ANDLW , popGetLit(1));
879 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
881 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
890 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
891 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
892 emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
893 emitpcode(POC_SUBLW, popGetLit(0));
894 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
897 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
898 emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
899 emitpcode(POC_SUBLW, popGetLit(0));
900 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
901 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
904 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
905 if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)
906 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
908 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
909 emitpcode(POC_SUBWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
911 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
912 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
913 emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
915 emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
917 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
918 if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
919 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
921 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
923 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
930 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
932 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
933 emitpcode(POC_SUBFW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
935 emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
936 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
943 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
944 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
945 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
947 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
949 emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
950 emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
958 // adjustArithmeticResult(ic);
961 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
962 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
963 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);