
/*
** arithmetic routines prefaced with "zz" to keep M80
** assembler from generating error msgs when this is compiled
*/

/*
** add primary and secondary registers (result in primary)
*/
zzadd() {ol("DAD D");}

/*
** subtract primary from secondary register (result in primary)
*/
zzsub() {call("CCSUB");}

/*
** multiply primary and secondary registers (result in primary)
*/
zzmult() {call("CCMULT");}

/*
** divide secondary by primary register
** (quotient in primary, remainder in secondary)
*/
zzdiv() {call("CCDIV");}

/*
** remainder of secondary/primary
** (remainder in primary, quotient in secondary)
*/
zzmod() {zzdiv();swap();}

/*
** inclusive "or" primary and secondary registers
** (result in primary)
*/
zzor() {call("CCOR");}

/*
** exclusive "or" the primary and secondary registers
** (result in primary)
*/
zzxor() {call("CCXOR");}

/*
** "and" primary and secondary registers
** (result in primary)
*/
zzand() {call("CCAND");}

/*
** logical negation of primary register
*/
lneg() {call("CCLNEG");}

/*
** arithmetic shift right secondary register
** number of bits given in primary register
** (result in primary)
*/
zzasr() {call("CCASR");}

/*
** arithmetic shift left secondary register
** number of bits given in primary register
** (result in primary)
*/
zzasl() {call("CCASL");}

/*
** two's complement primary register
*/
neg() {call("CCNEG");}

/*
** one's complement primary register
*/
com() {call("CCCOM");}

/*
** increment primary register by one object of whatever size
*/
inc(n) int n; {
  while(1) {
    ol("INX H");
    if(--n < 1) break;
    }
  }

/*
** decrement primary register by one object of whatever size
*/
dec(n) int n; {
  while(1) {
    ol("DCX H");
    if(--n < 1) break;
    }
  }
 
/*
** test for equal to
*/
zzeq()  {call("CCEQ");}

/*
** test for equal to zero
*/
eq0(label) int label; {
  ol("MOV A,H");
  ol("ORA L");
  ot("JNZ ");
  printlabel(label);
  nl();
  }

/*
** test for not equal to
*/
zzne()  {call("CCNE");}

/*
** test for not equal to zero
*/
ne0(label) int label; {
  ol("MOV A,H");
  ol("ORA L");
  ot("JZ ");
  printlabel(label);
  nl();
  }

/*
** test for less than (signed)
*/
zzlt()  {call("CCLT");}

/*
** test for less than to zero
*/
lt0(label) int label; {
  ol("XRA A");
  ol("ORA H");
  ot("JP ");
  printlabel(label);
  nl();
  }

/*
** test for less than or equal to (signed)
*/
zzle()  {call("CCLE");}

/*
** test for less than or equal to zero
*/
le0(label) int label; {
  ol("MOV A,H");
  ol("ORA L");
  ol("JZ $+8");
  ol("XRA A");
  ol("ORA H");
  ot("JP ");
  printlabel(label);
  nl();
  }

/*
** test for greater than (signed)
*/
zzgt()  {call("CCGT");}

/*
** test for greater than to zero
*/
gt0(label) int label; {
  ol("XRA A");
  ol("ORA H");
  ot("JM ");
  printlabel(label);
  nl();
  ol("ORA L");
  ot("JZ ");
  printlabel(label);
  nl();
  }

/*
** test for greater than or equal to (signed)
*/
zzge()  {call("CCGE");}

/*
** test for gteater than or equal to zero
*/
ge0(label) int label; {
  ol("XRA A");
  ol("ORA H");
  ot("JM ");
  printlabel(label);
  nl();
  }

/*
** test for less than (unsigned)
*/
ult()  {call("CCULT");}

/*
** test for less than to zero (unsigned)
*/
ult0(label) int label; {
  ot("JMP ");
  printlabel(label);
  nl();
  }

/*
** test for less than or equal to (unsigned)
*/
ule()  {call("CCULE");}

/*
** test for greater than (unsigned)
*/
ugt()  {call("CCUGT");}

/*
** test for greater than or equal to (unsigned)
*/
uge()  {call("CCUGE");}

#ifdef OPTIMIZE
peephole(ptr) char *ptr; {
  while(*ptr) {
#ifdef TAB
    if(streq(ptr, "\tLXI H,0\n\tDAD SP\n\tCALL CCGINT")) {
      if(streq(ptr+30, "\tXCHG;;")) {pp2();ptr=ptr+38;}
      else                        {pp1();ptr=ptr+30;}
      }
    else if(streq(ptr, "\tLXI H,2\n\tDAD SP\n\tCALL CCGINT")) {
      if(streq(ptr+30, "\tXCHG;;")) {pp3(pp2);ptr=ptr+38;}
      else                        {pp3(pp1);ptr=ptr+30;}
      }
    else if(optimize) {
      if(streq(ptr, "\tDAD SP\n\tCALL CCGINT")) {
        ol("CALL CCDSGI");
        ptr=ptr+21;
        }
      else if(streq(ptr, "\tDAD D\n\tCALL CCGINT")) {
        ol("CALL CCDDGI");
        ptr=ptr+20;
        }
      else if(streq(ptr, "\tDAD SP\n\tCALL CCGCHAR")) {
        ol("CALL CCDSGC");
        ptr=ptr+22;
        }
      else if(streq(ptr, "\tDAD D\n\tCALL CCGCHAR")) {
        ol("CALL CCDDGC");
        ptr=ptr+21;
        }
      else if(streq(ptr,
"\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGINT\n\tINX H\n\tCALL CCPINT")) {
        ol("CALL CCINCI");
        ptr=ptr+59;
        }
      else if(streq(ptr,
"\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGINT\n\tDCX H\n\tCALL CCPINT")) {
        ol("CALL CCDECI");
        ptr=ptr+59;
        }
      else if(streq(ptr,
"\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGCHAR\n\tINX H\n\tMOV A,L\n\tSTAX D")) {
        ol("CALL CCINCC");
        ptr=ptr+64;
        }
      else if(streq(ptr,
"\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGCHAR\n\tDCX H\n\tMOV A,L\n\tSTAX D")) {
        ol("CALL CCDECC");
        ptr=ptr+64;
        }
      else if(streq(ptr, "\tDAD D\n\tPOP D\n\tCALL CCPINT")) {
#ifdef M80
        ol("CALL CCDDPI"); /* unique name in six characters */
#else /* M80 */
        ol("CALL CCDDPDPI");
#endif /* M80 */
        ptr=ptr+27;
        }
      else if(streq(ptr, "\tDAD D\n\tPOP D\n\tMOV A,L\n\tSTAX D")) {
#ifdef M80
        ol("CALL CCDDPC"); /* unique name in six characters */
#else /* M80 */
        ol("CALL CCDDPDPC");
#endif /* M80 */
        ptr=ptr+31;
        }
      else if(streq(ptr, "\tPOP D\n\tCALL CCPINT")) {
        ol("CALL CCPDPI");
        ptr=ptr+20;
        }
      else if(streq(ptr, "\tPOP D\n\tMOV A,L\n\tSTAX D")) {
        ol("CALL CCPDPC");
        ptr=ptr+24;
        }
      /* additional optimizing logic goes here */
#else /* TAB */
    if(streq(ptr," LXI H,0\n DAD SP\n CALL CCGINT")) {
      if(streq(ptr+30, " XCHG;;")) {pp2();ptr=ptr+38;}
      else                        {pp1();ptr=ptr+30;}
      }
    else if(streq(ptr," LXI H,2\n DAD SP\n CALL CCGINT")) {
      if(streq(ptr+30, " XCHG;;")) {pp3(pp2);ptr=ptr+38;}
      else                        {pp3(pp1);ptr=ptr+30;}
      }
    else if(optimize) {
      if(streq(ptr, " DAD SP\n CALL CCGINT")) {
        ol("CALL CCDSGI");
        ptr=ptr+21;
        }
      else if(streq(ptr, " DAD D\n CALL CCGINT")) {
        ol("CALL CCDDGI");
        ptr=ptr+20;
        }
      else if(streq(ptr, " DAD SP\n CALL CCGCHAR")) {
        ol("CALL CCDSGC");
        ptr=ptr+22;
          }
      else if(streq(ptr, " DAD D\n CALL CCGCHAR")) {
        ol("CALL CCDDGC");
        ptr=ptr+21;
        }
      else if(streq(ptr,
" DAD SP\n MOV D,H\n MOV E,L\n CALL CCGINT\n INX H\n CALL CCPINT")) {
        ol("CALL CCINCI");
        ptr=ptr+59;
        }
      else if(streq(ptr,
" DAD SP\n MOV D,H\n MOV E,L\n CALL CCGINT\n DCX H\n CALL CCPINT")) {
        ol("CALL CCDECI");
        ptr=ptr+59;
        }
      else if(streq(ptr,
" DAD SP\n MOV D,H\n MOV E,L\n CALL CCGCHAR\n INX H\n MOV A,L\n STAX D")) {
        ol("CALL CCINCC");
        ptr=ptr+64;
        }
      else if(streq(ptr,
" DAD SP\n MOV D,H\n MOV E,L\n CALL CCGCHAR\n DCX H\n MOV A,L\n STAX D")) {
        ol("CALL CCDECC");
        ptr=ptr+64;
        }
      else if(streq(ptr, " DAD D\n POP D\n CALL CCPINT")) {
#ifdef M80
        ol("CALL CCDDPI"); /* unique name in six characters */
#else /* M80 */
        ol("CALL CCDDPDPI");
#endif /* M80 */
        ptr=ptr+27;
        }
      else if(streq(ptr, " DAD D\n POP D\n MOV A,L\n STAX D")) {
#ifdef M80
        ol("CALL CCDDPC"); /* unique name in six characters */
#else /* M80 */
        ol("CALL CCDDPDPC");
#endif /* M80 */
        ptr=ptr+31;
        }
      else if(streq(ptr, " POP D\n CALL CCPINT")) {
        ol("CALL CCPDPI");
        ptr=ptr+20;
        }
      else if(streq(ptr, " POP D\n MOV A,L\n STAX D")) {
        ol("CALL CCPDPC");
        ptr=ptr+24;
        }
      /* additional optimizing logic goes here */
#endif /* TAB */
      else cout(*ptr++, output);
      }
    else cout(*ptr++, output);
    }
  }

pp1() {
  ol("POP H");
  ol("PUSH H");
  }

pp2() {
  ol("POP D");
  ol("PUSH D");
  }

#ifdef FULLC
pp3(pp) int (*pp)(); {
  ol("POP B");
  (*pp)();
  ol("PUSH B");
  }

#else  /* FULLC */
pp3(pp) int pp; {
  ol("POP B");
  pp();
  ol("PUSH B");
  }
#endif  /* FULLC */

#endif /* OPTIMIZE */
                                                                       