+ 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;
+ 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 = size = AOP_SIZE(result);
+ offset = 0;
+ }
+ /* be as economical as possible */
+ if (shCount <= 4) {
+ offset = size -1;
+ while (shCount--) {
+ offset = size -1;
+ size = AOP_SIZE(result);
+ while (size--) {
+ if (offset == (size-1))
+ emitcode("asr","%s",aopGet(AOP(result),offset));
+ else
+ emitcode("lsr","%s",aopGet(AOP(result),offset));
+ offset--;
+ }
+ }
+ } else {
+ emitcode("ldi","r24,lo8(%d)",shCount);
+ tlbl = newiTempLabel(NULL);
+ emitcode("","L%05d:",tlbl->key);
+ offset = size -1;
+ while (size--) {
+ if (offset == (size-1)) emitcode("asr","%s",aopGet(AOP(result),offset));
+ else emitcode("lsr","%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));
+ emitcode("andi","%s,0x0f");
+ 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));
+ emitcode("andi","%s,0x0f",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);
+ }
+ emitcode("mov","r1,%s",aopGet(AOP(result),1));
+ emitcode("swap","%s",aopGet(AOP(result),0));
+ emitcode("andi","%s,0x0f",aopGet(AOP(result),0));
+ emitcode("andi","r1,0xf0");
+ emitcode("or","%s,r1",aopGet(AOP(result),0));
+ emitcode("swap","%s",aopGet(AOP(result),1));
+ emitcode("andi","%s,0x0f",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;
+ }
+ }
+ }