-/*-----------------------------------------------------------------*/
-/* genLeftShiftLiteral - left shifting by known count */
-/*-----------------------------------------------------------------*/
-static void genLeftShiftLiteral (operand *left,
- operand *right,
- operand *result,
- iCode *ic)
-{
- int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
- int size;
-
- freeAsmop(right,NULL,ic,TRUE);
-
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
-
- size = getSize(operandType(result));
-
-#if VIEW_SIZE
- emitcode("; shift left ","result %d, left %d",size,
- AOP_SIZE(left));
-#endif
-
- /* I suppose that the left size >= result size */
- if(shCount == 0){
- while(size--){
- movLeft2Result(left, size, result, size, 0);
- }
- }
-
- else if(shCount >= (size * 8))
- while(size--)
- aopPut(AOP(result),zero,size);
- else{
- switch (size) {
- case 1:
- genlshOne (result,left,shCount);
- break;
-
- case 2:
- case 3:
- genlshTwo (result,left,shCount);
- break;
-
- case 4:
- genlshFour (result,left,shCount);
- break;
- }
- }
- freeAsmop(left,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;
- char *l;
- symbol *tlbl , *tlbl1;
-
- right = IC_RIGHT(ic);
- left = IC_LEFT(ic);
- result = IC_RESULT(ic);
-
- aopOp(right,ic,FALSE);
-
- /* if the shift count is known then do it
- as efficiently as possible */
- if (AOP_TYPE(right) == AOP_LIT) {
- genLeftShiftLiteral (left,right,result,ic);
- return ;
- }
-
- /* shift count is unknown then we have to form
- a loop get the loop count in B : Note: we take
- only the lower order byte since shifting
- more that 32 bits make no sense anyway, ( the
- largest size of an object can be only 32 bits ) */
-
- emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
- emitcode("inc","b");
- freeAsmop (right,NULL,ic,TRUE);
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
-
- /* now move the left to the result if they are not the
- same */
- if (!sameRegs(AOP(left),AOP(result)) &&
- AOP_SIZE(result) > 1) {
-
- size = AOP_SIZE(result);
- offset=0;
- while (size--) {
- l = aopGet(AOP(left),offset,FALSE,TRUE);
- if (*l == '@' && (IS_AOP_PREG(result))) {
-
- emitcode("mov","a,%s",l);
- aopPut(AOP(result),"a",offset);
- } else
- aopPut(AOP(result),l,offset);
- offset++;
- }
- }
-
- tlbl = newiTempLabel(NULL);
- size = AOP_SIZE(result);
- offset = 0 ;
- tlbl1 = newiTempLabel(NULL);
-
- /* if it is only one byte then */
- if (size == 1) {
- symbol *tlbl1 = newiTempLabel(NULL);
-
- l = aopGet(AOP(left),0,FALSE,FALSE);
- MOVA(l);
- emitcode("sjmp","%05d$",tlbl1->key+100);
- emitcode("","%05d$:",tlbl->key+100);
- emitcode("add","a,acc");
- emitcode("","%05d$:",tlbl1->key+100);
- emitcode("djnz","b,%05d$",tlbl->key+100);
- aopPut(AOP(result),"a",0);
- goto release ;
- }
-
- reAdjustPreg(AOP(result));
-
- emitcode("sjmp","%05d$",tlbl1->key+100);
- emitcode("","%05d$:",tlbl->key+100);
- l = aopGet(AOP(result),offset,FALSE,FALSE);
- MOVA(l);
- emitcode("add","a,acc");
- aopPut(AOP(result),"a",offset++);
- while (--size) {
- l = aopGet(AOP(result),offset,FALSE,FALSE);
- MOVA(l);
- emitcode("rlc","a");
- aopPut(AOP(result),"a",offset++);
- }
- reAdjustPreg(AOP(result));
-
- emitcode("","%05d$:",tlbl1->key+100);
- emitcode("djnz","b,%05d$",tlbl->key+100);
-release:
- freeAsmop(left,NULL,ic,TRUE);
- freeAsmop(result,NULL,ic,TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/* genrshOne - right shift a one byte quantity by known count */
-/*-----------------------------------------------------------------*/
-static void genrshOne (operand *result, operand *left,
- int shCount, int sign)
-{
- shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
-}
-
-/*-----------------------------------------------------------------*/
-/* genrshTwo - right shift two bytes by known amount != 0 */
-/*-----------------------------------------------------------------*/
-static void genrshTwo (operand *result,operand *left,
- int shCount, int sign)
-{
- /* if shCount >= 8 */
- if (shCount >= 8) {
- shCount -= 8 ;
- if (shCount)
- shiftR1Left2Result(left, MSB16, result, LSB,
- shCount, sign);
- else
- movLeft2Result(left, MSB16, result, LSB, sign);
- addSign(result, MSB16, sign);
- }
-
- /* 1 <= shCount <= 7 */
- else
- shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
-}
-
-/*-----------------------------------------------------------------*/
-/* shiftRLong - shift right one long from left to result */
-/* offl = LSB or MSB16 */
-/*-----------------------------------------------------------------*/
-static void shiftRLong (operand *left, int offl,
- operand *result, int sign)
-{
- if(!sign)
- emitcode("clr","c");
- MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
- if(sign)
- emitcode("mov","c,acc.7");
- emitcode("rrc","a");
- aopPut(AOP(result),"a",MSB32-offl);
- if(offl == MSB16)
- /* add sign of "a" */
- addSign(result, MSB32, sign);
-
- MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
- emitcode("rrc","a");
- aopPut(AOP(result),"a",MSB24-offl);
-
- MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
- emitcode("rrc","a");
- aopPut(AOP(result),"a",MSB16-offl);
-
- if(offl == LSB){
- MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
- emitcode("rrc","a");
- aopPut(AOP(result),"a",LSB);
- }
-}
-
-/*-----------------------------------------------------------------*/
-/* genrshFour - shift four byte by a known amount != 0 */
-/*-----------------------------------------------------------------*/
-static void genrshFour (operand *result, operand *left,
- int shCount, int sign)
-{
- /* if shifting more that 3 bytes */
- if(shCount >= 24 ) {
- shCount -= 24;
- if(shCount)
- shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
- else
- movLeft2Result(left, MSB32, result, LSB, sign);
- addSign(result, MSB16, sign);
- }
- else if(shCount >= 16){
- shCount -= 16;
- if(shCount)
- shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
- else{
- movLeft2Result(left, MSB24, result, LSB, 0);
- movLeft2Result(left, MSB32, result, MSB16, sign);
- }
- addSign(result, MSB24, sign);
- }
- else if(shCount >= 8){
- shCount -= 8;
- if(shCount == 1)
- shiftRLong(left, MSB16, result, sign);
- else if(shCount == 0){
- movLeft2Result(left, MSB16, result, LSB, 0);
- movLeft2Result(left, MSB24, result, MSB16, 0);
- movLeft2Result(left, MSB32, result, MSB24, sign);
- addSign(result, MSB32, sign);
- }
- else{
- shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
- shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
- /* the last shift is signed */
- shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
- addSign(result, MSB32, sign);
- }
- }
- else{ /* 1 <= shCount <= 7 */
- if(shCount <= 2){
- shiftRLong(left, LSB, result, sign);
- if(shCount == 2)
- shiftRLong(result, LSB, result, sign);
- }
- else{
- shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
- shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
- shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
- }
- }
-}
-
-/*-----------------------------------------------------------------*/
-/* genRightShiftLiteral - right shifting by known count */
-/*-----------------------------------------------------------------*/
-static void genRightShiftLiteral (operand *left,
- operand *right,
- operand *result,
- iCode *ic,
- int sign)
-{
- int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
- int size;
-
- freeAsmop(right,NULL,ic,TRUE);
-
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
-
-#if VIEW_SIZE
- emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
- AOP_SIZE(left));
-#endif
-
- size = getDataSize(left);
- /* test the LEFT size !!! */
-
- /* I suppose that the left size >= result size */
- if(shCount == 0){
- size = getDataSize(result);
- while(size--)
- movLeft2Result(left, size, result, size, 0);
- }
-
- else if(shCount >= (size * 8)){
- if(sign)
- /* get sign in acc.7 */
- MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
- addSign(result, LSB, sign);
- } else{
- switch (size) {
- case 1:
- genrshOne (result,left,shCount,sign);
- break;
-
- case 2:
- genrshTwo (result,left,shCount,sign);
- break;
-
- case 4:
- genrshFour (result,left,shCount,sign);
- break;
- default :
- break;
- }
-
- freeAsmop(left,NULL,ic,TRUE);
- freeAsmop(result,NULL,ic,TRUE);
- }
-}
-
-/*-----------------------------------------------------------------*/
-/* genSignedRightShift - right shift of signed number */
-/*-----------------------------------------------------------------*/
-static void genSignedRightShift (iCode *ic)
-{
- operand *right, *left, *result;
- int size, offset;
- char *l;
- symbol *tlbl, *tlbl1 ;
-
- /* we do it the hard way put the shift count in b
- and loop thru preserving the sign */
-
- right = IC_RIGHT(ic);
- left = IC_LEFT(ic);
- result = IC_RESULT(ic);
-
- aopOp(right,ic,FALSE);
-
-
- if ( AOP_TYPE(right) == AOP_LIT) {
- genRightShiftLiteral (left,right,result,ic,1);
- return ;
- }
- /* shift count is unknown then we have to form
- a loop get the loop count in B : Note: we take
- only the lower order byte since shifting
- more that 32 bits make no sense anyway, ( the
- largest size of an object can be only 32 bits ) */
-
- emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
- emitcode("inc","b");
- freeAsmop (right,NULL,ic,TRUE);
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
-
- /* now move the left to the result if they are not the
- same */
- if (!sameRegs(AOP(left),AOP(result)) &&
- AOP_SIZE(result) > 1) {
-
- size = AOP_SIZE(result);
- offset=0;
- while (size--) {
- l = aopGet(AOP(left),offset,FALSE,TRUE);
- if (*l == '@' && IS_AOP_PREG(result)) {
-
- emitcode("mov","a,%s",l);
- aopPut(AOP(result),"a",offset);
- } else
- aopPut(AOP(result),l,offset);
- offset++;
- }
- }
-
- /* mov the highest order bit to OVR */
- tlbl = newiTempLabel(NULL);
- tlbl1= newiTempLabel(NULL);
-
- size = AOP_SIZE(result);
- offset = size - 1;
- emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
- emitcode("rlc","a");
- emitcode("mov","ov,c");
- /* if it is only one byte then */
- if (size == 1) {
- l = aopGet(AOP(left),0,FALSE,FALSE);
- MOVA(l);
- emitcode("sjmp","%05d$",tlbl1->key+100);
- emitcode("","%05d$:",tlbl->key+100);
- emitcode("mov","c,ov");
- emitcode("rrc","a");
- emitcode("","%05d$:",tlbl1->key+100);
- emitcode("djnz","b,%05d$",tlbl->key+100);
- aopPut(AOP(result),"a",0);
- goto release ;
- }
-
- reAdjustPreg(AOP(result));
- emitcode("sjmp","%05d$",tlbl1->key+100);
- emitcode("","%05d$:",tlbl->key+100);
- emitcode("mov","c,ov");
- while (size--) {
- l = aopGet(AOP(result),offset,FALSE,FALSE);
- MOVA(l);
- emitcode("rrc","a");
- aopPut(AOP(result),"a",offset--);
- }
- reAdjustPreg(AOP(result));
- emitcode("","%05d$:",tlbl1->key+100);
- emitcode("djnz","b,%05d$",tlbl->key+100);
-
-release:
- freeAsmop(left,NULL,ic,TRUE);
- freeAsmop(result,NULL,ic,TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/* genRightShift - generate code for right shifting */
-/*-----------------------------------------------------------------*/
-static void genRightShift (iCode *ic)
-{
- operand *right, *left, *result;
- link *retype ;
- int size, offset;
- char *l;
- symbol *tlbl, *tlbl1 ;
-
- /* if signed then we do it the hard way preserve the
- sign bit moving it inwards */
- retype = getSpec(operandType(IC_RESULT(ic)));
-
- if (!SPEC_USIGN(retype)) {
- genSignedRightShift (ic);
- return ;
- }
-
- /* signed & unsigned types are treated the same : i.e. the
- signed is NOT propagated inwards : quoting from the
- ANSI - standard : "for E1 >> E2, is equivalent to division
- by 2**E2 if unsigned or if it has a non-negative value,
- otherwise the result is implementation defined ", MY definition
- is that the sign does not get propagated */
-
- right = IC_RIGHT(ic);
- left = IC_LEFT(ic);
- result = IC_RESULT(ic);
-
- aopOp(right,ic,FALSE);
-
- /* if the shift count is known then do it
- as efficiently as possible */
- if (AOP_TYPE(right) == AOP_LIT) {
- genRightShiftLiteral (left,right,result,ic, 0);
- return ;
- }
-
- /* shift count is unknown then we have to form
- a loop get the loop count in B : Note: we take
- only the lower order byte since shifting
- more that 32 bits make no sense anyway, ( the
- largest size of an object can be only 32 bits ) */
-
- emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
- emitcode("inc","b");
- freeAsmop (right,NULL,ic,TRUE);
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
-
- /* now move the left to the result if they are not the
- same */
- if (!sameRegs(AOP(left),AOP(result)) &&
- AOP_SIZE(result) > 1) {
-
- size = AOP_SIZE(result);
- offset=0;
- while (size--) {
- l = aopGet(AOP(left),offset,FALSE,TRUE);
- if (*l == '@' && IS_AOP_PREG(result)) {
-
- emitcode("mov","a,%s",l);
- aopPut(AOP(result),"a",offset);
- } else
- aopPut(AOP(result),l,offset);
- offset++;
- }
- }
-
- tlbl = newiTempLabel(NULL);
- tlbl1= newiTempLabel(NULL);
- size = AOP_SIZE(result);
- offset = size - 1;
-
- /* if it is only one byte then */
- if (size == 1) {
- l = aopGet(AOP(left),0,FALSE,FALSE);
- MOVA(l);
- emitcode("sjmp","%05d$",tlbl1->key+100);
- emitcode("","%05d$:",tlbl->key+100);
- CLRC;
- emitcode("rrc","a");
- emitcode("","%05d$:",tlbl1->key+100);
- emitcode("djnz","b,%05d$",tlbl->key+100);
- aopPut(AOP(result),"a",0);
- goto release ;
- }
-
- reAdjustPreg(AOP(result));
- emitcode("sjmp","%05d$",tlbl1->key+100);
- emitcode("","%05d$:",tlbl->key+100);
- CLRC;
- while (size--) {
- l = aopGet(AOP(result),offset,FALSE,FALSE);
- MOVA(l);
- emitcode("rrc","a");
- aopPut(AOP(result),"a",offset--);
- }
- reAdjustPreg(AOP(result));
-
- emitcode("","%05d$:",tlbl1->key+100);
- emitcode("djnz","b,%05d$",tlbl->key+100);
-
-release:
- freeAsmop(left,NULL,ic,TRUE);
- freeAsmop(result,NULL,ic,TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/* genUnpackBits - generates code for unpacking bits */
-/*-----------------------------------------------------------------*/
-static void genUnpackBits (operand *result, char *rname, int ptype)
-{
- int shCnt ;
- int rlen = 0 ;
- link *etype;
- int offset = 0 ;
-
- etype = getSpec(operandType(result));
-
- /* read the first byte */
- switch (ptype) {
-
- case POINTER:
- case IPOINTER:
- emitcode("mov","a,@%s",rname);
- break;
-
- case PPOINTER:
- emitcode("movx","a,@%s",rname);
- break;
-
- case FPOINTER:
- emitcode("movx","a,@dptr");
- break;
-
- case CPOINTER:
- emitcode("clr","a");
- emitcode("movc","a","@a+dptr");
- break;
-
- case GPOINTER:
- emitcode("lcall","__gptrget");
- break;
- }