1 /*-------------------------------------------------------------------------
2 genarith.c - source file for code generation - arithmetic
3
4 Copyright (C) 1998, Sandeep Dutta . sandeep.dutta@usa.net
5 Copyright (C) 1999, Jean-Louis VERN.jlvern@writeme.com
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port:
8 Copyright (C) 2000, Scott Dattalo scott@dattalo.com
9 PIC16 port:
10 Copyright (C) 2002, Martin Dubuc m.dubuc@rogers.com
11
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
15 later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 -------------------------------------------------------------------------*/
26 /*
27 Notes:
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44
45 #if 1
46 #define pic16_emitcode DEBUGpic16_emitcode
47 #endif
48
49 extern void pic16_emitpLabelFORCE(int key);
50
51 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
52
53 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result);
54 void pic16_emitpcomment(char *, ...);
55 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
pic16_AopType(short type)56 const char *pic16_AopType(short type)
57 {
58 switch(type) {
59 case AOP_LIT: return "AOP_LIT";
60 case AOP_REG: return "AOP_REG";
61 case AOP_DIR: return "AOP_DIR";
62 case AOP_STK: return "AOP_STK";
63 case AOP_STR: return "AOP_STR";
64 case AOP_CRY: return "AOP_CRY";
65 case AOP_ACC: return "AOP_ACC";
66 case AOP_PCODE: return "AOP_PCODE";
67 case AOP_STA: return "AOP_STA";
68 }
69
70 return "BAD TYPE";
71 }
72
pic16_pCodeOpType(pCodeOp * pcop)73 const char *pic16_pCodeOpType(pCodeOp *pcop)
74 {
75
76 if(pcop) {
77
78 switch(pcop->type) {
79
80 case PO_NONE: return "PO_NONE";
81 case PO_W: return "PO_W";
82 case PO_WREG: return "PO_WREG";
83 case PO_STATUS: return "PO_STATUS";
84 case PO_BSR: return "PO_BSR";
85 case PO_FSR0: return "PO_FSR0";
86 case PO_INDF0: return "PO_INDF0";
87 case PO_INTCON: return "PO_INTCON";
88 case PO_GPR_REGISTER: return "PO_GPR_REGISTER";
89 case PO_GPR_BIT: return "PO_GPR_BIT";
90 case PO_GPR_TEMP: return "PO_GPR_TEMP";
91 case PO_SFR_REGISTER: return "PO_SFR_REGISTER";
92 case PO_PCL: return "PO_PCL";
93 case PO_PCLATH: return "PO_PCLATH";
94 case PO_PCLATU: return "PO_PCLATU";
95 case PO_PRODL: return "PO_PRODL";
96 case PO_PRODH: return "PO_PRODH";
97 case PO_LITERAL: return "PO_LITERAL";
98 case PO_REL_ADDR: return "PO_REL_ADDR";
99 case PO_IMMEDIATE: return "PO_IMMEDIATE";
100 case PO_DIR: return "PO_DIR";
101 case PO_CRY: return "PO_CRY";
102 case PO_BIT: return "PO_BIT";
103 case PO_STR: return "PO_STR";
104 case PO_LABEL: return "PO_LABEL";
105 case PO_WILD: return "PO_WILD";
106 case PO_TWO_OPS: return "PO_TWO_OPS";
107 }
108 }
109
110 return "BAD PO_TYPE";
111 }
112
pic16_pCodeOpSubType(pCodeOp * pcop)113 const char *pic16_pCodeOpSubType(pCodeOp *pcop)
114 {
115
116 if(pcop && (pcop->type == PO_GPR_BIT)) {
117
118 switch(PCORB(pcop)->subtype) {
119
120 case PO_NONE: return "PO_NONE";
121 case PO_W: return "PO_W";
122 case PO_WREG: return "PO_WREG";
123 case PO_STATUS: return "PO_STATUS";
124 case PO_BSR: return "PO_BSR";
125 case PO_FSR0: return "PO_FSR0";
126 case PO_INDF0: return "PO_INDF0";
127 case PO_INTCON: return "PO_INTCON";
128 case PO_GPR_REGISTER: return "PO_GPR_REGISTER";
129 case PO_GPR_BIT: return "PO_GPR_BIT";
130 case PO_GPR_TEMP: return "PO_GPR_TEMP";
131 case PO_SFR_REGISTER: return "PO_SFR_REGISTER";
132 case PO_PCL: return "PO_PCL";
133 case PO_PCLATH: return "PO_PCLATH";
134 case PO_PCLATU: return "PO_PCLATU";
135 case PO_PRODL: return "PO_PRODL";
136 case PO_PRODH: return "PO_PRODH";
137 case PO_LITERAL: return "PO_LITERAL";
138 case PO_REL_ADDR: return "PO_REL_ADDR";
139 case PO_IMMEDIATE: return "PO_IMMEDIATE";
140 case PO_DIR: return "PO_DIR";
141 case PO_CRY: return "PO_CRY";
142 case PO_BIT: return "PO_BIT";
143 case PO_STR: return "PO_STR";
144 case PO_LABEL: return "PO_LABEL";
145 case PO_WILD: return "PO_WILD";
146 case PO_TWO_OPS: return "PO_TWO_OPS";
147 }
148 }
149
150 return "BAD PO_TYPE";
151 }
152
153 /*-----------------------------------------------------------------*/
154 /* pic16_genPlusIncr :- does addition with increment if possible */
155 /*-----------------------------------------------------------------*/
pic16_genPlusIncr(iCode * ic)156 bool pic16_genPlusIncr (iCode *ic)
157 {
158 unsigned int icount;
159 unsigned int size = pic16_getDataSize(IC_RESULT(ic));
160
161 FENTRY;
162
163 DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
164 pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
165 pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
166 pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
167
168 /* will try to generate an increment */
169 /* if the right side is not a literal
170 we cannot */
171 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
172 {
173 return FALSE;
174 }
175
176 DEBUGpic16_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
177 /* if the literal value of the right hand side
178 is greater than 2 then it is faster to add */
179 if ((icount = (unsigned int)ulFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
180 {
181 return FALSE;
182 }
183
184 /* if increment 16 bits in register */
185 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && icount == 1)
186 {
187 int offset = LSB;
188
189 switch (size)
190 {
191 case 2:
192 pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(IC_RESULT(ic)), offset++));
193 case 1:
194 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
195 break;
196
197 default:
198 {
199 symbol *inclbl = newiTempLabel(NULL);
200 pCodeOp *pcop_lbl = pic16_popGetLabel(inclbl->key);
201 int label_use = 0;
202
203 size -= 2;
204 if (size)
205 {
206 label_use = 1;
207 }
208
209 while (size--)
210 {
211 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), offset++));
212 pic16_emitpcode(POC_BNC, pcop_lbl);
213 }
214
215 pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(IC_RESULT(ic)), offset++));
216 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
217
218 if (label_use)
219 {
220 pic16_emitpLabelFORCE(inclbl->key);
221 }
222 }
223 } // switch (size)
224
225 return TRUE;
226 }
227
228 // DEBUGpic16_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
229 /* if left is in accumulator - probably a bit operation*/ // VR - why this is a bit operation?!
230 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) &&
231 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
232
233 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
234 if(icount)
235 pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
236 //pic16_emitcode("xorlw","1");
237 else
238 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
239 //pic16_emitcode("andlw","1");
240
241 emitSKPZ;
242 pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
243
244 return TRUE;
245 }
246
247
248 /* if the sizes are greater than 1 then we cannot */
249 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
250 AOP_SIZE(IC_LEFT(ic)) > 1 )
251 return FALSE ;
252
253 /* If we are incrementing the same register by two: */
254
255 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
256
257 while (icount--)
258 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
259 //pic16_emitcode("incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
260
261 return TRUE ;
262 }
263
264 DEBUGpic16_emitcode ("; ","couldn't increment ");
265
266 return FALSE ;
267 }
268
269 /*-----------------------------------------------------------------*/
270 /* pic16_outBitAcc - output a bit in acc */
271 /*-----------------------------------------------------------------*/
pic16_outBitAcc(operand * result)272 void pic16_outBitAcc(operand *result)
273 {
274 symbol *tlbl = newiTempLabel(NULL);
275 /* if the result is a bit */
276 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
277
278 assert(0); // not implemented for PIC16?
279
280 if (AOP_TYPE(result) == AOP_CRY){
281 pic16_aopPut(AOP(result),"a",0);
282 }
283 else {
284 pic16_emitcode("jz","%05d_DS_",tlbl->key+100);
285 pic16_emitcode("mov","a,#01");
286 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
287 pic16_outAcc(result);
288 }
289 }
290
291 /*-----------------------------------------------------------------*/
292 /* pic16_genPlusBits - generates code for addition of two bits */
293 /*-----------------------------------------------------------------*/
pic16_genPlusBits(iCode * ic)294 void pic16_genPlusBits (iCode *ic)
295 {
296 FENTRY;
297
298 DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
299 pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
300 pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
301 pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
302 /*
303 The following block of code will add two bits.
304 Note that it'll even work if the destination is
305 the carry (C in the status register).
306 It won't work if the 'Z' bit is a source or destination.
307 */
308
309 /* If the result is stored in the accumulator (w) */
310 //if(strcmp(pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
311 switch(AOP_TYPE(IC_RESULT(ic))) {
312 case AOP_ACC:
313 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
314 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
315 pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
316 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
317 pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
318 break;
319 case AOP_REG:
320 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
321 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
322 pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
323 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
324 pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
325 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
326 break;
327 default:
328 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_RESULT(ic)),0));
329 pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
330 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
331 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
332 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
333 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
334 break;
335 }
336
337 }
338
339 #if 0
340 /* This is the original version of this code.
341 *
342 * This is being kept around for reference,
343 * because I am not entirely sure I got it right...
344 */
345 static void adjustArithmeticResult(iCode *ic)
346 {
347 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
348 AOP_SIZE(IC_LEFT(ic)) == 3 &&
349 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
350 pic16_aopPut(AOP(IC_RESULT(ic)),
351 pic16_aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
352 2);
353
354 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
355 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
356 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
357 pic16_aopPut(AOP(IC_RESULT(ic)),
358 pic16_aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
359 2);
360
361 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
362 AOP_SIZE(IC_LEFT(ic)) < 3 &&
363 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
364 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
365 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
366 char buffer[5];
367 SNPRINTF(buffer, sizeof(buffer), "#%d", pointerCode(getSpec(operandType(IC_LEFT(ic)))));
368 pic16_aopPut(AOP(IC_RESULT(ic)),buffer,2);
369 }
370 }
371 //#else
372 /* This is the pure and virtuous version of this code.
373 * I'm pretty certain it's right, but not enough to toss the old
374 * code just yet...
375 */
376 static void adjustArithmeticResult(iCode *ic)
377 {
378 if (opIsGptr(IC_RESULT(ic)) &&
379 opIsGptr(IC_LEFT(ic)) &&
380 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
381 {
382 pic16_aopPut(AOP(IC_RESULT(ic)),
383 pic16_aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
384 GPTRSIZE - 1);
385 }
386
387 if (opIsGptr(IC_RESULT(ic)) &&
388 opIsGptr(IC_RIGHT(ic)) &&
389 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
390 {
391 pic16_aopPut(AOP(IC_RESULT(ic)),
392 pic16_aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
393 GPTRSIZE - 1);
394 }
395
396 if (opIsGptr(IC_RESULT(ic)) &&
397 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
398 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
399 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
400 !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
401 char buffer[5];
402
403 SNPRINTF(buffer, sizeof(buffer), "#%d", pointerCode(getSpec(operandType(IC_LEFT(ic)))));
404 pic16_aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
405 }
406 }
407 #endif
408
409 #if 1
410 /*-----------------------------------------------------------------*/
411 /* genAddlit - generates code for addition */
412 /*-----------------------------------------------------------------*/
genAddLit2byte(operand * result,int offr,int lit)413 static void genAddLit2byte (operand *result, int offr, int lit)
414 {
415 FENTRY;
416
417 switch(lit & 0xff)
418 {
419 case 0:
420 break;
421
422 case 1:
423 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offr));
424 break;
425
426 case 0xff:
427 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
428 break;
429
430 default:
431 {
432 int resultIsWREG = (AOP_TYPE(result) != AOP_STA && ! strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE), "WREG"));
433
434 if (resultIsWREG)
435 {
436 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
437 }
438 else
439 {
440 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit & 0xff));
441 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
442 }
443 }
444 }
445 }
446 #endif
447
emitMOVWF(operand * reg,int offset)448 static void emitMOVWF(operand *reg, int offset)
449 {
450 if(!reg)
451 return;
452
453 if (AOP_TYPE(reg) == AOP_ACC) {
454 DEBUGpic16_emitcode ("; ***","%s %d ignoring mov into W",__FUNCTION__,__LINE__);
455 return;
456 }
457
458 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(reg),offset));
459
460 }
461
462
463 #if 1
464
genAddLit(iCode * ic,int lit)465 static void genAddLit (iCode *ic, int lit)
466 {
467
468 int size,same;
469 int lo, offset;
470
471 operand *result;
472 operand *left;
473
474 FENTRY;
475
476 left = IC_LEFT(ic);
477 result = IC_RESULT(ic);
478 same = pic16_sameRegs(AOP(left), AOP(result));
479 size = pic16_getDataSize(result);
480
481 if ((AOP_PCODE == AOP_TYPE(left))
482 && (PO_IMMEDIATE == AOP(left)->aopu.pcop->type))
483 {
484 /* see #1888004 for an example case for this */
485 for (offset = 0; offset < size; offset++) {
486 pic16_emitpcode(POC_MOVLW, pic16_newpCodeOpImmd(AOP(left)->aopu.pcop->name,
487 offset, PCOI(AOP(left)->aopu.pcop)->index + lit, 0));
488 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
489 } // for
490 return;
491 } // if
492
493 if(same) {
494
495 /* Handle special cases first */
496 if(size == 1)
497 genAddLit2byte (result, 0, lit);
498
499 else if(size == 2) {
500 int hi = 0xff & (lit >> 8);
501 lo = lit & 0xff;
502
503 switch(hi) {
504 case 0:
505
506 /* lit = 0x00LL */
507 DEBUGpic16_emitcode ("; hi = 0","%s %d",__FUNCTION__,__LINE__);
508 switch(lo) {
509 case 0:
510 break;
511
512 case 1:
513 pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(result),0));
514 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
515 break;
516
517 case 0xff:
518 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
519 pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
520 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
521
522 break;
523 default:
524 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
525 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
526 emitSKPNC;
527 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
528 }
529 break;
530
531 case 1:
532 /* lit = 0x01LL */
533 DEBUGpic16_emitcode ("; hi = 1","%s %d",__FUNCTION__,__LINE__);
534 switch(lo) {
535 case 0: /* 0x0100 */
536 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
537 break;
538 case 1: /* 0x0101 */
539 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
540 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
541 emitSKPNZ;
542 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
543 break;
544 case 0xff: /* 0x01ff */
545 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
546 pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
547 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
548 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
549 break;
550 default: /* 0x01LL */
551 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
552 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
553 emitSKPNC;
554 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
555 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
556 }
557 break;
558
559 case 0xff:
560 DEBUGpic16_emitcode ("; hi = ff","%s %d",__FUNCTION__,__LINE__);
561 /* lit = 0xffLL */
562 switch(lo) {
563 case 0: /* 0xff00 */
564 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
565 break;
566 case 1: /*0xff01 */
567 pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
568 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
569 break;
570
571 case 0xff: /* 0xffff */
572 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lo));
573 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
574 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),MSB16));
575 break;
576
577 default:
578 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
579 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
580 emitSKPC;
581 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
582
583 }
584
585 break;
586
587 default:
588 DEBUGpic16_emitcode ("; hi is generic","%d %s %d",hi,__FUNCTION__,__LINE__);
589
590 /* lit = 0xHHLL */
591 switch(lo) {
592 case 0: /* 0xHH00 */
593 genAddLit2byte (result, MSB16, hi);
594 break;
595 case 1: /* 0xHH01 */
596 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
597 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
598 pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
599 break;
600 /* case 0xff: * 0xHHff *
601 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
602 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
603 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
604 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
605 break;
606 */ default: /* 0xHHLL */
607 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
608 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
609 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
610 pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
611 break;
612 }
613
614 }
615 } else {
616 int carry_info = 0;
617 int prev_W = -1;
618 /* size > 2 */
619 DEBUGpic16_emitcode ("; add lit to long","%s %d",__FUNCTION__,__LINE__);
620
621 offset = 0;
622 while (size--)
623 {
624 lo = BYTEofLONG(lit,0);
625
626 if (carry_info)
627 {
628 if (prev_W != (lo & 0xFF))
629 {
630 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lo));
631 prev_W = lo & 0xFF;
632 }
633
634 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
635 }
636 else {
637 /* no carry info from previous step */
638 /* this means this is the first time to add */
639 switch (lo)
640 {
641 case 0:
642 break;
643
644 case 1:
645 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
646 carry_info = 1;
647 break;
648
649 default:
650 {
651 if (prev_W != (lo & 0xFF))
652 {
653 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lo));
654 prev_W = lo & 0xFF;
655 }
656
657 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
658
659 if (lit < 0x100)
660 carry_info = 3; /* Were adding only one byte and propogating the carry. */
661 else
662 carry_info = 2;
663 break;
664 }
665 }
666 }
667 offset++;
668 lit >>= 8;
669 }
670
671 /*
672 lo = BYTEofLONG(lit,0);
673
674 if(lit < 0x100) {
675 if(lo) {
676 if(lo == 1) {
677 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE));
678 emitSKPNZ;
679 } else {
680 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
681 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
682 emitSKPNC;
683 }
684 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE));
685 emitSKPNZ;
686 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE));
687 emitSKPNZ;
688 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE));
689
690 }
691 }
692
693 */
694 }
695 } else {
696 int offset = 1;
697 DEBUGpic16_emitcode ("; left and result aren't same","%s %d",__FUNCTION__,__LINE__);
698
699 if(size == 1) {
700
701 if(AOP_TYPE(left) == AOP_ACC) {
702 /* left addend is already in accumulator */
703 switch(lit & 0xff) {
704 case 0:
705 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
706 emitMOVWF(result,0);
707 break;
708 default:
709 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
710 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
711 emitMOVWF(result,0);
712 }
713 } else {
714 /* left addend is in a register */
715 switch(lit & 0xff) {
716 case 0:
717 pic16_mov2w(AOP(left),0);
718 emitMOVWF(result, 0);
719 break;
720 case 1:
721 pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
722 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
723 emitMOVWF(result,0);
724 break;
725 case 0xff:
726 pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0));
727 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
728 emitMOVWF(result,0);
729 break;
730 default:
731 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
732 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
733 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
734 emitMOVWF(result,0);
735 }
736 }
737
738 // } else if (pic16_isLitAop(AOP(left))) {
739 // // adding two literals
740 // assert ( !"adding two literals is not yet supported" );
741 } else {
742 int clear_carry=0;
743
744 /* left is not the accumulator */
745 if(lit & 0xff) {
746 pic16_mov2w(AOP(left),0);
747 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
748 } else {
749 pic16_mov2w(AOP(left),0);
750 /* We don't know the state of the carry bit at this point */
751 clear_carry = 1;
752 }
753 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
754 emitMOVWF(result,0);
755 while(--size) {
756 lit >>= 8;
757 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
758 if (offset < AOP_SIZE(left)) {
759 pic16_emitpcode(clear_carry ? POC_ADDFW : POC_ADDFWC, pic16_popGet(AOP(left),offset));
760 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
761 } else {
762 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
763 if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
764 /* sign-extend left (in result) */
765 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left),AOP_SIZE(left)-1,7));
766 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
767 }
768 pic16_emitpcode(clear_carry ? POC_ADDWF : POC_ADDWFC, pic16_popGet(AOP(result),offset));
769 }
770 clear_carry = 0;
771 offset++;
772 }
773 }
774 }
775 }
776
777 #else
778 /* this fails when result is an SFR because value is written there
779 * during addition and not at the end */
780
genAddLit(iCode * ic,int lit)781 static void genAddLit (iCode *ic, int lit)
782 {
783
784 int size,sizeL,same;
785 int i, llit, prev_W;
786
787 operand *result;
788 operand *left;
789
790 FENTRY;
791
792
793 left = IC_LEFT(ic);
794 result = IC_RESULT(ic);
795 same = pic16_sameRegs(AOP(left), AOP(result));
796 size = pic16_getDataSize(result);
797 sizeL = pic16_getDataSize(left);
798 llit = lit;
799
800 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
801 /* move left to result -- possibly sign extend */
802 for (i=0; i < MIN(size, sizeL); i++) {
803 pic16_mov2f (AOP(result), AOP(left), i);
804 } // for i
805 #undef MIN
806
807 /* extend to result size */
808 pic16_addSign(result, sizeL, !IS_UNSIGNED(operandType(left)));
809
810 /* special cases */
811 if (lit == 0) {
812 /* nothing to do */
813 } else if (lit == 1) {
814 switch (size) {
815 case 1:
816 /* handled below */
817 break;
818 case 2:
819 pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(result), 0));
820 break;
821 default:
822 assert (size > 2);
823 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), 0));
824 for (i=1; i < size-1; i++) {
825 emitSKPNC; /* a jump here saves up to 2(size-2)cycles */
826 pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), i));
827 } // for i
828 emitSKPNC;
829 break;
830 } // switch
831
832 pic16_emitpcode (POC_INCF, pic16_popGet (AOP(result), size-1));
833 } else {
834 /* general case */
835
836 /* add literal to result */
837 prev_W = -1;
838 for (i = 0; i < size; i++)
839 {
840 if (prev_W != (llit & 0xFF))
841 {
842 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(llit));
843 prev_W = llit & 0xFF;
844 }
845
846 llit >>= 8; /* FIXME: arithmetic right shift for signed literals? */
847 pic16_emitpcode(i == 0 ? POC_ADDWF : POC_ADDWFC, pic16_popGet(AOP(result), i));
848 }
849 }
850
851 #if 0
852
853 if(same) {
854
855 /* Handle special cases first */
856 if(size == 1)
857 genAddLit2byte (result, 0, lit);
858
859 else if(size == 2) {
860 int hi = 0xff & (lit >> 8);
861 lo = lit & 0xff;
862
863 switch(hi) {
864 case 0:
865
866 /* lit = 0x00LL */
867 DEBUGpic16_emitcode ("; hi = 0","%s %d",__FUNCTION__,__LINE__);
868 switch(lo) {
869 case 0:
870 break;
871 case 1:
872 pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(result),0));
873 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
874 break;
875 case 0xff:
876 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
877 pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
878 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
879
880 break;
881 default:
882 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
883 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
884 emitSKPNC;
885 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
886
887
888 }
889 break;
890
891 case 1:
892 /* lit = 0x01LL */
893 DEBUGpic16_emitcode ("; hi = 1","%s %d",__FUNCTION__,__LINE__);
894 switch(lo) {
895 case 0: /* 0x0100 */
896 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
897 break;
898 case 1: /* 0x0101 */
899 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
900 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
901 emitSKPNZ;
902 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
903 break;
904 case 0xff: /* 0x01ff */
905 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
906 pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
907 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
908 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
909 break;
910 default: /* 0x01LL */
911 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
912 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
913 emitSKPNC;
914 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
915 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
916 }
917 break;
918
919 case 0xff:
920 DEBUGpic16_emitcode ("; hi = ff","%s %d",__FUNCTION__,__LINE__);
921 /* lit = 0xffLL */
922 switch(lo) {
923 case 0: /* 0xff00 */
924 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
925 break;
926 case 1: /*0xff01 */
927 pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
928 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
929 break;
930 /* case 0xff: * 0xffff *
931 pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0,FALSE,FALSE));
932 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
933 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0,FALSE,FALSE));
934 break;
935 */
936 default:
937 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
938 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
939 emitSKPC;
940 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
941
942 }
943
944 break;
945
946 default:
947 DEBUGpic16_emitcode ("; hi is generic","%d %s %d",hi,__FUNCTION__,__LINE__);
948
949 /* lit = 0xHHLL */
950 switch(lo) {
951 case 0: /* 0xHH00 */
952 genAddLit2byte (result, MSB16, hi);
953 break;
954 case 1: /* 0xHH01 */
955 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
956 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
957 pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
958 break;
959 /* case 0xff: * 0xHHff *
960 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
961 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
962 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
963 pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
964 break;
965 */ default: /* 0xHHLL */
966 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
967 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
968 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
969 pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
970 break;
971 }
972
973 }
974 } else {
975 int carry_info = 0;
976 int offset = 0;
977 /* size > 2 */
978 DEBUGpic16_emitcode ("; add lit to long","%s %d",__FUNCTION__,__LINE__);
979
980 while(size--) {
981 lo = BYTEofLONG(lit,0);
982
983 if(carry_info) {
984 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
985 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
986 }else {
987 /* no carry info from previous step */
988 /* this means this is the first time to add */
989 switch(lo) {
990 case 0:
991 break;
992 case 1:
993 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
994 carry_info=1;
995 break;
996 default:
997 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
998 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
999 if(lit <0x100)
1000 carry_info = 3; /* Were adding only one byte and propogating the carry */
1001 else
1002 carry_info = 2;
1003 break;
1004 }
1005 }
1006 offset++;
1007 lit >>= 8;
1008 }
1009
1010 /*
1011 lo = BYTEofLONG(lit,0);
1012
1013 if(lit < 0x100) {
1014 if(lo) {
1015 if(lo == 1) {
1016 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1017 emitSKPNZ;
1018 } else {
1019 pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
1020 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1021 emitSKPNC;
1022 }
1023 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE));
1024 emitSKPNZ;
1025 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE));
1026 emitSKPNZ;
1027 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE));
1028
1029 }
1030 }
1031
1032 */
1033 }
1034 } else {
1035 int offset = 1;
1036 DEBUGpic16_emitcode ("; left and result aren't same","%s %d",__FUNCTION__,__LINE__);
1037
1038 if(size == 1) {
1039
1040 if(AOP_TYPE(left) == AOP_ACC) {
1041 /* left addend is already in accumulator */
1042 switch(lit & 0xff) {
1043 case 0:
1044 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1045 emitMOVWF(result,0);
1046 break;
1047 default:
1048 pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
1049 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1050 emitMOVWF(result,0);
1051 }
1052 } else {
1053 /* left addend is in a register */
1054 switch(lit & 0xff) {
1055 case 0:
1056 pic16_mov2w(AOP(left),0);
1057 emitMOVWF(result, 0);
1058 break;
1059 case 1:
1060 pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
1061 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1062 emitMOVWF(result,0);
1063 break;
1064 case 0xff:
1065 pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0));
1066 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1067 emitMOVWF(result,0);
1068 break;
1069 default:
1070 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1071 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
1072 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1073 emitMOVWF(result,0);
1074 }
1075 }
1076
1077 } else {
1078 int clear_carry=0;
1079
1080 /* left is not the accumulator */
1081 if(lit & 0xff) {
1082 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1083 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
1084 } else {
1085 pic16_mov2w(AOP(left),0);
1086 /* We don't know the state of the carry bit at this point */
1087 clear_carry = 1;
1088 }
1089 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1090 emitMOVWF(result,0);
1091 while(--size) {
1092
1093 lit >>= 8;
1094 if(lit & 0xff) {
1095 if(clear_carry) {
1096 /* The ls byte of the lit must've been zero - that
1097 means we don't have to deal with carry */
1098
1099 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1100 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offset));
1101 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
1102
1103 clear_carry = 0;
1104
1105 } else {
1106 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1107 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),offset));
1108 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
1109 }
1110
1111 } else {
1112 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
1113 pic16_mov2w(AOP(left),offset);
1114 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
1115 }
1116 offset++;
1117 }
1118 }
1119 }
1120 #endif
1121 }
1122
1123 #endif
1124
1125 /*-----------------------------------------------------------------*/
1126 /* pic16_genPlus - generates code for addition */
1127 /*-----------------------------------------------------------------*/
pic16_genPlus(iCode * ic)1128 void pic16_genPlus (iCode *ic)
1129 {
1130 int i, size, offset = 0;
1131 operand *result, *left, *right;
1132
1133 FENTRY;
1134
1135 /* special cases :- */
1136 result = IC_RESULT(ic);
1137 left = IC_LEFT(ic);
1138 right = IC_RIGHT(ic);
1139 pic16_aopOp (left,ic,FALSE);
1140 pic16_aopOp (right,ic,FALSE);
1141 pic16_aopOp (result,ic,TRUE);
1142 DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
1143 // pic16_DumpOp("(left)",left);
1144
1145 /* if literal, literal on the right or
1146 if left requires ACC or right is already
1147 in ACC */
1148
1149 if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) {
1150 operand *t = right;
1151 right = IC_RIGHT(ic) = left;
1152 left = IC_LEFT(ic) = t;
1153 }
1154
1155 /* if both left & right are in bit space */
1156 if (AOP_TYPE(left) == AOP_CRY &&
1157 AOP_TYPE(right) == AOP_CRY) {
1158 pic16_genPlusBits (ic);
1159 goto release ;
1160 }
1161
1162 /* if left in bit space & right literal */
1163 if (AOP_TYPE(left) == AOP_CRY &&
1164 AOP_TYPE(right) == AOP_LIT) {
1165 /* if result in bit space */
1166 if(AOP_TYPE(result) == AOP_CRY){
1167 if(ulFromVal (AOP(right)->aopu.aop_lit) != 0L) {
1168 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0));
1169 if (!pic16_sameRegs(AOP(left), AOP(result)) )
1170 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
1171 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0));
1172 }
1173 } else {
1174 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
1175 size = pic16_getDataSize(result);
1176 while (size--) {
1177 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
1178 pic16_emitpcode (POC_MOVLW, pic16_popGetLit ((lit >> (8*offset)) & 0xFF));
1179 pic16_emitpcode (POC_ADDWFC, pic16_popGet(AOP(result), offset++));
1180 //MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
1181 //pic16_emitcode("addc","a,#00 ;%d",__LINE__);
1182 //pic16_aopPut(AOP(result),"a",offset++);
1183 }
1184 }
1185 goto release ;
1186 } // left == CRY
1187
1188 /* if I can do an increment instead
1189 of add then GOOD for ME */
1190 if (pic16_genPlusIncr (ic) == TRUE)
1191 goto release;
1192
1193 size = pic16_getDataSize(result);
1194
1195 if(AOP(right)->type == AOP_LIT) {
1196 /* Add a literal to something else */
1197 //bool know_W=0;
1198 unsigned lit = (unsigned) ulFromVal (AOP(right)->aopu.aop_lit);
1199 //unsigned l1=0;
1200
1201 //offset = 0;
1202 DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
1203
1204 genAddLit (ic, lit);
1205 goto release;
1206
1207 } else if(AOP_TYPE(right) == AOP_CRY) {
1208
1209 pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
1210 pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
1211 pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
1212
1213 /* here we are adding a bit to a char or int */
1214 if(size == 1) {
1215 if (pic16_sameRegs(AOP(left), AOP(result)) ) {
1216
1217 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
1218 pic16_emitpcode(POC_INCF , pic16_popGet(AOP(result),0));
1219 } else { // not same
1220
1221 if(AOP_TYPE(left) == AOP_ACC) {
1222 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
1223 pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
1224 } else {
1225 pic16_mov2w(AOP(left),0);
1226 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
1227 pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(left),0));
1228 }
1229
1230 if(AOP_TYPE(result) != AOP_ACC) {
1231
1232 if(AOP_TYPE(result) == AOP_CRY) {
1233 pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
1234 pic16_emitpcode(POC_BCF , pic16_popGet(AOP(result),0));
1235 emitSKPZ;
1236 pic16_emitpcode(POC_BSF , pic16_popGet(AOP(result),0));
1237 } else {
1238 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result),0));
1239 }
1240 }
1241 }
1242
1243 } else {
1244 int offset = 1;
1245 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1246 if (pic16_sameRegs(AOP(left), AOP(result)) ) {
1247 emitCLRZ;
1248 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
1249 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
1250 } else {
1251 emitCLRZ; // needed here as well: INCFW is not always executed, Z is undefined then
1252 pic16_mov2w(AOP(left),0);
1253 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
1254 pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
1255 emitMOVWF(right,0);
1256 }
1257
1258 while(--size){
1259 emitSKPZ;
1260 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset++));
1261 }
1262
1263 }
1264
1265 } else {
1266 // add bytes
1267
1268 // Note: the following is an example of WISC code, eg.
1269 // it's supposed to run on a Weird Instruction Set Computer :o)
1270
1271 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1272
1273 if ( AOP_TYPE(left) == AOP_ACC) {
1274 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1275 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),0));
1276 if ( AOP_TYPE(result) != AOP_ACC)
1277 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1278 goto release; // we're done, since WREG is 1 byte
1279 }
1280
1281
1282 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1283
1284 size = min( AOP_SIZE(result), AOP_SIZE(right) );
1285 size = min( size, AOP_SIZE(left) );
1286 offset = 0;
1287
1288 if(pic16_debug_verbose) {
1289 // fprintf(stderr, "%s:%d result: %d\tleft: %d\tright: %d\n", __FILE__, __LINE__,
1290 // AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
1291 // fprintf(stderr, "%s:%d size of operands: %d\n", __FILE__, __LINE__, size);
1292 }
1293
1294
1295
1296 if ((AOP_TYPE(left) == AOP_PCODE) && (
1297 (AOP(left)->aopu.pcop->type == PO_LITERAL) ||
1298 // (AOP(left)->aopu.pcop->type == PO_DIR) || // patch 9
1299 (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)))
1300 {
1301 // add to literal operand
1302
1303 // add first bytes
1304 for(i=0; i<size; i++) {
1305 if (AOP_TYPE(right) == AOP_ACC) {
1306 pic16_emitpcode(POC_ADDLW, pic16_popGet(AOP(left),i));
1307 } else {
1308 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
1309 if(i) { // add with carry
1310 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(right),i));
1311 } else { // add without
1312 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),i));
1313 }
1314 }
1315 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1316 }
1317
1318 DEBUGpic16_pic16_AopTypeSign(__LINE__, NULL, right, NULL);
1319
1320 // add leftover bytes
1321 if (SPEC_USIGN(getSpec(operandType(right)))) {
1322 // right is unsigned
1323 for(i=size; i< AOP_SIZE(result); i++) {
1324 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
1325 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
1326 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
1327 }
1328
1329 } else {
1330 // right is signed, oh dear ...
1331 for(i=size; i< AOP_SIZE(result); i++) {
1332 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
1333 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1334 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),i));
1335 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
1336 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
1337 }
1338
1339 }
1340 goto release;
1341
1342 } else {
1343 // add regs
1344
1345 if (pic16_sameRegs(AOP(left), AOP(result))
1346 && (AOP_SIZE(left) < AOP_SIZE(result)))
1347 {
1348 // extend left operand, sign-bit still intact
1349 pic16_addSign (result, AOP_SIZE(left), !SPEC_USIGN(getSpec(operandType(left))));
1350 }
1351
1352 // add first bytes
1353 for(i=0; i<size; i++) {
1354 if (AOP_TYPE(right) != AOP_ACC)
1355 pic16_mov2w(AOP(right),i);
1356 if (pic16_sameRegs(AOP(left), AOP(result)))
1357 {
1358 if(i) { // add with carry
1359 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
1360 } else { // add without
1361 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),i));
1362 }
1363 } else { // not same
1364 if(i) { // add with carry
1365 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
1366 } else { // add without
1367 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),i));
1368 }
1369 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1370 }
1371 }
1372
1373 // add leftover bytes
1374 // either left or right is too short
1375 for (i=size; i < AOP_SIZE(result); i++) {
1376 // get right operand into WREG
1377 if (i < AOP_SIZE(right)) {
1378 pic16_mov2w (AOP(right), i);
1379 } else {
1380 // right is too short, not overwritten with result
1381 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
1382 if (!SPEC_USIGN(getSpec(operandType(right)))) {
1383 // right operand is signed
1384 // Make sure that right's sign is not yet overwritten
1385 assert (!pic16_sameRegs (AOP(right), AOP(result)));
1386 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),AOP_SIZE(right)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1387 pic16_emitpcode(POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
1388 }
1389 }
1390
1391 // get left+WREG+CARRY into result
1392 if (pic16_sameRegs (AOP(left), AOP(result))) {
1393 // left might have been extended in result above
1394 pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
1395 } else if (i < AOP_SIZE(left)) {
1396 pic16_emitpcode (POC_ADDFWC, pic16_popGet (AOP(left), i));
1397 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1398 } else {
1399 // left is too short, not overwritten with result
1400 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
1401 if (!SPEC_USIGN(getSpec(operandType(left)))) {
1402 // left operand is signed
1403 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1404 pic16_emitpcode(POC_SETF, pic16_popGet (AOP(result), i));
1405 }
1406 pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
1407 }
1408 } // for i
1409 goto release;
1410 }
1411
1412 }
1413
1414 assert( 0 );
1415
1416 release:
1417 pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1418 pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1419 pic16_freeAsmop(result,NULL,ic,TRUE);
1420 }
1421
1422 /*-----------------------------------------------------------------*/
1423 /* pic16_genMinusDec :- does subtraction with decrement if possible */
1424 /*-----------------------------------------------------------------*/
pic16_genMinusDec(iCode * ic)1425 bool pic16_genMinusDec (iCode *ic)
1426 {
1427 unsigned int icount ;
1428 unsigned int size = pic16_getDataSize(IC_RESULT(ic));
1429
1430 FENTRY;
1431 /* will try to generate an increment */
1432 /* if the right side is not a literal
1433 we cannot */
1434 if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) ||
1435 (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) ||
1436 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
1437 return FALSE ;
1438
1439 DEBUGpic16_emitcode ("; lit val","%d",(unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1440
1441 /* if the literal value of the right hand side
1442 is greater than 4 then it is not worth it */
1443 if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1444 return FALSE ;
1445
1446 /* if decrement 16 bits in register */
1447 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1448 (size > 1) &&
1449 (icount == 1)) {
1450
1451 if(size == 2) {
1452 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1453 emitSKPC;
1454 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1455
1456 pic16_emitcode("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1457 pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1458 pic16_emitcode(" decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1459 } else {
1460 /* size is 3 or 4 */
1461 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1462 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
1463 pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1464 pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),MSB24));
1465
1466 pic16_emitcode("movlw","0xff");
1467 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1468
1469 //emitSKPNC;
1470 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1471 //emitSKPNC;
1472 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
1473
1474 if(size > 3) {
1475 pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),MSB32));
1476
1477 pic16_emitcode("skpnc","");
1478 //emitSKPNC;
1479 pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
1480 }
1481
1482 }
1483
1484 return TRUE;
1485
1486 }
1487
1488 /* if the sizes are greater than 1 then we cannot */
1489 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1490 AOP_SIZE(IC_LEFT(ic)) > 1 )
1491 return FALSE ;
1492
1493 /* we can if the aops of the left & result match or
1494 if they are in registers and the registers are the
1495 same */
1496 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1497
1498 while (icount--)
1499 pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),0));
1500
1501 //pic16_emitcode ("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1502
1503 return TRUE ;
1504 }
1505
1506 DEBUGpic16_emitcode ("; returning"," result=%s, left=%s",
1507 pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
1508 pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1509 if(size==1) {
1510
1511 pic16_emitcode("decf","%s,w",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1512 pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1513
1514 pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1515 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
1516
1517 return TRUE;
1518 }
1519
1520 return FALSE ;
1521 }
1522
1523 /*-----------------------------------------------------------------*/
1524 /* pic16_addSign - propogate sign bit to higher bytes */
1525 /*-----------------------------------------------------------------*/
pic16_addSign(operand * result,int offset,int sign)1526 void pic16_addSign(operand *result, int offset, int sign)
1527 {
1528 int size = (pic16_getDataSize(result) - offset);
1529 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1530
1531 if(size > 0){
1532 if(sign && offset) {
1533
1534 if(size == 1) {
1535 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
1536 pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1537 pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
1538 } else {
1539
1540 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
1541 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1542 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
1543 while(size--)
1544 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size));
1545
1546 }
1547 } else
1548 while(size--)
1549 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1550 }
1551 }
1552
1553 /*-----------------------------------------------------------------*/
1554 /* pic16_genMinus - generates code for subtraction */
1555 /*-----------------------------------------------------------------*/
pic16_genMinus(iCode * ic)1556 void pic16_genMinus (iCode *ic)
1557 {
1558 int size, offset = 0, same=0;
1559 unsigned long lit = 0L;
1560
1561 FENTRY;
1562 pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1563 pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
1564 pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1565
1566 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1567 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1568 operand *t = IC_RIGHT(ic);
1569 IC_RIGHT(ic) = IC_LEFT(ic);
1570 IC_LEFT(ic) = t;
1571 }
1572
1573 DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
1574 pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1575 pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1576 pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1577
1578 /* special cases :- */
1579 /* if both left & right are in bit space */
1580 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1581 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1582 pic16_genPlusBits (ic);
1583 goto release ;
1584 }
1585
1586 /* if I can do an decrement instead
1587 of subtract then GOOD for ME */
1588 // if (pic16_genMinusDec (ic) == TRUE)
1589 // goto release;
1590
1591 size = pic16_getDataSize(IC_RESULT(ic));
1592 same = pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
1593
1594 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
1595 /* Add a literal to something else */
1596
1597 lit = ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1598 lit = - (long)lit;
1599
1600 genAddLit ( ic, lit);
1601 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1602 // bit subtraction
1603
1604 pic16_emitcode(";bitsub","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1605 pic16_emitcode(";bitsub","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1606 pic16_emitcode(";bitsub","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1607
1608 /* here we are subtracting a bit from a char or int */
1609 if(size == 1) {
1610 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1611
1612 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1613 pic16_emitpcode(POC_DECF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1614 } else {
1615
1616 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1617 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1618 pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
1619 }else if( (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1620
1621 lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1622
1623 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1624 if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1625 if(lit & 1) {
1626 pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1));
1627 pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1628 }
1629 }else{
1630 pic16_emitpcode(POC_BCF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1631 if(lit & 1)
1632 pic16_emitpcode(POC_BTFSS , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1633 else
1634 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1635 pic16_emitpcode(POC_BSF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1636 }
1637 goto release;
1638 } else {
1639 pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff));
1640 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1641 pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff));
1642 //pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1643
1644 }
1645
1646 } else {
1647 pic16_mov2w(AOP(IC_LEFT(ic)),0);
1648 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1649 pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
1650 }
1651
1652 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1653
1654 pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1655
1656 } else {
1657 pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
1658 /*
1659 pic16_emitpcode(POC_BCF , pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1660 emitSKPZ;
1661 pic16_emitpcode(POC_BSF , pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1662 */
1663 }
1664
1665 }
1666
1667 }
1668 } else if((AOP(IC_LEFT(ic))->type == AOP_LIT) &&
1669 (AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)) {
1670
1671 lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1672 DEBUGpic16_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
1673 pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1674 pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1675 pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1676
1677
1678 if( (size == 1) && ((lit & 0xff) == 0) ) {
1679 /* res = 0 - right */
1680 if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1681 pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(IC_RIGHT(ic)),0));
1682 } else {
1683 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
1684 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
1685 pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
1686 }
1687 goto release;
1688 }
1689
1690 pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1691 pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));
1692 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1693
1694
1695 offset = 0;
1696 while(--size) {
1697 lit >>= 8;
1698 offset++;
1699 if(same) {
1700 // here we have x = lit - x for sizeof(x)>1
1701 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1702 pic16_emitpcode(POC_SUBFWB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1703 } else {
1704 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1705 pic16_emitpcode(POC_SUBFWB_D0, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
1706 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1707 }
1708 }
1709
1710
1711 } else {
1712
1713 DEBUGpic16_emitcode ("; ","line %d result %s, left %s, right %s",__LINE__,
1714 pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1715 pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1716 pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1717
1718 if ((AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RESULT(ic)))
1719 && pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1720 // extend left in result
1721 pic16_addSign (IC_RESULT(ic), AOP_SIZE(IC_LEFT(ic)), !SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))));
1722 }
1723
1724 if ((AOP_SIZE(IC_RIGHT(ic)) < AOP_SIZE(IC_RESULT(ic)))
1725 && pic16_sameRegs (AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
1726 // extend right in result---fails if left resides in result as well...
1727 assert ((IC_LEFT(ic) == IC_RIGHT(ic)) || !pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))));
1728 pic16_addSign (IC_RESULT(ic), AOP_SIZE(IC_RIGHT(ic)), !SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))));
1729 }
1730
1731 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1732 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1733 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
1734 pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
1735 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
1736 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1737 } else {
1738
1739 DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1740 if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)
1741 pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1742
1743 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1744 pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
1745 else {
1746 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1747 pic16_emitpcode(POC_SUBLW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1748 } else {
1749 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1750 }
1751 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1752 if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1753 pic16_emitpcode(POC_BCF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1754 emitSKPZ;
1755 pic16_emitpcode(POC_BSF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1756 }else
1757 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1758 }
1759 }
1760 }
1761
1762 /*
1763 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1764
1765 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1766 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1767 } else {
1768 pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1769 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1770 }
1771 */
1772 offset = 1;
1773 size--;
1774
1775 while (size--) {
1776 if (pic16_sameRegs (AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
1777 pic16_mov2w (AOP(IC_RESULT(ic)), offset);
1778 } else if (offset < AOP_SIZE(IC_RIGHT(ic)))
1779 pic16_mov2w(AOP(IC_RIGHT(ic)),offset);
1780 else {
1781 // right operand is too short, not overwritten with result
1782 pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
1783 if (!SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1784 // signed -- sign extend the right operand
1785 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),AOP_SIZE(IC_RIGHT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1786 pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
1787 }
1788 }
1789 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1790 pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1791 } else if (offset < AOP_SIZE(IC_LEFT(ic))) {
1792 pic16_emitpcode(POC_SUBWFB_D0, pic16_popGet(AOP(IC_LEFT(ic)),offset));
1793 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1794 } else {
1795 // left operand is too short, not overwritten with result
1796 pic16_emitpcode (POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
1797 if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
1798 // signed -- sign extend the left operand
1799 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),AOP_SIZE(IC_LEFT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1800 pic16_emitpcode (POC_SETF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); // keep CARRY/#BORROW bit intact!
1801 }
1802 pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1803 }
1804 offset++;
1805 }
1806 }
1807
1808 // adjustArithmeticResult(ic);
1809
1810 release:
1811 pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1812 pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1813 pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1814 }
1815
1816
1817 /*-----------------------------------------------------------------*
1818 * pic_genMult8XLit_n - multiplication of two 8-bit numbers.
1819 *
1820 *
1821 *-----------------------------------------------------------------*/
1822 static void
pic16_genMult8XLit_n(operand * left,operand * right,operand * result)1823 pic16_genMult8XLit_n (operand *left, operand *right, operand *result)
1824 {
1825 int lit;
1826 int size = AOP_SIZE (result);
1827
1828 FENTRY;
1829 DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
1830
1831 if (AOP_TYPE (right) != AOP_LIT)
1832 {
1833 fprintf (stderr, "%s %d - right operand is not a literal\n", __FILE__, __LINE__);
1834 exit (1);
1835 }
1836
1837 lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
1838 assert ((lit >= -128) && (lit < 256) );
1839
1840 /* We need to adjust the high byte of the result (in PRODH) if
1841 * (a) literals < 0 or
1842 * (b) signed register operands < 0.
1843 *
1844 * If lit >= 0 and val is unsigned, MULLW will do the trick.
1845 *
1846 * If val is signed and 8 bit:
1847 * val = -2^7 * v_7 + SUM(2^i * v_i, i=0..6)
1848 * = -2^7 * v_7 + -2^7 * v_7 + SUM(2^i * v_i, i=0..7)
1849 * = -2^8 * v_7 + SUM(2^i * v_i, i=0..7)
1850 * = -2^8 * v_7 + UNSIGNED(val)
1851 *
1852 * For lit >= 0:
1853 * lit * val = lit * UNSIGNED(val) - 2^8 * v_7 * lit
1854 *
1855 * For lit < 0, lit = l_7 .. l_0:
1856 *
1857 * lit * val = (-2^8 * l_7 + UNSIGNED(lit)) * (-2^8 * v_7 + UNSIGNED(val))
1858 * = 2^8 * l_7 * 2^8 * v_7
1859 * - 2^8 * l_7 * UNSIGNED(val)
1860 * - 2^8 * v_7 * UNSIGNED(lit)
1861 * + UNSIGNED(lit) * UNSIGNED(val)
1862 * = 2^16 * l_7 * v_7
1863 * - 2^8 * (l_7 * UNSIGNED(val) + v_7 * UNSIGNED(lit))
1864 * + UNSIGNED(lit) * UNSIGNED(val)
1865 *
1866 * '2^16 * X' is only of interest if the result is larger than 16 * bit
1867 * ==> ignored.
1868 * '-2^8 * X' requires subtracting the original values of 'val'
1869 * respectively 'lit' from the high byte of the result.
1870 * UNSIGNED(lit) * UNSIGNED(val) can be computed via a MUL instruction.
1871 *
1872 * So, we do:
1873 * MOVF val, W
1874 * MULLW lit
1875 * # Now, PRODH:PRODL hold UNSIGNED(val) * UNSIGNED(lit)
1876 * if result > 8 bit:
1877 * if lit < 0:
1878 * SUBWF PRODH, F # -2^8 * l_7 * UNSIGNED(val)
1879 * MOVF PRODH, W
1880 * BTFSC val, 7
1881 * SUBLW lit # -2^8 * v_7 * UNSIGNED(lit)
1882 * MOVWF result[1] # this might overwrite val!
1883 * MOVFF PRODL, result[0] # this might overwrite val!
1884 */
1885
1886 pic16_mov2w (AOP (left), 0);
1887 pic16_emitpcode (POC_MULLW, pic16_popGetLit (lit & 0x00ff));
1888
1889 if (size > 1)
1890 {
1891 /* Adjust PRODH for signed operands. */
1892 if (lit < 0)
1893 {
1894 /* left is still in WREG */
1895 pic16_emitpcode (POC_SUBWF, pic16_popCopyReg (&pic16_pc_prodh));
1896 } // if
1897
1898 pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_prodh));
1899 if (!SPEC_USIGN (operandType (left)))
1900 {
1901 pic16_emitpcode (POC_BTFSC,
1902 pic16_newpCodeOpBit (pic16_aopGet (AOP (left), 0, FALSE, FALSE),
1903 7, 0, PO_GPR_REGISTER));
1904 pic16_emitpcode (POC_SUBLW, pic16_popGetLit (lit & 0x00ff));
1905 } // if
1906
1907 /* Assign result (high byte) -- this may overwrite val. */
1908 pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 1));
1909 } // if
1910
1911 /* Assign result (low byte) -- this may overwrite val. */
1912 pic16_emitpcode (POC_MOVFF,
1913 pic16_popGet2p (pic16_popCopyReg (&pic16_pc_prodl),
1914 pic16_popGet (AOP (result), 0)));
1915
1916 /* Must sign/zero-extend here if size > 2. */
1917 if (size > 2)
1918 {
1919 pic16_addSign (result, 2, !IS_UNSIGNED (operandType (left)));
1920 } // if
1921 }
1922
1923 /*-----------------------------------------------------------------*
1924 * genMult8X8_n - multiplication of two 8-bit numbers.
1925 *
1926 *
1927 *-----------------------------------------------------------------*/
1928 void
pic16_genMult8X8_n(operand * left,operand * right,operand * result)1929 pic16_genMult8X8_n (operand *left, operand *right, operand *result)
1930 {
1931 FENTRY;
1932
1933 /* Special case: multiply by literal. */
1934 if (AOP_TYPE (right) == AOP_LIT)
1935 {
1936 pic16_genMult8XLit_n (left, right, result);
1937 return;
1938 }
1939 else if (AOP_TYPE (left) == AOP_LIT)
1940 {
1941 pic16_genMult8XLit_n (right, left, result);
1942 return;
1943 } // if
1944
1945 /* cases:
1946 A = A x B B = A x B
1947 A = B x C
1948 W = A x B
1949 W = W x B W = B x W
1950 */
1951 /* if result == right then exchange left and right */
1952 if (pic16_sameRegs (AOP (result), AOP (right)))
1953 {
1954 operand *tmp;
1955 tmp = left;
1956 left = right;
1957 right = tmp;
1958 } // if
1959
1960 if (AOP_TYPE (left) != AOP_ACC)
1961 {
1962 // left is not WREG
1963 if (AOP_TYPE (right) != AOP_ACC)
1964 {
1965 pic16_mov2w (AOP (left), 0);
1966 pic16_emitpcode (POC_MULWF, pic16_popGet (AOP (right), 0));
1967 }
1968 else
1969 {
1970 pic16_emitpcode (POC_MULWF, pic16_popGet (AOP (left), 0));
1971 } // if
1972 }
1973 else
1974 {
1975 pic16_emitpcode (POC_MULWF, pic16_popGet (AOP (right), 0));
1976 } // if
1977
1978 /* result is in PRODL:PRODH */
1979 if (AOP_TYPE (result) != AOP_ACC)
1980 {
1981 int isPRODL = (AOP (result)->type != AOP_STA && ! strcmp (pic16_aopGet (AOP (result), 0, TRUE, FALSE), "_PRODL"));
1982
1983 if (AOP_SIZE (result) > 1)
1984 {
1985 /* If s8 x s8 --> s16 multiplication was called for, fixup high byte.
1986 * (left=a1a0, right=b1b0, X1: high byte, X0: low byte)
1987 *
1988 * a1a0 * b1b0
1989 * --------------
1990 * a1b0 a0b0
1991 * a1b1 a0b1
1992 * ---------------
1993 * a0b0 a1= 0, b1= 0 (both unsigned)
1994 * -b0 a0b0 a1=-1, b1= 0 (a signed and < 0, b unsigned or >= 0)
1995 * -a0 a0b0 a1= 0, b1=-1 (b signed and < 0, a unsigned or >= 0)
1996 * -(a0+b0) a0b0 a1=-1, b1=-1 (a and b signed and < 0)
1997 *
1998 * Currently, PRODH:PRODL holds a0b0 as 16 bit value; we need to
1999 * subtract a0 and/or b0 from PRODH. */
2000 if (!IS_UNSIGNED (operandType (right)))
2001 {
2002 /* right operand (b1) signed and < 0, then subtract left op (a0) */
2003 pic16_mov2w (AOP (left), 0);
2004 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (right), 0, 7));
2005 pic16_emitpcode (POC_SUBWF, pic16_popCopyReg (&pic16_pc_prodh));
2006 } // if
2007
2008 if (!IS_UNSIGNED (getSpec (operandType (left))))
2009 {
2010 /* left operand (a1) signed and < 0, then subtract right op (b0) */
2011 pic16_mov2w (AOP (right), 0 );
2012 pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (left), 0, 7));
2013 pic16_emitpcode (POC_SUBWF, pic16_popCopyReg (&pic16_pc_prodh));
2014 } // if
2015
2016 /* Assing high byte of result -- this may overwrite one of the operands. */
2017 pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet (AOP (result), 1)));
2018 } // if
2019
2020 /* Assign low byte of result -- this may overwrite one of the operands. */
2021 if (!isPRODL)
2022 {
2023 pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_prodl), pic16_popGet (AOP (result), 0)));
2024 } // if
2025
2026 /* Must sign/zero-extend here if size > 2. */
2027 if (AOP_SIZE (result) > 2)
2028 {
2029 pic16_addSign (result, 2, !IS_UNSIGNED (operandType (left)));
2030 } // if
2031 }
2032 else
2033 {
2034 pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_prodl));
2035 }
2036 }
2037