New Memory Allocation functions
[fw/sdcc] / src / z80 / gen.c
index 2a31a4cde93f92fab7165819b73c8d9db4631961..7a2984eb996c5ccb7df662f48cb7f52e142691d8 100644 (file)
@@ -17,6 +17,7 @@
   Better reg packing, first peephole           20038   163     1873
   With assign packing                          19281   165     1849
   5/3/00                                       17741   185     17B6
+  With reg params for mul and div              16234   202     162D
 
   Michael Hope <michaelh@earthling.net>        2000
   Based on the mcs51 generator - 
 #endif
 
 #include "z80.h"
+#include "SDCCglobl.h"
 #include "SDCCpeeph.h"
 #include "gen.h"
 #include "SDCCglue.h"
+#include "newalloc.h"
 
 /* this is the down and dirty file with all kinds of kludgy & hacky
    stuff. This is what it is all about CODE GENERATION for a specific MCU.
@@ -332,7 +335,7 @@ static asmop *newAsmop (short type)
 {
     asmop *aop;
 
-    ALLOC(aop,sizeof(asmop));
+    aop = Safe_calloc(sizeof(asmop));
     aop->type = type;
     return aop;
 }
@@ -367,7 +370,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
     /* special case for a function */
     if (IS_FUNC(sym->type)) {   
         sym->aop = aop = newAsmop(AOP_IMMD);    
-        ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
+        aop->aopu.aop_immd = Safe_calloc(strlen(sym->rname)+1);
         strcpy(aop->aopu.aop_immd,sym->rname);
         aop->size = 2;
         return aop;
@@ -427,7 +430,7 @@ static asmop *aopForRemat (symbol *sym)
         break;
     }
 
-    ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
+    aop->aopu.aop_immd = Safe_calloc(strlen(buffer)+1);
     strcpy(aop->aopu.aop_immd,buffer);    
     return aop;        
 }
@@ -714,7 +717,7 @@ char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
            tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
        else
            tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
+       rs = Safe_calloc(strlen(s)+1);
        strcpy(rs,s);   
        return rs;
     case AOP_LIT: {
@@ -723,13 +726,15 @@ char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
        /* otherwise it is fairly simple */
        if (!IS_FLOAT(val->type)) {
            unsigned long v = floatFromVal(val);
+
            if (offset == 2)
                v >>= 16;
+
            if (with_hash)
                tsprintf(buffer, "!immedword", v);
            else
                tsprintf(buffer, "!constword", v);
-           ALLOC_ATOMIC(rs,strlen(buffer)+1);
+           rs = Safe_calloc(strlen(buffer)+1);
            return strcpy (rs,buffer);
        }
        else {
@@ -740,7 +745,7 @@ char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
                tsprintf(buffer, "!immedword", f.w[offset/2]);
            else
                tsprintf(buffer, "!constword", f.w[offset/2]);
-           ALLOC_ATOMIC(rs,strlen(buffer)+1);
+           rs = Safe_calloc(strlen(buffer)+1);
            return strcpy (rs,buffer);
        }
     }
@@ -802,6 +807,26 @@ static bool requiresHL(asmop *aop)
     }
 }
 
+static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
+{
+    unsigned long v;
+    value * val = aop->aopu.aop_lit;
+
+    wassert(aop->type == AOP_LIT);
+    wassert(!IS_FLOAT(val->type));
+    
+    v = floatFromVal(val);
+
+    if (xor)
+       v ^= 0x8000;
+    if (negate)
+       v = -v;
+    v &= 0xFFFF;
+
+    tsprintf(buffer, "!immedword", v);
+    return gc_strdup(buffer);
+}
+
 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
 {
     const char *l;
@@ -827,7 +852,7 @@ static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
        _G.pairs[pairId].lit = gc_strdup(l);
        _G.pairs[pairId].offset = offset;
     }
-    if (IS_GB && pairId == PAIR_DE) {
+    if (IS_GB && pairId == PAIR_DE && 0) {
        if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
            if (abs(_G.pairs[pairId].offset - offset) < 3) {
                adjustPair(pair, &_G.pairs[pairId].offset, offset);
@@ -970,7 +995,7 @@ static char *aopGet(asmop *aop, int offset, bool bit16)
            default:
                wassert(0);
            }
-       ALLOC_ATOMIC(rs,strlen(s)+1);
+       rs = Safe_calloc(strlen(s)+1);
        strcpy(rs,s);   
        return rs;
        
@@ -978,7 +1003,7 @@ static char *aopGet(asmop *aop, int offset, bool bit16)
        wassert(IS_GB);
        emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
        sprintf(s, "a");
-       ALLOC_ATOMIC(rs,strlen(s)+1);
+       rs = Safe_calloc(strlen(s)+1);
        strcpy(rs,s);   
        return rs;
        
@@ -986,7 +1011,7 @@ static char *aopGet(asmop *aop, int offset, bool bit16)
        wassert(IS_GB);
        emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
        sprintf(s, "a");
-       ALLOC_ATOMIC(rs,strlen(s)+1);
+       rs = Safe_calloc(strlen(s)+1);
        strcpy(rs,s);   
        return rs;
 
@@ -1003,7 +1028,7 @@ static char *aopGet(asmop *aop, int offset, bool bit16)
        wassert(IS_Z80);
        setupPair(PAIR_IY, aop, offset);
        tsprintf(s,"!*iyx", offset);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
+       rs = Safe_calloc(strlen(s)+1);
        strcpy(rs,s);   
        return rs;
 
@@ -1013,9 +1038,11 @@ static char *aopGet(asmop *aop, int offset, bool bit16)
            tsprintf(s, "!*hl");
        }
        else {
-           tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
+           if (aop->aopu.aop_stk >= 0)
+               offset += _G.stack.param_offset;
+           tsprintf(s,"!*ixx ; x", aop->aopu.aop_stk+offset);
        }
-       ALLOC_ATOMIC(rs,strlen(s)+1);
+       rs = Safe_calloc(strlen(s)+1);
        strcpy(rs,s);   
        return rs;
        
@@ -1149,6 +1176,8 @@ static void aopPut (asmop *aop, const char *s, int offset)
                emit2("ld !*hl,%s", s);
        }
        else {
+           if (aop->aopu.aop_stk >= 0)
+               offset += _G.stack.param_offset;
            if (!canAssignToPtr(s)) {
                emit2("ld a,%s", s);
                emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
@@ -1274,7 +1303,7 @@ void outAcc(operand *result)
 
 /** Take the value in carry and put it into a register
  */
-void outBitC(operand *result)
+void outBitCLong(operand *result, bool swap_sense)
 {
     /* if the result is bit */
     if (AOP_TYPE(result) == AOP_CRY) {
@@ -1284,10 +1313,17 @@ void outBitC(operand *result)
     else {
        emit2("ld a,!zero");
        emit2("rla");
+       if (swap_sense)
+           emit2("xor a,!immedbyte", 1);
         outAcc(result);
     }
 }
 
+void outBitC(operand *result)
+{
+    outBitCLong(result, FALSE);
+}
+
 /*-----------------------------------------------------------------*/
 /* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
@@ -1314,7 +1350,7 @@ void toBoolean(operand *oper)
 /*-----------------------------------------------------------------*/
 static void genNot (iCode *ic)
 {
-    link *optype = operandType(IC_LEFT(ic));
+    sym_link *optype = operandType(IC_LEFT(ic));
 
     /* assign asmOps to operand & result */
     aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
@@ -1383,7 +1419,7 @@ static void genCpl (iCode *ic)
 static void genUminus (iCode *ic)
 {
     int offset ,size ;
-    link *optype, *rtype;
+    sym_link *optype, *rtype;
 
     /* assign asmops */
     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
@@ -1678,10 +1714,7 @@ static bool isInHome(void)
 static void emitCall(iCode *ic, bool ispcall)
 {
     int pushed_de = 0;
-    link *detype = getSpec(operandType(IC_LEFT(ic)));
-
-    if (IS_BANKED(detype)) 
-       emit2("; call to a banked function");
+    sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
 
     /* if caller saves & we have not saved then */
     if (!ic->regsSaved) {
@@ -1753,7 +1786,7 @@ static void emitCall(iCode *ic, bool ispcall)
     }
 
     if (ispcall) {
-       if (IS_BANKED(detype)) {
+       if (IS_BANKEDCALL(detype)) {
            werror(W_INDIR_BANKED);
        }
        aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
@@ -1780,7 +1813,7 @@ static void emitCall(iCode *ic, bool ispcall)
        char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
            OP_SYMBOL(IC_LEFT(ic))->rname :
            OP_SYMBOL(IC_LEFT(ic))->name;
-       if (IS_BANKED(detype)) {
+       if (IS_BANKEDCALL(detype)) {
            emit2("call banked_call");
            emit2("!dws", name);
            emit2("!dw !bankimmeds", name);
@@ -1841,7 +1874,7 @@ static void emitCall(iCode *ic, bool ispcall)
 /*-----------------------------------------------------------------*/
 static void genCall (iCode *ic)
 {
-    link *detype = getSpec(operandType(IC_LEFT(ic)));
+    sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
     emitCall(ic, FALSE);
 }
 
@@ -1870,17 +1903,24 @@ static int resultRemat (iCode *ic)
     return 0;
 }
 
+extern set *publics;
+
 /*-----------------------------------------------------------------*/
 /* genFunction - generated code for function entry                 */
 /*-----------------------------------------------------------------*/
 static void genFunction (iCode *ic)
 {
     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
-    link *fetype;
+    sym_link *fetype;
 
     nregssaved = 0;
     setArea(IS_NONBANKED(sym->etype));
 
+    /* PENDING: hack */
+    if (!IS_STATIC(sym->etype)) {
+       addSetIfnotP(&publics, sym);
+    }
+
     /* create the function header */
     emit2("!functionheader", sym->name);
     /* PENDING: portability. */
@@ -2542,7 +2582,7 @@ static void genIfxJump (iCode *ic, char *jval)
 
     /* if true label then we jump if condition
     supplied is true */
-    if ( IC_TRUE(ic) ) {
+    if (IC_TRUE(ic)) {
         jlbl = IC_TRUE(ic);
        if (!strcmp(jval, "a")) {
            inst = "nz";
@@ -2550,6 +2590,9 @@ static void genIfxJump (iCode *ic, char *jval)
        else if (!strcmp(jval, "c")) {
            inst = "c";
        }
+       else if (!strcmp(jval, "nc")) {
+           inst = "nc";
+       }
        else {
            /* The buffer contains the bit on A that we should test */
            inst = "nz";
@@ -2564,6 +2607,9 @@ static void genIfxJump (iCode *ic, char *jval)
        else if (!strcmp(jval, "c")) {
            inst = "nc";
        }
+       else if (!strcmp(jval, "nc")) {
+           inst = "c";
+       }
        else {
            /* The buffer contains the bit on A that we should test */
            inst = "z";
@@ -2575,6 +2621,8 @@ static void genIfxJump (iCode *ic, char *jval)
     }
     else if (!strcmp(jval, "c")) {
     }
+    else if (!strcmp(jval, "nc")) {
+    }
     else {
        emitcode("bit", "%s,a", jval);
     }
@@ -2584,6 +2632,11 @@ static void genIfxJump (iCode *ic, char *jval)
     ic->generated = 1;
 }
 
+static const char *_getPairIdName(PAIR_ID id)
+{
+    return _pairs[id].name;
+}
+
 /** Generic compare for > or <
  */
 static void genCmp (operand *left,operand *right,
@@ -2591,6 +2644,7 @@ static void genCmp (operand *left,operand *right,
 {
     int size, offset = 0 ;
     unsigned long lit = 0L;
+    bool swap_sense = FALSE;
 
     /* if left & right are bit variables */
     if (AOP_TYPE(left) == AOP_CRY &&
@@ -2615,6 +2669,40 @@ static void genCmp (operand *left,operand *right,
                emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
         } 
        else {
+           /* Special cases:
+              On the GB:
+                 If the left or the right is a lit:
+                       Load -lit into HL, add to right via, check sense.
+           */
+           if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
+               PAIR_ID id = PAIR_DE;
+               asmop *lit = AOP(right);
+               asmop *op = AOP(left);
+               swap_sense = TRUE;
+
+               if (AOP_TYPE(left) == AOP_LIT) {
+                   swap_sense = FALSE;
+                   lit = AOP(left);
+                   op = AOP(right);
+               }
+               if (sign) {
+                   emit2("ld e,%s", aopGet(op, 0, 0));
+                   emit2("ld a,%s", aopGet(op, 1, 0));
+                   emit2("xor a,!immedbyte", 0x80);
+                   emit2("ld d,a");
+               }
+               else {
+                   id = getPairId(op);
+                   if (id == PAIR_INVALID) {
+                       fetchPair(PAIR_DE, op);
+                       id = PAIR_DE;
+                   }
+               }
+               spillPair(PAIR_HL);
+               emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
+               emit2("add hl,%s", _getPairIdName(id));
+               goto release;
+           }
             if(AOP_TYPE(right) == AOP_LIT) {
                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
                 /* optimize if(x < 0) or if(x >= 0) */
@@ -2688,15 +2776,15 @@ static void genCmp (operand *left,operand *right,
 
 release:
     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
-        outBitC(result);
+        outBitCLong(result, swap_sense);
     } else {
         /* if the result is used in the next
         ifx conditional branch then generate
         code a little differently */
-        if (ifx )
-            genIfxJump (ifx,"c");
+        if (ifx)
+            genIfxJump(ifx, swap_sense ? "nc" : "c");
         else
-            outBitC(result);
+            outBitCLong(result, swap_sense);
         /* leave the result in acc */
     }
 }
@@ -2707,7 +2795,7 @@ release:
 static void genCmpGt (iCode *ic, iCode *ifx)
 {
     operand *left, *right, *result;
-    link *letype , *retype;
+    sym_link *letype , *retype;
     int sign ;
 
     left = IC_LEFT(ic);
@@ -2735,7 +2823,7 @@ static void genCmpGt (iCode *ic, iCode *ifx)
 static void genCmpLt (iCode *ic, iCode *ifx)
 {
     operand *left, *right, *result;
-    link *letype , *retype;
+    sym_link *letype , *retype;
     int sign ;
 
     left = IC_LEFT(ic);
@@ -4005,7 +4093,7 @@ static void genRightShiftLiteral (operand *left,
 static void genRightShift (iCode *ic)
 {
     operand *right, *left, *result;
-    link *retype ;
+    sym_link *retype ;
     int size, offset, first = 1;
     char *l;
     bool is_signed;
@@ -4093,7 +4181,7 @@ static void genGenPointerGet (operand *left,
                               operand *result, iCode *ic)
 {
     int size, offset ;
-    link *retype = getSpec(operandType(result));
+    sym_link *retype = getSpec(operandType(result));
     int pair = PAIR_HL;
 
     if (IS_GB)
@@ -4158,7 +4246,7 @@ static void genGenPointerGet (operand *left,
 static void genPointerGet (iCode *ic)
 {
     operand *left, *result ;
-    link *type, *etype;
+    sym_link *type, *etype;
 
     left = IC_LEFT(ic);
     result = IC_RESULT(ic) ;
@@ -4185,7 +4273,7 @@ static void genGenPointerSet (operand *right,
                               operand *result, iCode *ic)
 {    
     int size, offset ;
-    link *retype = getSpec(operandType(right));
+    sym_link *retype = getSpec(operandType(right));
     PAIR_ID pairId = PAIR_HL;
 
     aopOp(result,ic,FALSE, FALSE);
@@ -4251,7 +4339,7 @@ static void genGenPointerSet (operand *right,
 static void genPointerSet (iCode *ic)
 {    
     operand *right, *result ;
-    link *type, *etype;
+    sym_link *type, *etype;
 
     right = IC_RIGHT(ic);
     result = IC_RESULT(ic) ;
@@ -4333,7 +4421,10 @@ static void genAddrOf (iCode *ic)
        spillCached();
        if (sym->onStack) {
            /* if it has an offset  then we need to compute it */
-           emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+           if (sym->stack > 0) 
+               emitcode("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+           else
+               emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
            emitcode("add", "hl,sp");
        }
        else {
@@ -4482,7 +4573,7 @@ static void genJumpTab (iCode *ic)
 static void genCast (iCode *ic)
 {
     operand *result = IC_RESULT(ic);
-    link *ctype = operandType(IC_LEFT(ic));
+    sym_link *ctype = operandType(IC_LEFT(ic));
     operand *right = IC_RIGHT(ic);
     int size, offset ;