+static void
+genOrOp (iCode * ic)
+{
+ operand *left, *right, *result;
+ symbol *tlbl;
+ int size, offset;
+
+ /* note here that || operations that are in an
+ if statement are taken away by backPatchLabels
+ only those used in arthmetic operations remain */
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+ aopOp ((result = IC_RESULT (ic)), ic, FALSE);
+
+ tlbl = newiTempLabel (NULL);
+ toBoolean (left, "r0", TRUE);
+ toBoolean (right, "r0", FALSE);
+ emitcode ("ldi", "r24,1");
+ emitcode ("breq", "L%05d", tlbl->key);
+ emitcode ("dec", "r24");
+ emitcode ("", "L%05d:", tlbl->key);
+ aopPut (AOP (result), "r24", 0);
+ size = AOP_SIZE (result) - 1;
+ offset = 1;
+ while (size--)
+ aopPut (AOP (result), zero, offset++);
+
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+enum {
+ AVR_AND = 0, AVR_OR, AVR_XOR
+};
+static char *bopnames_lit[] = { "andi", "ori" };
+static char *bopnames[] = { "and", "or", "eor" };
+/*-----------------------------------------------------------------*/
+/* genBitWise - generate bitwise operations */
+/*-----------------------------------------------------------------*/
+static void
+genBitWise (iCode * ic, iCode * ifx, int bitop)
+{
+ operand *left, *right, *result;
+ int size, offset = 0;
+ char *l;
+ symbol *lbl, *lbl1;
+ int samerl, samerr;
+
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+ aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+ size = AOP_SIZE (left);
+ offset = 0;
+ if (ifx) { /* used only for jumps */
+ if (AOP_TYPE (right) == AOP_LIT &&
+ (bitop == AVR_AND || bitop == AVR_OR)) {
+ int lit =
+ (int) floatFromVal (AOP (right)->aopu.
+ aop_lit);
+ int p2 = powof2 (lit);
+ if (bitop == AVR_AND && (p2 >= 0)) { /* right side is a power of 2 */
+ l = aopGet (AOP (left), p2 / 8);
+ if (IC_TRUE (ifx)) {
+ emitcode ("sbrc", "%s,%d", l,
+ (p2 % 8));
+ emitcode ("rjmp", "L%05d",
+ IC_TRUE (ifx)->key);
+ }
+ else {
+ emitcode ("sbrs", "%s,%d", l,
+ (p2 % 8));
+ emitcode ("rjmp", "L%05d",
+ IC_FALSE (ifx)->key);
+ }
+ }
+ else { /* right not power of two */
+ int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
+ if (size == 1) {
+ if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
+ emitcode (bopnames_lit[bitop],
+ "%s,<(%d)",
+ aopGet (AOP (IC_LEFT (ic)), 0), lit);
+ }
+ else {
+ MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
+ emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
+ }
+ lbl = newiTempLabel (NULL);
+ if (IC_TRUE (ifx)) {
+ emitcode ("breq", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+ }
+ else {
+ emitcode ("brne", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
+ }
+ emitcode ("", "L%05d:", lbl->key);
+ }
+ else if (size == 2) {
+ emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
+ emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
+ emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
+ emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
+ emitcode ("sbiw", "r24,0");
+ lbl = newiTempLabel (NULL);
+ if (IC_TRUE (ifx)) {
+ emitcode ("breq", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+ }
+ else {
+ emitcode ("brne", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
+ }
+ emitcode ("", "L%05d:", lbl->key);
+ }
+ else {
+ lbl = newiTempLabel (NULL);
+ lbl1 = newiTempLabel (NULL);
+ while (size--) {
+ if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
+ emitcode (bopnames_lit [bitop], "%s,<(%d)",
+ aopGet (AOP (IC_LEFT (ic)), offset),
+ lit);
+ }
+ else {
+ char *l = aopGet (AOP (IC_LEFT (ic)), offset);
+ MOVR24 (l);
+ emitcode ("andi", "r24,<(%d)", lit);
+ }
+ emitcode ("brne", "L%05d", lbl->key);
+ offset++;
+ }
+ /* all are zero */
+ if (IC_FALSE (ifx))
+ emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
+ else
+ emitcode ("rjmp", "L%05d", lbl1->key);
+ emitcode ("", "L%05d:", lbl->key);
+ /* not zero */
+ if (IC_TRUE (ifx))
+ emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+ emitcode ("", "L%05d:", lbl1->key);
+
+ }
+ }
+ }
+ else { /* right is not a literal */
+ int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
+ int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
+ if (size == 1) {
+ if (eh) {
+ emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
+ aopGet (AOP (IC_RIGHT (ic)), 0));
+ }
+ else if (reh) {
+ emitcode (bopnames[bitop], "%s,%s",
+ aopGet (AOP (IC_RIGHT (ic)), 0),
+ aopGet (AOP (IC_LEFT (ic)), 0));
+ }
+ else {
+ MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
+ emitcode (bopnames[bitop], "r0,%s",
+ aopGet (AOP (IC_RIGHT (ic)), 0));
+ }
+ lbl = newiTempLabel (NULL);
+ if (IC_TRUE (ifx)) {
+ emitcode ("breq", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d",
+ IC_TRUE (ifx)->key);
+ }
+ else {
+ emitcode ("brne", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d",
+ IC_FALSE (ifx)->key);
+ }
+ emitcode ("", "L%05d:", lbl->key);
+ }
+ else if (size == 2) {
+ emitcode ("mov", "r24,%s",
+ aopGet (AOP (IC_LEFT (ic)), 0));
+ emitcode ("mov", "r25,%s",
+ aopGet (AOP (IC_LEFT (ic)), 1));
+ emitcode (bopnames[bitop], "r24,%s",
+ aopGet (AOP (IC_RIGHT (ic)), 0));
+ emitcode (bopnames[bitop], "r25,%s",
+ aopGet (AOP (IC_RIGHT (ic)), 1));
+ emitcode ("sbiw", "r24,0");
+ lbl = newiTempLabel (NULL);
+ if (IC_TRUE (ifx)) {
+ emitcode ("breq", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+ }
+ else {
+ emitcode ("brne", "L%05d", lbl->key);
+ emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
+ }
+ emitcode ("", "L%05d:", lbl->key);
+ }
+ else {
+ lbl = newiTempLabel (NULL);
+ lbl1 = newiTempLabel (NULL);
+ while (size--) {
+ if (eh) {
+ emitcode (bopnames[bitop], "%s,%s",
+ aopGet (AOP (IC_LEFT (ic)), offset),
+ aopGet (AOP (IC_RIGHT (ic)), offset));
+ }
+ else if (reh) {
+ emitcode (bopnames[bitop], "%s,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset),
+ aopGet (AOP (IC_LEFT (ic)), offset));
+ }
+ else {
+ MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
+ emitcode (bopnames[bitop], "r0,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset));
+ }
+ emitcode ("brne", "L%05d", lbl->key);
+ offset++;
+ }
+ /* all are zero */
+ if (IC_FALSE (ifx))
+ emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
+ else
+ emitcode ("rjmp", "L%05d", lbl1->key);
+ emitcode ("", "L%05d:", lbl->key);
+ /* not zero */
+ if (IC_TRUE (ifx))
+ emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+ emitcode ("", "L%05d:", lbl1->key);
+
+ }
+ }
+ goto release;
+ }
+
+ /* result needs to go a register */
+ samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
+ samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
+ while (size--) {
+ if (AOP_TYPE (right) == AOP_LIT) {
+ unsigned int lit =
+ (int) floatFromVal (AOP (right)->aopu.
+ aop_lit);
+ if (((lit >> (8 * offset)) & 0xff) == 0) {
+ if (bitop == AVR_AND) {
+ aopPut (AOP (result), zero, offset++);
+ continue;
+ }
+ else if (bitop == AVR_OR) {
+ if (!samerl)
+ aopPut (AOP (result),
+ aopGet (AOP (left),
+ offset),
+ offset);
+ offset++;
+ continue;
+ }
+ }
+ }
+ if (samerl) {
+ if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
+ AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
+ (bitop == AVR_AND || bitop == AVR_OR)) {
+ emitcode (bopnames_lit[bitop], "%s,%s(%d)",
+ aopGet (AOP (IC_LEFT (ic)), offset),
+ larray[offset],
+ (int) floatFromVal (AOP (right)-> aopu.aop_lit));
+ }
+ else {
+ emitcode (bopnames[bitop], "%s,%s",
+ aopGet (AOP (IC_LEFT (ic)), offset),
+ aopGet (AOP (IC_RIGHT (ic)), offset));
+ }
+ }
+ else if (samerr) {
+ emitcode (bopnames[bitop], "%s,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset),
+ aopGet (AOP (IC_LEFT (ic)), offset));
+ }
+ else {
+ aopPut (AOP (IC_RESULT (ic)),
+ aopGet (AOP (IC_LEFT (ic)), offset), offset);
+ emitcode (bopnames[bitop],
+ aopGet (AOP (IC_RESULT (ic)), offset),
+ aopGet (AOP (IC_RIGHT (ic)), offset));
+ }
+ offset++;
+ }
+ release:
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genAnd - code for and */
+/*-----------------------------------------------------------------*/
+static void
+genAnd (iCode * ic, iCode * ifx)
+{
+ genBitWise (ic, ifx, AVR_AND);
+}
+
+/*-----------------------------------------------------------------*/
+/* genOr - code for or */
+/*-----------------------------------------------------------------*/
+static void
+genOr (iCode * ic, iCode * ifx)
+{
+ genBitWise (ic, ifx, AVR_OR);
+}
+
+/*-----------------------------------------------------------------*/
+/* genXor - code for xclusive or */
+/*-----------------------------------------------------------------*/
+static void
+genXor (iCode * ic, iCode * ifx)
+{
+ genBitWise (ic, ifx, AVR_XOR);
+}
+
+/*-----------------------------------------------------------------*/
+/* genInline - write the inline code out */
+/*-----------------------------------------------------------------*/
+static void
+genInline (iCode * ic)
+{
+ char *buffer, *bp, *bp1;
+
+ _G.inLine += (!options.asmpeep);
+
+ buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
+ strcpy (buffer, IC_INLINE (ic));
+
+ /* emit each line as a code */
+ while (*bp) {
+ if (*bp == '\n') {
+ *bp++ = '\0';
+ emitcode (bp1, "");
+ bp1 = bp;
+ }
+ else {
+ if (*bp == ':') {
+ bp++;
+ *bp = '\0';
+ bp++;
+ emitcode (bp1, "");
+ bp1 = bp;
+ }
+ else
+ bp++;
+ }
+ }
+ if (bp1 != bp)
+ emitcode (bp1, "");
+ /* emitcode("",buffer); */
+ _G.inLine -= (!options.asmpeep);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRotC - rotate right/left with carry , lr = 1 rotate right */
+/*-----------------------------------------------------------------*/
+static void
+genRotC (iCode * ic, int lr)
+{
+ operand *left, *result;
+ int size, offset = 0;
+
+ /* rotate right with carry */
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+
+ /* move it to the result */
+ size = AOP_SIZE (result);
+ if (!sameRegs (AOP (left), AOP (result))) {
+ offset = 0;
+ while (size--) {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset), offset);
+ offset++;
+ }
+ size = AOP_SIZE (result);
+ }
+ if (lr)
+ offset = size - 1;
+ else
+ offset = 0;
+
+ CLRC;
+ emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
+ (lr ? 0 : 7));
+ emitcode ("sec", "");
+
+ while (size--) {
+ emitcode ((lr ? "ror" : "rol"), "%s",
+ aopGet (AOP (result), offset));
+ if (lr)
+ offset--;
+ else
+ offset++;
+ }
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry */
+/*-----------------------------------------------------------------*/
+static void
+genRRC (iCode * ic)
+{
+ genRotC (ic, 1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry */
+/*-----------------------------------------------------------------*/
+static void
+genRLC (iCode * ic)
+{
+ genRotC (ic, 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetHbit - generates code get highest order bit */
+/*-----------------------------------------------------------------*/
+static void
+genGetHbit (iCode * ic)
+{
+ operand *left, *result;
+ int size, offset;
+
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+
+ size = AOP_SIZE (result);
+ if (!sameRegs (AOP (left), AOP (result))) {
+ emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
+ emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
+ emitcode ("subi", "%s,<(-1)",
+ aopGet (AOP (result), size - 1));
+ }
+ else {
+ emitcode ("clr", "r0");
+ emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
+ emitcode ("subi", "r0,<(-1)");
+ aopPut (AOP (result), "r0", 0);
+ }
+ offset = 1;
+ size--;
+ while (size--) {
+ emitcode ("clr", aopGet (AOP (result), offset++));
+ }
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genShiftLeftLit - shift left by a known amount */
+/*-----------------------------------------------------------------*/
+static void
+genShiftLeftLit (iCode * ic)
+{
+ operand *left, *right, *result;
+ int size, shCount, offset = 0;
+ int lByteZ = 0;
+
+ right = IC_RIGHT (ic);
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+ size = AOP_SIZE (result);
+ shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ if (shCount > (size * 8 - 1)) {
+ while (size--)
+ aopPut (AOP (result), zero, offset++);
+ goto release;
+ }
+ switch (size) {
+ case 1:
+ if (!sameRegs (AOP (left), AOP (result)))
+ aopPut (AOP (result), aopGet (AOP (left), 0), 0);
+ if (shCount >= 4) {
+ if (AOP_ISHIGHREG(AOP(result),0)) {
+ emitcode ("swap", "%s", aopGet (AOP (result), 0));
+ emitcode ("andi", "%s,0xf0");
+ } else {
+ emitcode ("ldi","r24,0xf0");
+ emitcode ("swap", "%s", aopGet (AOP (result), 0));
+ emitcode ("and", "%s,r24");
+ }
+ shCount -= 4;
+ }
+ if (shCount == 1) {
+ emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
+ aopGet (AOP (result), 0));
+ shCount--;
+ }
+ while (shCount--)
+ emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+ break;
+ case 2:
+ if (shCount >= 12) {
+ aopPut (AOP (result), aopGet (AOP (left), 0), 1);
+ aopPut (AOP (result), zero, 0);
+ emitcode ("swap", "%s", aopGet (AOP (result), 1));
+ if (AOP_ISHIGHREG(AOP(result),1)) {
+ emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
+ } else {
+ emitcode ("ldi","r24,0xf0");
+ emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
+ }
+ shCount -= 12;
+ lByteZ = 1;
+ }
+ if (shCount >= 8) {
+ aopPut (AOP (result), aopGet (AOP (left), 0), 1);
+ aopPut (AOP (result), zero, 0);
+ shCount -= 8;
+ lByteZ = 1;
+ }
+ if (shCount >= 4) {
+ shCount -= 4;
+ if (!sameRegs (AOP (left), AOP (result))) {
+ aopPut (AOP (result), aopGet (AOP (left), 0),
+ 0);
+ aopPut (AOP (result), aopGet (AOP (left), 1),
+ 1);
+ }
+ emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
+ emitcode ("andi", "r24,0x0f");
+ if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
+ emitcode("ldi","r25,0xf0");
+ }
+ emitcode ("swap", "%s", aopGet (AOP (result), 0));
+ if (AOP_ISHIGHREG(AOP(result),0)) {
+ emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
+ } else {
+ emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
+ }
+ emitcode ("swap", "%s", aopGet (AOP (result), 1));
+ if (AOP_ISHIGHREG(AOP(result),1)) {
+ emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
+ } else {
+ emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
+ }
+ emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
+ while (shCount--) {
+ emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+ emitcode ("rol", "%s", aopGet (AOP (result), 1));
+ }
+ }
+ if (!lByteZ && !sameRegs (AOP (result), AOP (left))
+ && shCount) {
+ offset = 0;
+ while (size--) {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset), offset);
+ offset++;
+ }
+ }
+ while (shCount--) {
+ if (lByteZ) {
+ emitcode ("lsl", "%s", aopGet (AOP (result), 1));
+ }
+ else {
+ emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+ emitcode ("rol", "%s", aopGet (AOP (result), 1));
+ }
+ }
+ break;
+ case 3:
+ assert ("shifting generic pointer ?\n");
+ break;
+ case 4:
+ /* 32 bits we do only byte boundaries */
+ if (shCount >= 24) {
+ aopPut (AOP (result), aopGet (AOP (left), 0), 3);
+ aopPut (AOP (result), zero, 2);
+ aopPut (AOP (result), zero, 1);
+ aopPut (AOP (result), zero, 0);
+ lByteZ = 3;
+ shCount -= 24;
+ }
+ if (shCount >= 16) {
+ aopPut (AOP (result), aopGet (AOP (left), 0), 3);
+ aopPut (AOP (result), aopGet (AOP (left), 1), 2);
+ aopPut (AOP (result), zero, 1);
+ aopPut (AOP (result), zero, 0);
+ lByteZ = 2;
+ shCount -= 16;
+ }
+ if (shCount >= 8) {
+ aopPut (AOP (result), aopGet (AOP (left), 0), 3);
+ aopPut (AOP (result), aopGet (AOP (left), 1), 2);
+ aopPut (AOP (result), aopGet (AOP (left), 2), 1);
+ aopPut (AOP (result), zero, 0);
+ shCount -= 8;
+ lByteZ = 1;
+ }
+ if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
+ offset = 0;
+ while (size--) {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset), offset);
+ offset++;
+ }
+ offset = 0;
+ size = AOP_SIZE (result);
+ }
+ if (shCount) {
+ switch (lByteZ) {
+ case 0:
+ while (shCount--) {
+ emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+ emitcode ("rol", "%s", aopGet (AOP (result), 1));
+ emitcode ("rol", "%s", aopGet (AOP (result), 2));
+ emitcode ("rol", "%s", aopGet (AOP (result), 3));
+ }
+ break;
+ case 1:
+ while (shCount--) {
+ emitcode ("lsl", "%s", aopGet (AOP (result), 1));
+ emitcode ("rol", "%s", aopGet (AOP (result), 2));
+ emitcode ("rol", "%s", aopGet (AOP (result), 3));
+ }
+ break;
+ case 2:
+ while (shCount--) {
+ emitcode ("lsl", "%s", aopGet (AOP (result), 2));
+ emitcode ("rol", "%s", aopGet (AOP (result), 3));
+ }
+ break;
+ case 3:
+ while (shCount--) {
+ emitcode ("lsl", "%s", aopGet (AOP (result), 3));
+ }
+ break;
+ }
+ }
+ }
+
+ release:
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (right, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting */
+/*-----------------------------------------------------------------*/
+static void
+genLeftShift (iCode * ic)
+{
+ operand *left, *right, *result;
+ int size, offset;
+ symbol *tlbl;
+
+ right = IC_RIGHT (ic);
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+
+ aopOp (right, ic, FALSE);
+
+ if (AOP_TYPE (right) == AOP_LIT) {
+ genShiftLeftLit (ic);
+ return;
+ }
+
+ /* unknown count */
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+ size = AOP_SIZE (result);
+ offset = 0;
+ if (AOP_SIZE (right) > 1) {
+ if (isRegPair (AOP (right))) {
+ emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
+ }
+ else {
+ emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+ emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
+ }
+ }
+ else {
+ emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+ }
+ if (!sameRegs (AOP (left), AOP (result))) {
+ while (size--) {
+ aopPut (AOP (result), aopGet (AOP (left), offset),
+ offset);
+ offset++;
+ }
+ size = AOP_SIZE (result);
+ }
+ tlbl = newiTempLabel (NULL);
+ emitcode ("", "L%05d:", tlbl->key);
+ offset = 0;
+ while (size--) {
+ if (offset)
+ emitcode ("rol", "%s", aopGet (AOP (result), offset));
+ else
+ emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+ offset++;
+ }
+ if (AOP_SIZE (right) > 1)
+ emitcode ("sbiw", "r24,1");
+ else
+ emitcode ("dec", "r24");
+ emitcode ("brne", "L%05d", tlbl->key);
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (right, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genShiftRightLit - generate for right shift with known count */
+/*-----------------------------------------------------------------*/
+static void
+genShiftRightLit (iCode * ic)
+{
+ operand *left = IC_LEFT (ic)
+ , *right = IC_RIGHT (ic)
+ , *result = IC_RESULT (ic);
+ int size, shCount, offset = 0;
+ int hByteZ = 0;
+ sym_link *letype = getSpec (operandType (left));
+ int sign = !SPEC_USIGN (letype);
+
+ right = IC_RIGHT (ic);
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+ size = AOP_SIZE (result);
+ shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ /* if signed then give up and use a loop to shift */
+ if (sign) {
+ symbol *tlbl;
+ if (!sameRegs (AOP (left), AOP (result))) {
+ while (size--) {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset), offset);
+ offset++;
+ }
+ size = AOP_SIZE (result);
+ offset = 0;
+ }
+ /* be as economical as possible */
+ if (shCount <= 4) {
+ while (shCount--) {
+ size = AOP_SIZE (result);
+ offset = size - 1;
+ while (size--) {
+ /* highest order byte */
+ if (offset == (AOP_SIZE(result)-1))
+ emitcode ("asr", "%s", aopGet (AOP (result), offset));
+ else
+ emitcode ("ror", "%s", aopGet (AOP (result), offset));
+ offset--;
+ }
+ }
+ }
+ else {
+ emitcode ("ldi", "r24,<(%d)", shCount);
+ tlbl = newiTempLabel (NULL);
+ emitcode ("", "L%05d:", tlbl->key);
+ offset = size - 1;
+ while (size--) {
+ if (offset == (AOP_SIZE(result) - 1))
+ emitcode ("asr", "%s", aopGet (AOP (result), offset));
+ else
+ emitcode ("ror", "%s", aopGet (AOP (result), offset));
+ offset--;
+ }
+ emitcode ("dec", "r24");
+ emitcode ("brne", "L%05d", tlbl->key);
+ }
+ goto release;
+ }
+ if (shCount > (size * 8 - 1)) {
+ while (size--)
+ aopPut (AOP (result), zero, offset++);
+ goto release;
+ }
+ /* for unsigned we can much more efficient */
+ switch (size) {
+ case 1:
+ if (!sameRegs (AOP (left), AOP (result)))
+ aopPut (AOP (result), aopGet (AOP (left), 0), 0);
+ if (shCount >= 4) {
+ emitcode ("swap", "%s", aopGet (AOP (result), 0));
+ if (AOP_ISHIGHREG(AOP(result),0)) {
+ emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
+ } else {
+ emitcode ("ldi","r24,0x0f");
+ emitcode ("and", "%s,r24",aopGet(AOP(result),0));
+ }
+ shCount -= 4;
+ }
+ while (shCount--)
+ emitcode ("lsr", "%s", aopGet (AOP (result), 0));
+ break;
+ case 2:
+ if (shCount >= 12) {
+ aopPut (AOP (result), aopGet (AOP (left), 1), 0);
+ aopPut (AOP (result), zero, 1);
+ emitcode ("swap", "%s", aopGet (AOP (result), 0));
+ if (AOP_ISHIGHREG(AOP(result),0)) {
+ emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
+ } else {
+ emitcode ("ldi","r24,0x0f");
+ emitcode ("and", "%s,r24",aopGet(AOP(result),0));
+ }
+ shCount -= 12;
+ hByteZ = 1;
+ }
+ if (shCount >= 8) {
+ aopPut (AOP (result), aopGet (AOP (left), 1), 0);
+ aopPut (AOP (result), zero, 1);
+ shCount -= 8;
+ hByteZ = 1;
+ }
+ if (shCount >= 4) {
+ shCount -= 4;
+ if (!sameRegs (AOP (left), AOP (result))) {
+ aopPut (AOP (result), aopGet (AOP (left), 0), 0);
+ aopPut (AOP (result), aopGet (AOP (left), 1), 1);
+ }
+ if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
+ emitcode("ldi","r25,0x0f");
+ }
+ emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
+ emitcode ("andi", "r24,0xf0");
+ emitcode ("swap", "%s", aopGet (AOP (result), 0));
+ if (AOP_ISHIGHREG(AOP(result),0)) {
+ emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
+ } else {
+ emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
+ }
+ emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
+ emitcode ("swap", "%s", aopGet (AOP (result), 1));
+ if (AOP_ISHIGHREG(AOP(result),1)) {
+ emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
+ } else {
+ emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
+ }
+ while (shCount--) {
+ emitcode ("lsr", "%s", aopGet (AOP (result), 1));
+ emitcode ("ror", "%s", aopGet (AOP (result), 0));
+ }
+
+ }
+ if (!hByteZ && !sameRegs (AOP (result), AOP (left))
+ && shCount) {
+ offset = 0;
+ while (size--) {
+ aopPut (AOP (result), aopGet (AOP (left), offset), offset);
+ offset++;
+ }
+ }
+ while (shCount--) {
+ if (hByteZ) {
+ emitcode ("lsr", "%s", aopGet (AOP (result), 0));
+ }
+ else {
+ emitcode ("lsr", "%s", aopGet (AOP (result), 1));
+ emitcode ("ror", "%s", aopGet (AOP (result), 0));
+ }
+ }
+ break;
+
+ case 3:
+ assert ("shifting generic pointer ?\n");
+ break;
+ case 4:
+ /* 32 bits we do only byte boundaries */
+ if (shCount >= 24) {
+ aopPut (AOP (result), aopGet (AOP (left), 3), 0);
+ aopPut (AOP (result), zero, 1);
+ aopPut (AOP (result), zero, 2);
+ aopPut (AOP (result), zero, 3);
+ hByteZ = 3;
+ shCount -= 24;
+ }
+ if (shCount >= 16) {
+ aopPut (AOP (result), aopGet (AOP (left), 3), 1);
+ aopPut (AOP (result), aopGet (AOP (left), 2), 0);
+ aopPut (AOP (result), zero, 2);
+ aopPut (AOP (result), zero, 3);
+ hByteZ = 2;
+ shCount -= 16;
+ }
+ if (shCount >= 8) {
+ aopPut (AOP (result), aopGet (AOP (left), 1), 0);
+ aopPut (AOP (result), aopGet (AOP (left), 2), 1);
+ aopPut (AOP (result), aopGet (AOP (left), 3), 2);
+ aopPut (AOP (result), zero, 3);
+ shCount -= 8;
+ hByteZ = 1;
+ }
+ if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
+ offset = 0;
+ while (size--) {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset), offset);
+ offset++;
+ }
+ offset = 0;
+ size = AOP_SIZE (result);
+ }
+ if (shCount) {
+ switch (hByteZ) {
+ case 0:
+ while (shCount--) {
+ emitcode ("lsr", "%s", aopGet (AOP (result), 3));
+ emitcode ("ror", "%s", aopGet (AOP (result), 2));
+ emitcode ("ror", "%s", aopGet (AOP (result), 1));
+ emitcode ("ror", "%s", aopGet (AOP (result), 0));
+ }
+ break;
+ case 1:
+ while (shCount--) {
+ emitcode ("lsr", "%s", aopGet (AOP (result), 2));
+ emitcode ("ror", "%s", aopGet (AOP (result), 1));
+ emitcode ("ror", "%s", aopGet (AOP (result), 0));
+ }
+ break;
+ case 2:
+ while (shCount--) {
+ emitcode ("lsr", "%s", aopGet (AOP (result), 1));
+ emitcode ("ror", "%s", aopGet (AOP (result), 0));
+ }
+ break;
+ case 3:
+ while (shCount--) {
+ emitcode ("lsr", "%s", aopGet (AOP (result), 0));
+ }
+ break;
+ }
+ }
+ }
+ release:
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (right, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting */
+/*-----------------------------------------------------------------*/
+static void
+genRightShift (iCode * ic)
+{
+ operand *right, *left, *result;
+ sym_link *letype;
+ int size, offset;
+ int sign = 0, first = 1;
+ symbol *tlbl;
+
+ aopOp (right = IC_RIGHT (ic), ic, FALSE);
+
+ if (AOP_TYPE (right) == AOP_LIT) {
+ genShiftRightLit (ic);
+ return;
+ }
+ /* unknown count */
+ if (AOP_SIZE (right) > 1) {
+ if (isRegPair (AOP (right))) {
+ emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
+ }
+ else {
+ emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+ emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
+ }
+ }
+ else {
+ emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+ }
+ aopOp (left = IC_LEFT (ic), ic, FALSE);
+ aopOp (result = IC_RESULT (ic), ic, FALSE);
+ size = AOP_SIZE (result);
+ tlbl = newiTempLabel (NULL);
+ emitcode ("", "L%05d:", tlbl->key);
+ offset = size - 1;
+ letype = getSpec (operandType (left));
+ sign = !SPEC_USIGN (letype);
+ if (!sameRegs (AOP (left), AOP (result))) {
+ while (size--) {
+ aopPut (AOP (result), aopGet (AOP (left), offset), offset);
+ offset++;
+ }
+ size = AOP_SIZE (result);
+ }
+ size = AOP_SIZE (result);
+ while (size--) {
+ if (first) {
+ if (sign)
+ emitcode ("asr", "%s", aopGet (AOP (result), offset));
+ else
+ emitcode ("lsr", "%s", aopGet (AOP (result), offset));
+ first = 0;
+ }
+ else
+ emitcode ("ror", "%s", aopGet (AOP (result), offset));
+ offset--;
+ }
+ if (AOP_SIZE (right) > 1)
+ emitcode ("sbiw", "r24,1");
+ else
+ emitcode ("dec", "r24");
+ emitcode ("brne", "L%05d", tlbl->key);
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* RRsh - shift right rn by known count */
+/*-----------------------------------------------------------------*/
+static void
+RRsh (int shCount,int reg)
+{
+ shCount &= 0x0007; // shCount : 0..7
+
+ switch (shCount) {
+ case 0:
+ break;
+ case 1:
+ emitcode ("lsr", "r%d",reg);
+ break;
+ case 2:
+ emitcode ("lsr", "r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ break;
+ case 3:
+ emitcode ("swap", "r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ break;
+ case 4:
+ emitcode ("swap", "r%d",reg);
+ break;
+ case 5:
+ emitcode ("swap", "r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ break;
+ case 6:
+ emitcode ("swap","r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ break;
+ case 7:
+ emitcode ("swap","r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* RLsh - shift left rn by known count */
+/*-----------------------------------------------------------------*/
+static void
+RLsh (int shCount, int reg)
+{
+ shCount &= 0x0007; // shCount : 0..7
+
+ switch (shCount) {
+ case 0:
+ break;
+ case 1:
+ emitcode ("lsl", "r%d",reg);
+ break;
+ case 2:
+ emitcode ("lsl", "r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ break;
+ case 3:
+ emitcode ("swap","r%d",reg);
+ emitcode ("lsr", "r%d",reg);
+ break;
+ case 4:
+ emitcode ("swap", "r%d",reg);
+ break;
+ case 5:
+ emitcode ("swap","r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ break;
+ case 6:
+ emitcode ("swap","r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ break;
+ case 7:
+ emitcode ("swap","r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ emitcode ("lsl", "r%d",reg);
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits */
+/*-----------------------------------------------------------------*/
+static void
+genUnpackBits (operand * result, char *rname, int ptype)
+{
+ int shCnt;
+ int rlen = 0;
+ sym_link *etype;
+ int offset = 0;
+ int rsize;
+
+ etype = getSpec (operandType (result));
+ rsize = getSize (operandType (result));
+ /* read the first byte */
+ switch (ptype) {
+
+ case POINTER:
+ case IPOINTER:
+ case PPOINTER:
+ case FPOINTER:
+ emitcode ("ld", "r24,%s+", rname);
+ break;
+
+ case CPOINTER:
+ emitcode ("lpm", "r24,%s+", rname);
+ break;
+
+ case GPOINTER:
+ emitcode ("call","__gptrget_pi");
+ emitcode ("mov","r24,r0");
+ break;
+ }
+
+ rlen = SPEC_BLEN (etype);
+
+ /* if we have bitdisplacement then it fits */
+ /* into this byte completely or if length is */
+ /* less than a byte */
+ if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8)) {
+
+ /* shift right acc */
+ RRsh (shCnt,24);
+
+ emitcode ("andi", "r24,lo(0x%x)",
+ ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
+ aopPut (AOP (result), "r24", offset++);
+ goto finish;
+ }
+
+ /* bit field did not fit in a byte */
+ aopPut (AOP (result), "r24", offset++);
+
+ while (1) {
+
+ switch (ptype) {
+
+ case POINTER:
+ case IPOINTER:
+ case PPOINTER:
+ case FPOINTER:
+ emitcode ("ld", "r24,%s+");
+ break;
+
+ case CPOINTER:
+ emitcode ("lpm", "r24,%s+");
+ break;
+
+ case GPOINTER:
+ emitcode ("call", "__gptrget_pi");
+ break;
+ }
+
+ rlen -= 8;
+ /* if we are done */
+ if (rlen < 8)
+ break;
+
+ aopPut (AOP (result), "r24", offset++);
+
+ }
+
+ if (rlen) {
+ aopPut (AOP (result), "r24", offset++);
+ }
+
+ finish:
+ if (offset < rsize) {
+ rsize -= offset;
+ while (rsize--)
+ aopPut (AOP (result), zero, offset++);
+ }
+ return;
+}
+
+/*-----------------------------------------------------------------*/
+/* genDataPointerGet - generates code when ptr offset is known */
+/*-----------------------------------------------------------------*/
+static void
+genDataPointerGet (operand * left, operand * result, iCode * ic)
+{
+ char *l;
+ char buffer[256];
+ int size, offset = 0;
+ aopOp (result, ic, TRUE);
+
+ /* get the string representation of the name */
+ l = aopGet (AOP (left), 0);
+ size = AOP_SIZE (result);
+ while (size--) {
+ if (offset)
+ sprintf (buffer, "(%s + %d)", l, offset);
+ else
+ sprintf (buffer, "%s", l);
+ emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
+ buffer);
+ }
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genNearPointerGet - emitcode for near pointer fetch */
+/*-----------------------------------------------------------------*/
+static void
+genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
+{
+ asmop *aop = NULL;
+ regs *preg = NULL;
+ int gotFreePtr = 0;
+ char *rname, *frname = NULL;
+ sym_link *rtype, *retype;
+ sym_link *ltype = operandType (left);
+
+ rtype = operandType (result);
+ retype = getSpec (rtype);
+
+ aopOp (left, ic, FALSE);
+
+ /* if left is rematerialisable and
+ result is not bit variable type and
+ the left is pointer to data space i.e
+ lower 128 bytes of space */
+ if (AOP_TYPE (left) == AOP_IMMD &&
+ !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
+ genDataPointerGet (left, result, ic);
+ return;
+ }
+
+ /* if the value is already in a pointer register
+ then don't need anything more */
+ if (!AOP_INPREG (AOP (left))) {
+ /* otherwise get a free pointer register */
+ aop = newAsmop (0);
+ preg = getFreePtr (ic, &aop, FALSE, 0);
+ if (isRegPair (AOP (left) )) {
+ emitcode ("movw", "%s,%s",
+ aop->aopu.aop_ptr->name,
+ aopGet(AOP(left),0));
+ } else {
+ emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
+ aopGet (AOP (left), 0));
+ emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
+ aopGet (AOP (left), 1));
+ }
+ gotFreePtr = 1;
+ }
+ else {
+ aop = AOP(left);
+ frname = aopGet(aop,0);
+ }
+ if (AOP_ISX(aop)) {
+ rname = "X";
+ } else if (AOP_ISZ(aop)) {
+ rname = "Z";
+ } else {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "pointer not in correct register");
+ exit (0);
+ }
+
+ aopOp (result, ic, FALSE);
+
+ /* if bitfield then unpack the bits */
+ if (IS_BITVAR (retype))
+ genUnpackBits (result, rname, POINTER);
+ else {
+ /* we have can just get the values */
+ int size = AOP_SIZE (result);
+ int offset = 0;
+
+ while (size--) {
+ if (size || pi) {
+ emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
+ } else {
+ emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
+ }
+ }
+ }
+
+ /* now some housekeeping stuff */
+ if (gotFreePtr) {
+ /* we had to allocate for this iCode */
+ if (pi) {
+ if (isRegPair (AOP (left) )) {
+ emitcode ("movw", "%s,%s",
+ aopGet (AOP(left),0),
+ aop->aopu.aop_ptr->name);
+ } else {
+ emitcode ("mov", "%s,%s",
+ aopGet (AOP (left), 0),
+ aop->aopu.aop_ptr->name);
+ emitcode ("mov", "%s,%s",
+ aopGet (AOP (left), 1),
+ aop->aop_ptr2->name);
+ }
+ }
+ freeAsmop (NULL, aop, ic, TRUE);
+ } else {
+
+ /* we did not allocate which means left
+ already in a pointer register, then
+ if size > 0 && this could be used again
+ we have to point it back to where it
+ belongs */
+ if ((AOP_SIZE (result) > 1 &&
+ !OP_SYMBOL (left)->remat &&
+ (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) && !pi) {
+ int size = AOP_SIZE (result) - 1;
+ emitcode ("sbiw", "%s,%d",frname,size);
+ }
+ }
+
+ /* done */
+ if (pi) pi->generated = 1;
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genCodePointerGet - gget value from code space */
+/*-----------------------------------------------------------------*/
+static void
+genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
+{
+ int size, offset;
+ sym_link *retype = getSpec (operandType (result));
+ asmop *aop = NULL;
+ int gotFreePtr = 0;
+
+ aopOp (left, ic, FALSE);
+
+ /* if the operand is already in Z register
+ then we do nothing else we move the value to Z register */
+ if (AOP_ISZ(AOP(left))) {
+ aop = AOP (left);
+ } else {
+ aop = newAsmop(0);
+ getFreePtr(ic,&aop,FALSE,TRUE);
+ if (isRegPair(AOP (left))) {
+ emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
+ } else {
+ emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
+ emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
+ }
+ gotFreePtr = 1;
+ }
+
+ aopOp (result, ic, FALSE);
+
+ /* if bit then unpack */
+ if (IS_BITVAR (retype))
+ genUnpackBits (result, "Z", CPOINTER);
+ else {
+ size = AOP_SIZE (result);
+ offset = 0;
+
+ while (size--) {
+ if (size || pi) {
+ emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
+ } else {
+ emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
+ }
+ }
+ }
+
+ /* now some housekeeping stuff */
+ if (gotFreePtr) {
+ /* we had to allocate for this iCode */
+ if (pi) {
+ if (isRegPair(AOP (left))) {
+ emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
+ } else {
+ emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
+ emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
+ }
+ }
+ freeAsmop (NULL, aop, ic, TRUE);
+ } else {
+
+ /* we did not allocate which means left
+ already in a pointer register, then
+ if size > 0 && this could be used again
+ we have to point it back to where it
+ belongs */
+ if ((AOP_SIZE (result) > 1 &&
+ !OP_SYMBOL (left)->remat &&
+ (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
+ !pi) {
+ int size = AOP_SIZE (result) - 1;
+ emitcode ("sbiw", "r30,%d",size);
+ }
+ }
+
+ /* done */
+ if (pi) pi->generated=1;
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerGet - gget value from generic pointer space */
+/*-----------------------------------------------------------------*/
+static void
+genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
+{
+ int size, offset;
+ int gotFreePtr = 0;
+ sym_link *retype = getSpec (operandType (result));
+ asmop *aop = NULL;
+
+ aopOp (left, ic, FALSE);
+
+ /* if the operand is already in dptr
+ then we do nothing else we move the value to dptr */
+ if (AOP_ISZ(AOP(left))) {
+ aop = AOP(left);
+ } else {
+ aop = newAsmop(0);
+ getFreePtr(ic,&aop,FALSE,TRUE);
+ if (isRegPair(AOP(left))) {
+ emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
+ } else {
+ emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
+ emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
+ }
+ emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
+ gotFreePtr=1;
+ }
+
+ /* so Z register now contains the address */
+
+ aopOp (result, ic, FALSE);
+
+ /* if bit then unpack */
+ if (IS_BITVAR (retype))
+ genUnpackBits (result, "Z", GPOINTER);
+ else {
+ size = AOP_SIZE (result);
+ offset = 0;
+
+ while (size--) {
+ if (size || pi)
+ emitcode ("call", "__gptrget_pi");
+ else
+ emitcode ("call", "__gptrget");
+ aopPut (AOP (result), "r0", offset++);
+ }
+ }
+
+
+ /* now some housekeeping stuff */
+ if (gotFreePtr) {
+ /* we had to allocate for this iCode */
+ if (pi) {
+ if (isRegPair(AOP (left))) {
+ emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
+ } else {
+ emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
+ emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
+ }
+ }
+ freeAsmop (NULL, aop, ic, TRUE);
+ } else {
+
+ /* we did not allocate which means left
+ already in a pointer register, then
+ if size > 0 && this could be used again
+ we have to point it back to where it
+ belongs */
+ if ((AOP_SIZE (result) > 1 &&
+ !OP_SYMBOL (left)->remat &&
+ (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) &&
+ !pi) {
+ int size = AOP_SIZE (result) - 1;
+ emitcode ("sbiw", "r30,%d",size);
+ }
+ }
+ if (pi) pi->generated=1;
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerGet - generate code for pointer get */
+/*-----------------------------------------------------------------*/
+static void
+genPointerGet (iCode * ic, iCode *pi)
+{
+ operand *left, *result;
+ sym_link *type, *etype;
+ int p_type;
+
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+
+ /* depending on the type of pointer we need to
+ move it to the correct pointer register */
+ type = operandType (left);
+ etype = getSpec (type);
+ /* if left is of type of pointer then it is simple */
+ if (IS_PTR (type) && !IS_FUNC (type->next))
+ p_type = DCL_TYPE (type);
+ else {
+ /* we have to go by the storage class */
+ p_type = PTR_TYPE (SPEC_OCLS (etype));
+
+
+ }
+
+ /* now that we have the pointer type we assign
+ the pointer values */
+ switch (p_type) {
+
+ case POINTER:
+ case IPOINTER:
+ case PPOINTER:
+ case FPOINTER:
+ genMemPointerGet (left, result, ic, pi);
+ break;
+
+ case CPOINTER:
+ genCodePointerGet (left, result, ic, pi);
+ break;
+
+ case GPOINTER:
+ genGenPointerGet (left, result, ic, pi);
+ break;
+ }
+