-static void genCmp (operand *left,operand *right,
- operand *result, iCode *ifx, int sign)
-{
- int size, offset = 0 ;
- unsigned long lit = 0L;
-
- /* if left & right are bit variables */
- if (AOP_TYPE(left) == AOP_CRY &&
- AOP_TYPE(right) == AOP_CRY ) {
- /* Cant happen on the Z80 */
- assert(0);
- } else {
- /* subtract right from left if at the
- end the carry flag is set then we know that
- left is greater than right */
- size = max(AOP_SIZE(left),AOP_SIZE(right));
-
- /* if unsigned char cmp with lit, just compare */
- if((size == 1) && !sign &&
- (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
- emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
- emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
- }
- else {
- if(AOP_TYPE(right) == AOP_LIT) {
- lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
- /* optimize if(x < 0) or if(x >= 0) */
- if (lit == 0L){
- if (!sign) {
- /* No sign so it's always false */
- CLRC;
- }
- else{
- /* Just load in the top most bit */
- MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
- if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
- assert(0);
- genIfxJump (ifx,"acc.7");
- return;
- }
- else
- emitcode("rlc","a");
- }
- goto release;
- }
- }
- while (size--) {
- /* Do a long subtract */
- MOVA(aopGet(AOP(left),offset,FALSE));
- if (sign && size == 0) {
- /* Case where it's signed and we've hit the end */
- assert(0);
- } else {
- /* Subtract through, propagating the carry */
- if (offset==0) {
- emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
- }
- else
- emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
- }
- }
- }
+static void
+genCmp (operand * left, operand * right,
+ operand * result, iCode * ifx, int sign)
+{
+ int size, offset = 0;
+ unsigned long lit = 0L;
+ bool swap_sense = FALSE;
+
+ /* if left & right are bit variables */
+ if (AOP_TYPE (left) == AOP_CRY &&
+ AOP_TYPE (right) == AOP_CRY)
+ {
+ /* Cant happen on the Z80 */
+ wassert (0);
+ }
+ else
+ {
+ /* subtract right from left if at the
+ end the carry flag is set then we know that
+ left is greater than right */
+ size = max (AOP_SIZE (left), AOP_SIZE (right));
+
+ /* if unsigned char cmp with lit, just compare */
+ if ((size == 1) &&
+ (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
+ {
+ emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+ if (sign)
+ {
+ emit2 ("xor a,!immedbyte", 0x80);
+ emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
+ }
+ else
+ emit2 ("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 (IS_GB && 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) */
+ if (lit == 0L)
+ {
+ if (!sign)
+ {
+ /* No sign so it's always false */
+ _clearCarry();
+ }
+ else
+ {
+ /* Just load in the top most bit */
+ _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+ if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
+ {
+ genIfxJump (ifx, "7");
+ return;
+ }
+ else
+ emit2 ("rlc a");
+ }
+ goto release;
+ }
+ }
+ if (sign)
+ {
+ /* First setup h and l contaning the top most bytes XORed */
+ bool fDidXor = FALSE;
+ if (AOP_TYPE (left) == AOP_LIT)
+ {
+ unsigned long lit = (unsigned long)
+ floatFromVal (AOP (left)->aopu.aop_lit);
+ emit2 ("ld %s,!immedbyte", _fTmp[0],
+ 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
+ }
+ else
+ {
+ emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
+ emit2 ("xor a,!immedbyte", 0x80);
+ emit2 ("ld %s,a", _fTmp[0]);
+ fDidXor = TRUE;
+ }
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ unsigned long lit = (unsigned long)
+ floatFromVal (AOP (right)->aopu.aop_lit);
+ emit2 ("ld %s,!immedbyte", _fTmp[1],
+ 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
+ }
+ else
+ {
+ emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
+ emit2 ("xor a,!immedbyte", 0x80);
+ emit2 ("ld %s,a", _fTmp[1]);
+ fDidXor = TRUE;
+ }
+ if (!fDidXor)
+ _clearCarry();
+ }
+ else
+ {
+ _clearCarry();
+ }
+ while (size--)
+ {
+ /* Do a long subtract */
+ if (!sign || size)
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ }
+ if (sign && size == 0)
+ {
+ emit2 ("ld a,%s", _fTmp[0]);
+ emit2 ("sbc a,%s", _fTmp[1]);
+ }
+ else
+ {
+ /* Subtract through, propagating the carry */
+ emit2 ("sbc a,%s", aopGet (AOP (right), offset++, FALSE));
+ }
+ }
+ }