- 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)
- {
- emitcode ("swap", "%s", aopGet (AOP (result), 0));
- emitcode ("andi", "%s,0xf0");
- 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));
- emitcode ("andi", "%s,0xf0", 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", "r1,%s", aopGet (AOP (result), 0));
- emitcode ("swap", "%s", aopGet (AOP (result), 0));
- emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
- emitcode ("andi", "r1,0x0f");
- emitcode ("swap", "%s", aopGet (AOP (result), 1));
- emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
- emitcode ("or", "%s,r1", 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));
+ 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));
+ }