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)
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"
77 /*-----------------------------------------------------------------*/
78 /* genPlusIncr :- does addition with increment if possible */
79 /*-----------------------------------------------------------------*/
80 bool genPlusIncr (iCode *ic)
83 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
85 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
86 DEBUGpic14_emitcode ("; ","result %d, left %d, right %d",
87 AOP_TYPE(IC_RESULT(ic)),
88 AOP_TYPE(IC_LEFT(ic)),
89 AOP_TYPE(IC_RIGHT(ic)));
91 /* will try to generate an increment */
92 /* if the right side is not a literal
94 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
97 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
98 /* if the literal value of the right hand side
99 is greater than 1 then it is faster to add */
100 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
103 /* if increment 16 bits in register */
104 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
109 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
110 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
114 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
115 //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
121 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
122 /* if left is in accumulator - probably a bit operation*/
123 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
124 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
126 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
127 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
128 AOP(IC_RESULT(ic))->aopu.aop_dir,
129 AOP(IC_RESULT(ic))->aopu.aop_dir);
131 emitpcode(POC_XORLW,popGetLit(1));
132 //pic14_emitcode("xorlw","1");
134 emitpcode(POC_ANDLW,popGetLit(1));
135 //pic14_emitcode("andlw","1");
138 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
139 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
140 AOP(IC_RESULT(ic))->aopu.aop_dir,
141 AOP(IC_RESULT(ic))->aopu.aop_dir);
148 /* if the sizes are greater than 1 then we cannot */
149 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
150 AOP_SIZE(IC_LEFT(ic)) > 1 )
153 /* If we are incrementing the same register by two: */
155 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
158 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
159 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
164 DEBUGpic14_emitcode ("; ","couldn't increment result-%s left-%s",
165 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
166 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
170 /*-----------------------------------------------------------------*/
171 /* pic14_outBitAcc - output a bit in acc */
172 /*-----------------------------------------------------------------*/
173 void pic14_outBitAcc(operand *result)
175 symbol *tlbl = newiTempLabel(NULL);
176 /* if the result is a bit */
177 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
179 if (AOP_TYPE(result) == AOP_CRY){
180 aopPut(AOP(result),"a",0);
183 pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
184 pic14_emitcode("mov","a,#01");
185 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
186 pic14_outAcc(result);
190 /*-----------------------------------------------------------------*/
191 /* genPlusBits - generates code for addition of two bits */
192 /*-----------------------------------------------------------------*/
193 void genPlusBits (iCode *ic)
196 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
198 The following block of code will add two bits.
199 Note that it'll even work if the destination is
200 the carry (C in the status register).
201 It won't work if the 'Z' bit is a source or destination.
204 /* If the result is stored in the accumulator (w) */
205 //if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
206 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
207 //emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
208 // popGet(AOP(result),0,FALSE,FALSE));
210 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
211 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
212 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
213 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
214 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
215 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
217 pic14_emitcode("movlw","(1 << (%s & 7))",
218 AOP(IC_RESULT(ic))->aopu.aop_dir,
219 AOP(IC_RESULT(ic))->aopu.aop_dir);
220 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
221 AOP(IC_RESULT(ic))->aopu.aop_dir,
222 AOP(IC_RESULT(ic))->aopu.aop_dir);
223 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
224 AOP(IC_RIGHT(ic))->aopu.aop_dir,
225 AOP(IC_RIGHT(ic))->aopu.aop_dir);
226 pic14_emitcode("xorwf","(%s >>3),f",
227 AOP(IC_RESULT(ic))->aopu.aop_dir);
228 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
229 AOP(IC_LEFT(ic))->aopu.aop_dir,
230 AOP(IC_LEFT(ic))->aopu.aop_dir);
231 pic14_emitcode("xorwf","(%s>>3),f",
232 AOP(IC_RESULT(ic))->aopu.aop_dir);
235 emitpcode(POC_CLRW, NULL);
236 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
237 emitpcode(POC_XORLW, popGetLit(1));
238 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
239 emitpcode(POC_XORLW, popGetLit(1));
241 pic14_emitcode("clrw","");
242 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
243 AOP(IC_RIGHT(ic))->aopu.aop_dir,
244 AOP(IC_RIGHT(ic))->aopu.aop_dir);
245 pic14_emitcode("xorlw","1");
246 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
247 AOP(IC_LEFT(ic))->aopu.aop_dir,
248 AOP(IC_LEFT(ic))->aopu.aop_dir);
249 pic14_emitcode("xorlw","1");
255 /* This is the original version of this code.
257 * This is being kept around for reference,
258 * because I am not entirely sure I got it right...
260 static void adjustArithmeticResult(iCode *ic)
262 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
263 AOP_SIZE(IC_LEFT(ic)) == 3 &&
264 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
265 aopPut(AOP(IC_RESULT(ic)),
266 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
269 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
270 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
271 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
272 aopPut(AOP(IC_RESULT(ic)),
273 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
276 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
277 AOP_SIZE(IC_LEFT(ic)) < 3 &&
278 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
279 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
280 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
282 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
283 aopPut(AOP(IC_RESULT(ic)),buffer,2);
287 /* This is the pure and virtuous version of this code.
288 * I'm pretty certain it's right, but not enough to toss the old
291 static void adjustArithmeticResult(iCode *ic)
293 if (opIsGptr(IC_RESULT(ic)) &&
294 opIsGptr(IC_LEFT(ic)) &&
295 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
297 aopPut(AOP(IC_RESULT(ic)),
298 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
302 if (opIsGptr(IC_RESULT(ic)) &&
303 opIsGptr(IC_RIGHT(ic)) &&
304 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
306 aopPut(AOP(IC_RESULT(ic)),
307 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
311 if (opIsGptr(IC_RESULT(ic)) &&
312 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
313 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
314 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
315 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
317 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
318 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
323 /*-----------------------------------------------------------------*/
324 /* genPlus - generates code for addition */
325 /*-----------------------------------------------------------------*/
326 void genPlus (iCode *ic)
328 int size, offset = 0;
330 /* special cases :- */
331 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
333 aopOp (IC_LEFT(ic),ic,FALSE);
334 aopOp (IC_RIGHT(ic),ic,FALSE);
335 aopOp (IC_RESULT(ic),ic,TRUE);
337 /* if literal, literal on the right or
338 if left requires ACC or right is already
341 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
342 operand *t = IC_RIGHT(ic);
343 IC_RIGHT(ic) = IC_LEFT(ic);
347 /* if both left & right are in bit space */
348 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
349 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
354 /* if left in bit space & right literal */
355 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
356 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
357 /* if result in bit space */
358 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
359 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
360 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
361 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
362 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
363 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
366 size = pic14_getDataSize(IC_RESULT(ic));
368 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
369 pic14_emitcode("addc","a,#00 ;%d",__LINE__);
370 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
376 /* if I can do an increment instead
377 of add then GOOD for ME */
378 if (genPlusIncr (ic) == TRUE)
381 size = pic14_getDataSize(IC_RESULT(ic));
383 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
384 /* Add a literal to something else */
386 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
390 DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
393 DEBUGpic14_emitcode(";","size %d",size);
395 switch (lit & 0xff) {
399 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
400 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
403 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
404 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
405 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
409 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
410 emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
413 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
414 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
415 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
419 if( !know_W || ( (lit&0xff) != l1) ) {
421 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
423 if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
424 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
427 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
428 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
431 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
441 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
443 pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
444 pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
445 pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
447 /* here we are adding a bit to a char or int */
449 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
451 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
452 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
454 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
455 AOP(IC_RIGHT(ic))->aopu.aop_dir,
456 AOP(IC_RIGHT(ic))->aopu.aop_dir);
457 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
460 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
461 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
462 emitpcode(POC_XORLW , popGetLit(1));
464 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
465 AOP(IC_RIGHT(ic))->aopu.aop_dir,
466 AOP(IC_RIGHT(ic))->aopu.aop_dir);
467 pic14_emitcode(" xorlw","1");
469 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
470 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
471 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
473 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
474 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
475 AOP(IC_RIGHT(ic))->aopu.aop_dir,
476 AOP(IC_RIGHT(ic))->aopu.aop_dir);
477 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
480 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
482 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
483 emitpcode(POC_ANDLW , popGetLit(1));
484 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
486 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
488 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
489 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
497 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
499 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
500 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
502 pic14_emitcode("clrz","");
504 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
505 AOP(IC_RIGHT(ic))->aopu.aop_dir,
506 AOP(IC_RIGHT(ic))->aopu.aop_dir);
507 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
511 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
512 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
513 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
514 emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
517 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
518 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
519 AOP(IC_RIGHT(ic))->aopu.aop_dir,
520 AOP(IC_RIGHT(ic))->aopu.aop_dir);
521 pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
522 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
528 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
529 //pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
536 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
537 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
538 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
541 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
542 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
543 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
544 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
547 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
549 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
550 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
552 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
553 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
554 emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
556 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
557 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
558 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
568 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
569 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
570 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
572 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
573 pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
576 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
578 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
579 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
582 pic14_emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
584 pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
585 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
593 //adjustArithmeticResult(ic);
596 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
597 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
598 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
601 /*-----------------------------------------------------------------*/
602 /* genMinusDec :- does subtraction with decrement if possible */
603 /*-----------------------------------------------------------------*/
604 bool genMinusDec (iCode *ic)
606 unsigned int icount ;
607 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
609 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
610 /* will try to generate an increment */
611 /* if the right side is not a literal
613 if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) ||
614 (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) ||
615 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
618 DEBUGpic14_emitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
620 /* if the literal value of the right hand side
621 is greater than 4 then it is not worth it */
622 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
625 /* if decrement 16 bits in register */
626 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
631 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
632 emitpcode(POC_INCFSZW, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
633 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
635 pic14_emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
636 pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
637 pic14_emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
640 emitpcode(POC_MOVLW, popGetLit(0xff));
641 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
643 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
645 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
647 pic14_emitcode("movlw","0xff");
648 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
651 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
653 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
657 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
659 pic14_emitcode("skpnc","");
661 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
670 /* if the sizes are greater than 1 then we cannot */
671 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
672 AOP_SIZE(IC_LEFT(ic)) > 1 )
675 /* we can if the aops of the left & result match or
676 if they are in registers and the registers are the
678 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
681 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
683 //pic14_emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
688 DEBUGpic14_emitcode ("; returning"," result=%s, left=%s",
689 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
690 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
693 pic14_emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
694 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
696 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
697 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
705 /*-----------------------------------------------------------------*/
706 /* addSign - complete with sign */
707 /*-----------------------------------------------------------------*/
708 void addSign(operand *result, int offset, int sign)
710 int size = (pic14_getDataSize(result) - offset);
711 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
714 pic14_emitcode("rlc","a");
715 pic14_emitcode("subb","a,acc");
717 aopPut(AOP(result),"a",offset++);
720 aopPut(AOP(result),"#0",offset++);
724 /*-----------------------------------------------------------------*/
725 /* genMinusBits - generates code for subtraction of two bits */
726 /*-----------------------------------------------------------------*/
727 void genMinusBits (iCode *ic)
729 symbol *lbl = newiTempLabel(NULL);
730 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
731 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
732 pic14_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
733 pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
734 pic14_emitcode("cpl","c");
735 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
736 pic14_outBitC(IC_RESULT(ic));
739 pic14_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
740 pic14_emitcode("subb","a,acc");
741 pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
742 pic14_emitcode("inc","a");
743 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
744 aopPut(AOP(IC_RESULT(ic)),"a",0);
745 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
749 /*-----------------------------------------------------------------*/
750 /* genMinus - generates code for subtraction */
751 /*-----------------------------------------------------------------*/
752 void genMinus (iCode *ic)
754 int size, offset = 0;
755 unsigned long lit = 0L;
757 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
758 aopOp (IC_LEFT(ic),ic,FALSE);
759 aopOp (IC_RIGHT(ic),ic,FALSE);
760 aopOp (IC_RESULT(ic),ic,TRUE);
762 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
763 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
764 operand *t = IC_RIGHT(ic);
765 IC_RIGHT(ic) = IC_LEFT(ic);
769 /* special cases :- */
770 /* if both left & right are in bit space */
771 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
772 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
777 /* if I can do an decrement instead
778 of subtract then GOOD for ME */
779 if (genMinusDec (ic) == TRUE)
782 size = pic14_getDataSize(IC_RESULT(ic));
784 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
785 /* Add a literal to something else */
787 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
790 /* add the first byte: */
791 pic14_emitcode("movlw","0x%x", lit & 0xff);
792 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
793 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
794 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
806 if((lit & 0xff) == 0xff) {
807 emitpcode(POC_MOVLW, popGetLit(0xff));
809 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
811 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
813 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
814 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
818 /* do the rlf known zero trick here */
819 emitpcode(POC_MOVLW, popGetLit(1));
821 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
826 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
829 pic14_emitcode(";bitsub","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
830 pic14_emitcode(";bitsub","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
831 pic14_emitcode(";bitsub","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
833 /* here we are subtracting a bit from a char or int */
835 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
837 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
838 emitpcode(POC_DECF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
840 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
841 AOP(IC_RIGHT(ic))->aopu.aop_dir,
842 AOP(IC_RIGHT(ic))->aopu.aop_dir);
843 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
846 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
847 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
848 emitpcode(POC_XORLW , popGetLit(1));
849 }else if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
850 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
852 lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
854 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
855 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
857 emitpcode(POC_MOVLW , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
858 emitpcode(POC_XORWF , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
861 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
863 emitpcode(POC_BTFSS , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
865 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
866 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
870 emitpcode(POC_MOVLW , popGetLit(lit & 0xff));
871 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
872 emitpcode(POC_MOVLW , popGetLit((lit-1) & 0xff));
873 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
878 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
879 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
880 emitpcode(POC_DECFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
883 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
885 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
888 emitpcode(POC_ANDLW , popGetLit(1));
890 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
892 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
901 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
902 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
903 emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
904 emitpcode(POC_SUBLW, popGetLit(0));
905 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
908 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
909 emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
910 emitpcode(POC_SUBLW, popGetLit(0));
911 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
912 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
915 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
916 if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)
917 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
919 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
920 emitpcode(POC_SUBWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
922 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
923 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
924 emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
926 emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
928 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
929 if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
930 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
932 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
934 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
941 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
943 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
944 emitpcode(POC_SUBFW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
946 emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
947 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
954 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
955 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
956 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
958 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
960 emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
961 emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
969 // adjustArithmeticResult(ic);
972 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
973 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
974 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);