Example #1
0
/*
 * Process a machine op.
 */
VOID  machine(struct mne * mp)
{
  int op, t1, t2;
  struct expr e1, e2;
  int rf, v1, v2;
  
  clrexpr(&e1);
  clrexpr(&e2);
  op = (int) mp->m_valu;
  rf = mp->m_type;
#if 0
  if (!hd64 && rf>X_HD64)
    rf = 0;
#endif
  
  if (!r4k_mode && rf > X_R4K_MODE)
    rf = 0;
  
  switch (rf)
    {
    case S_INH1:
      outab(op);
      break;
      
    case S_INH2:
      outab(0xED);
      outab(op);
      break;
      
    case S_RET:
      if (more()) {
        if ((v1 = admode(CND)) != 0) {
          outab(op | (v1<<3));
        } else {
          qerr();
        }
      } else {
        outab(0xC9);
      }
      break;
      
    case S_PUSH:
      if (admode(R16X)) {
        outab(op+0x30);
        break;
      } else if ((v1 = admode(R8IP)) != 0) {
        outab(0xED);
        if (op == 0xC5) 
          outab(0x76);  /* push */
        else
          outab(0x7E);  /* pop  */
        break;
      } else
        if ((v1 = admode(R16)) != 0 && (v1 &= 0xFF) != SP) {
          if (v1 != gixiy(v1)) {
            outab(op+0x20);
            break;
          }
          outab(op | (v1<<4));
          break;
        } else if (r4k_mode) {
          if ( (v1 = admode(R32_JKHL)) != 0 ) {
            outab(JKHL_PG);
            outab(op+0x30);
            break;
          } else if ( (v1 = admode(R32_BCDE)) != 0 ) {
            outab(BCDE_PG);
            outab(op+0x30);
            break;
          }
        }
      aerr();
      break;
      
    case S_RST:
      v1 = (int) absexpr();
      /* ljm comment -
       *   block RST 00, 08, and 30 b/c those opcodes
       *   are assigned to different instructions in the
       *   rabbit processor
       */
      if ((v1 == 0x00) || (v1 == 0x08) || (v1 == 0x30)) {
        aerr( );
        v1 = 0;
      }
      if (v1 & ~0x38) {
        aerr();
        v1 = 0;
      }
      outab(op|v1);
      break;
      
#if 0
      /* IM x set interrupt mode on Z-80 */
      /* Rabbit processor use the opcode to set interrupt level */
    case S_IM:
      expr(&e1, 0);
      abscheck(&e1);
      if (e1.e_addr > 2) {
        aerr();
        e1.e_addr = 0;
      }
      outab(op);
      outab(imtab[(int) e1.e_addr]);
      break;
#endif
      
    case S_BIT:
      expr(&e1, 0);
      t1 = 0;
      v1 = (int) e1.e_addr;
      if (v1 > 7) {
        ++t1;
        v1 &= 0x07;
      }
      op |= (v1<<3);
      comma(1);
      addr(&e2);
      abscheck(&e1);
      if (genop(0xCB, op, &e2, 0) || t1)
        aerr();
      break;
      
    case S_RL:
      t1 = 0;
      t2 = addr(&e2);
      if ((t2 == S_IMMED) && r4k_mode)
        {
          v1 = (int) e2.e_addr;
          /* v1 should be shift count of 1,2,4, or 8 */
          comma(1);
          clrexpr(&e2);
          t2 = addr(&e2);
          
          if ((t2 != S_R32_BCDE) && (t2 != S_R32_JKHL))
            aerr( );
          
          if (v1 == 1)
            v1 = 0x48;
          else if (v1 == 2)
            v1 = 0x49;
          else if (v1 == 4)
            v1 = 0x4B;
          else if ((v1 == 8) && (op < 0x20 /* op is rlc|rrc|rl|rr */))
            v1 = 0x4F;
          else {
            err('o');
            break;
          }
          
          /* 00 rlc, 08 rrc, 10 rl , 18 rr                    *
           * 20 sla, 28 sra,         38 srl,  [30 sll == sla] */
          outab( ((t2 == S_R32_JKHL)?JKHL_PG:BCDE_PG) );
          outab(v1 + (op << 1));
          break;
        }
      else if (more()) {
        if ((t2 != S_R8) || (e2.e_addr != A))
          ++t1;
        comma(1);
        clrexpr(&e2);
        t2 = addr(&e2);
      } else if (t2 == S_R16) {
        v2 = (int) e2.e_addr;
        if ((v2 == DE) && 
            ((op == 0x10 /* rl */) || (op == 0x18 /* rr */))) {
          outab( 0xF3 - 0x10 + op );
          break;
        }
        
        if ((v2 == HL) && (op == 0x18 /* rr */)) {
          outab( 0xFC );
          break;
        }
        
        if (r4k_mode) {
          if ((v2 == HL) && (op == 0x10 /* rl */)) {
            outab( 0x42 );
            break;
          }
          if (((v2 == BC)||(v2 == DE)) &&
              (op < 0x20 /* 00 rlc, 08 rrc, 10 rl, 18 rr */)) {
            outab( 0x50 + (op >> 3) + ((v2==BC)?0x10:0x00) );
            break;
          }
        }
        
        aerr( );
      }
Example #2
0
/*
 * Process machine ops.
 */
VOID
machine(struct mne *mp)
{
        char *p, *str;
        char pid[NINPUT], id[NINPUT];
        int c, d, t, t1, v1;
        a_uint op;
        struct sym *sp;
        struct expr e, e1, e2;

        clrexpr(&e);
        clrexpr(&e1);
        clrexpr(&e2);

        op = mp->m_valu;
        switch (mp->m_type) {

        case S_CPU:
                opcycles = OPCY_CPU;
                lmode = SLIST;
                switch(op) {
                default: op = DS8XCXXX;
                case DS8XCXXX: v1 = 2; str = "DS8XCXXX"; sym[2].s_addr = X_DS8XCXXX; break;
                case DS80C310: v1 = 2; str = "DS80C310"; sym[2].s_addr = X_DS80C310; break;
                case DS80C320: v1 = 2; str = "DS80C320"; sym[2].s_addr = X_DS80C320; break;
                case DS80C323: v1 = 2; str = "DS80C323"; sym[2].s_addr = X_DS80C323; break;
                case DS80C390: v1 = 3; str = "DS80C390"; sym[2].s_addr = X_DS80C390; break;
                case DS83C520: v1 = 2; str = "DS83C520"; sym[2].s_addr = X_DS83C520; break;
                case DS83C530: v1 = 2; str = "DS83C530"; sym[2].s_addr = X_DS83C530; break;
                case DS83C550: v1 = 2; str = "DS83C550"; sym[2].s_addr = X_DS83C550; break;
                case DS87C520: v1 = 2; str = "DS87C520"; sym[2].s_addr = X_DS87C520; break;
                case DS87C530: v1 = 2; str = "DS87C530"; sym[2].s_addr = X_DS87C530; break;
                case DS87C550: v1 = 2; str = "DS87C550"; sym[2].s_addr = X_DS87C550; break;
                case DS______: v1 = 2; str = "DS______"; sym[2].s_addr = X_DS______;
                        if (more()) {
                                str = p = pid;
                                d = getnb();
                                while ((c = get()) != d) {
                                        if (c == '\0') {
                                                qerr();
                                        }
                                        if (p < &pid[sizeof(pid)-3]) {
                                                *p++ = c;
                                        } else {
                                                break;
                                        }
                                }
                                *p = 0;
                        }
                        break;
                }
                if (op != 0) {
                        ds8_bytes = v1;
                        exprmasks(v1);
                }
                mchtyp = (int) op;

                sprintf(id, "__%s", str);
                sp = lookup(id);
                if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) {
                        err('m');
                }
                sp->s_type = S_USER;
                sp->s_addr = 1;
                sp->s_flag |= S_ASG;

                sprintf(buff, "%s %s", DS_CPU, str);
                cpu = buff;

                sp = lookup("__SFR_BITS");
                if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) {
                        err('m');
                }
                sp->s_type = S_USER;
                sp->s_flag |= S_ASG;

                if (more()) {
                        expr(&e, 0);
                        abscheck(&e);
                        sp->s_addr = e.e_addr;
                } else {
                        sp->s_addr = 1;
                }
                break;

        case S_AMODE:
                opcycles = OPCY_AMODE;
                if ((mchtyp != 0) && (mchtyp != DS80C390)) {
                        err('o');
                        break;
                }
                expr(&e, 0);
                abscheck(&e);
                amode = (int) e.e_addr;
                if ((amode < 0) || (amode > 2)) {
                        amode = 0;
                        err('o');
                }
                if ((c = getnb()) == ',') {
                        expr(&e1, 0);
                        abscheck(&e1);
                        if (e1.e_addr != 0) {
/* mov  ta,#0aah */             outab(0x075);   outab(0x0C7);   outab(0x0AA);
/* mov  ta,#055h */             outab(0x075);   outab(0x0C7);   outab(0x055);
/* mov  acon,#amode */          outab(0x075);   outab(0x09D);   outab(amode);
                        } else {
                                lmode = SLIST;
                        }
                } else {
                        unget(c);
                        lmode = SLIST;
                }
                break;

        case S_BITS:
                if (ds8_bytes == 0) {
                        ds8_bytes = (int) op;
                        exprmasks(ds8_bytes);
                } else
                if (ds8_bytes != (int) op) {
                        err('m');
                }
                opcycles = OPCY_BITS;
                lmode = SLIST;
                break;

        case S_INH:
                outab(op);
                break;

        case S_JMP11:
                expr(&e, 0);
                if (amode == 2) {
                        outr3bm(&e, R_J19, op);
                } else {
                        outrwm(&e, R_J11, op);
                }
                break;

        case S_JMP16:
                expr(&e, 0);
                outab(op);
                if (amode == 2) {
                        outr3b(&e, R_NORM);
                } else {
                        outrw(&e, R_NORM);
                }
                break;

        case S_ACC:
                t = addr(&e);
                if (t != S_A)
                        aerr();
                outab(op);
                break;

        case S_TYP1:
                /* A, direct, @R0, @R1, R0 to R7.  "INC" also allows DPTR */
                t = addr(&e);

                switch (t) {
                case S_A:
                        outab(op + 4);
                        break;

                case S_DIR:
                case S_EXT:
                        /* Direct is also legal */
                        outab(op + 5);
                        outrb(&e, R_PAG0);
                        break;

                case S_AT_R:
                        outab(op + 6 + e.e_addr);
                        break;

                case S_REG:
                        outab(op + 8 + e.e_addr);
                        break;

                case S_DPTR:
                        if (op != 0)
                                /* only INC (op=0) has DPTR mode */
                                aerr();
                        else
                                outab( 0xA3);
                        break;

                default:
                        aerr();
                }
                break;

        case S_TYP2:
                /* A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7 */
                t = addr(&e);
                if (t != S_A)
                        aerr();
                comma(1);
                t1 = addr(&e1);

                switch (t1) {
                case S_IMMED:
                        outab(op + 4);
                        outrb(&e1, R_NORM);
                        break;

                case S_DIR:
                case S_EXT:
                        outab(op + 5);
                        outrb(&e1, R_PAG0);
                        break;

                case S_AT_R:
                        outab(op + 6 + e1.e_addr);
                        break;

                case S_REG:
                        outab(op + 8 + (e1.e_addr));
                        break;

                default:
                        aerr();
                }
                break;

        case S_TYP3:
                /* dir,A; dir,#imm;
                 * A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7
                 * C,direct;  C,/direct
                 */
                t = addr(&e);
                comma(1);
                t1 = addr(&e1);

                switch (t) {
                case S_DIR:
                case S_EXT:
                        switch (t1) {
                        case S_A:
                                outab(op + 2);
                                outrb(&e, R_PAG0);
                                break;

                        case S_IMMED:
                                outab(op + 3);
                                outrb(&e, R_PAG0);
                                outrb(&e1, R_NORM);
                                break;

                        default:
                                aerr();
                        }
                        break;

                case S_A:
                        switch (t1) {
                        case S_IMMED:
                                outab(op + 4);
                                outrb(&e1, R_NORM);
                                break;

                        case S_DIR:
                        case S_EXT:
                                outab(op + 5);
                                outrb(&e1, R_PAG0);
                                break;

                        case S_AT_R:
                                outab(op + 6 + e1.e_addr);
                                break;

                        case S_REG:
                                outab(op + 8 + e1.e_addr);
                                break;

                        default:
                                aerr();
                        }
                        break;

                case S_C:
                        /* XRL has no boolean version.  Trap it */
                        if (op == 0x60)
                                aerr();

                        switch (t1) {
                        case S_DIR:
                        case S_EXT:
                                outab(op + 0x32);
                                outrb(&e1, R_PAG0);
                                break;

                        case S_NOT_BIT:
                                outab(op + 0x60);
                                outrb(&e1, R_PAG0);
                                break;

                        default:
                                aerr();
                        }
                        break;

                default:
                        aerr();
                }
                break;

        case S_TYP4:
                /* A,direct; A,@R0; A,@R1; A,R0 to A,R7 */
                t = addr(&e);
                if (t != S_A)
                        aerr();
                comma(1);
                t1 = addr(&e1);

                switch (t1) {
                case S_DIR:
                case S_EXT:
                        outab(op + 5);
                        outrb(&e1, R_PAG0);
                        break;

                case S_AT_R:
                        outab(op + 6 + e1.e_addr);
                        break;

                case S_REG:
                        outab(op + 8 + e1.e_addr);
                        break;

                default:
                        aerr();
                }
                break;

        /* MOV instruction, all modes */
        case S_MOV:
                t = addr(&e);
                comma(1);
                t1 = addr(&e1);

                switch (t) {
                case S_A:
                        switch (t1) {
                        case S_IMMED:
                                outab(0x74);
                                outrb(&e1, R_NORM);
                                break;

                        case S_DIR:
                        case S_EXT:
                                outab(0xE5);
                                outrb(&e1, R_PAG0);
                                break;

                        case S_AT_R:
                                outab(0xE6 + e1.e_addr);
                                break;

                        case S_REG:
                                outab(0xE8 + e1.e_addr);
                                break;

                        default:
                                aerr();
                        }
                        break;

                case S_REG:
                        switch (t1) {
                        case S_A:
                                outab(0xF8 + e.e_addr);
                                break;

                        case S_IMMED:
                                outab(0x78 + e.e_addr);
                                outrb(&e1, R_NORM);
                                break;

                        case S_DIR:
                        case S_EXT:
                                outab(0xA8 + e.e_addr);
                                outrb(&e1, R_PAG0);
                                break;

                        default:
                                aerr();
                        }
                        break;

                case S_DIR:
                case S_EXT:
                        switch (t1) {
                        case S_A:
                                outab(0xF5);
                                outrb(&e, R_PAG0);
                                break;

                        case S_IMMED:
                                outab(0x75);
                                outrb(&e, R_PAG0);
                                outrb(&e1, R_NORM);
                                break;

                        case S_DIR:
                        case S_EXT:
                                outab(0x85);
                                outrb(&e1, R_PAG0);
                                outrb(&e, R_PAG0);
                                break;

                        case S_AT_R:
                                outab(0x86 + e1.e_addr);
                                outrb(&e, R_PAG0);
                                break;

                        case S_REG:
                                outab(0x88 + e1.e_addr);
                                outrb(&e, R_PAG0);
                                break;

                        case S_C:
                                outab(0x92);
                                outrb(&e, R_PAG0);
                                break;

                        default:
                                aerr();
                        }
                        break;

                case S_AT_R:
                        switch (t1) {
                        case S_IMMED:
                                outab(0x76 + e.e_addr);
                                outrb(&e1, R_NORM);
                                break;

                        case S_DIR:
                        case S_EXT:
                                outab(0xA6 + e.e_addr);
                                outrb(&e1, R_PAG0);
                                break;

                        case S_A:
                                outab(0xF6 + e.e_addr);
                                break;

                        default:
                                aerr();
                        }
                        break;

                case S_C:
                        if ((t1 != S_DIR) && (t1 != S_EXT))
                                aerr();
                        outab(0xA2);
                        outrb(&e1, R_PAG0);
                        break;

                case S_DPTR:
                        if (t1 != S_IMMED)
                                aerr();
                        outab(0x90);
                        if (amode == 2)
                                outr3b(&e1, R_NORM);
                        else
                                outrw(&e1, R_NORM);
                        break;

                default:
                        aerr();
                }
                break;

        case S_BITBR:   /* JB, JBC, JNB bit,rel */
                /* Branch on bit set/clear */
                t = addr(&e);
                if ((t != S_DIR) && (t != S_EXT))
                        aerr();
                /* sdcc svn rev #4994: fixed bug 1865114 */
                comma(1);
                expr(&e1, 0);

                outab(op);
                outrb(&e, R_PAG0);

                if (mchpcr(&e1)) {
                        v1 = (int) (e1.e_addr - dot.s_addr - 1);
                        /* sdcc svn rev #602: Fix some path problems */
                        if (pass == 2 && ((v1 < -128) || (v1 > 127)))
                                aerr();
                        outab(v1);
                } else {
                        outrb(&e1, R_PCR);
                }
                if (e1.e_mode != S_USER)
                        rerr();
                break;

        case S_BR:  /* JC, JNC, JZ, JNZ */
                /* Relative branch */
                /* sdcc svn rev #4994: fixed bug 1865114 */
                expr(&e1, 0);
                outab(op);

                if (mchpcr(&e1)) {
                        v1 = (int) (e1.e_addr - dot.s_addr - 1);
                        /* sdcc svn rev #602: Fix some path problems */
                        if (pass == 2 && ((v1 < -128) || (v1 > 127)))
                                aerr();
                        outab(v1);
                } else {
                        outrb(&e1, R_PCR);
                }
                if (e1.e_mode != S_USER)
                        rerr();
                break;

        case S_CJNE:
                /* A,#;  A,dir;  @R0,#;  @R1,#;  Rn,# */
                t = addr(&e);
                comma(1);
                t1 = addr(&e1);

                /* Benny */
                comma(1);
                expr(&e2, 0);

                switch (t) {
                case S_A:
                        if (t1 == S_IMMED) {
                                outab(op + 4);
                                outrb(&e1, R_NORM);
                        }
                        else if ((t1 == S_DIR) || (t1 == S_EXT)) {
                                outab(op + 5);
                                outrb(&e1, R_PAG0);
                        }
                        else
                                aerr();
                        break;

                case S_AT_R:
                        outab(op + 6 + e.e_addr);
                        if (t1 != S_IMMED)
                                aerr();
                        outrb(&e1, R_NORM);
                        break;

                case S_REG:
                        outab(op + 8 + e.e_addr);
                        if (t1 != S_IMMED)
                                aerr();
                        outrb(&e1, R_NORM);
                        break;

                default:
                        aerr();
                        break;
                }

                /* branch destination */
                if (mchpcr(&e2)) {
                        v1 = (int) (e2.e_addr - dot.s_addr - 1);
                        /* sdcc svn rev #602: Fix some path problems */
                        if (pass == 2 && ((v1 < -128) || (v1 > 127)))
                                aerr();
                        outab(v1);
                } else {
                        outrb(&e2, R_PCR);
                }
                if (e2.e_mode != S_USER)
                        rerr();
                break;

        case S_DJNZ:
                /* Dir,dest;  Reg,dest */
                t = addr(&e);
                /* sdcc svn rev #4994: fixed bug 1865114 */
                comma(1);
                expr(&e1, 0);

                switch (t) {
                case S_DIR:
                case S_EXT:
                        outab(op + 5);
                        outrb(&e, R_PAG0);
                        break;

                case S_REG:
                        outab(op + 8 + e.e_addr);
                        break;

                default:
                        aerr();
                }

                /* branch destination */
                /* sdcc svn rev #4994: fixed bug 1865114 */
                if (mchpcr(&e1)) {
                        v1 = (int) (e1.e_addr - dot.s_addr - 1);
                        /* sdcc svn rev #602: Fix some path problems */
                        if (pass == 2 && ((v1 < -128) || (v1 > 127)))
                                aerr();
                        outab(v1);
                } else {
                        outrb(&e1, R_PCR);
                }
                if (e1.e_mode != S_USER)
                        rerr();
                break;

        case S_JMP:
                /* @A+DPTR */
                t = addr(&e);
                if (t != S_AT_ADP)
                        aerr();
                outab(op);
                break;

        case S_MOVC:
                /* A,@A+DPTR  A,@A+PC */
                t = addr(&e);
                if (t != S_A)
                        aerr();
                comma(1);
                t1 = addr(&e1);
                if (t1 == S_AT_ADP)
                        outab(0x93);
                else if (t1 == S_AT_APC)
                        outab(0x83);
                else
                        aerr();
                break;

        case S_MOVX:
                /* A,@DPTR  A,@R0  A,@R1  @DPTR,A  @R0,A  @R1,A */
                t = addr(&e);
                comma(1);
                t1 = addr(&e1);

                switch (t) {
                case S_A:
                        switch (t1) {
                        case S_AT_DP:
                                outab(0xE0);
                                break;

                        case S_AT_R:
                                outab(0xE2 + e1.e_addr);
                                break;

                        default:
                                aerr();
                        }
                        break;

                case S_AT_DP:
                        if (t1 == S_A)
                                outab(0xF0);
                        else
                                aerr();
                        break;

                case S_AT_R:
                        if (t1 == S_A)
                                outab(0xF2 + e.e_addr);
                        else
                                aerr();
                        break;

                default:
                        aerr();
                }
                break;

        /* MUL/DIV A,B */
        case S_AB:
                t = addr(&e);
                if (t != S_RAB)
                        aerr();
                outab(op);
                break;

        /* CLR or CPL:  A, C, or bit */
        case S_ACBIT:
                t = addr(&e);
                switch (t) {
                case S_A:
                        if (op == 0xB2)
                                outab(0xF4);
                        else
                                outab(0xE4);
                        break;

                case S_C:
                        outab(op+1);
                        break;

                case S_DIR:
                case S_EXT:
                        outab(op);
                        outrb(&e, R_PAG0);
                        break;

                default:
                        aerr();
                }
                break;

        /* SETB C or bit */
        case S_SETB:
                t = addr(&e);
                switch (t) {
                case S_C:
                        outab(op+1);
                        break;

                case S_DIR:
                case S_EXT:
                        outab(op);
                        outrb(&e, R_PAG0);
                        break;

                default:
                        aerr();
                }
                break;

        /* direct */
        case S_DIRECT:
                t = addr(&e);
                if (t == S_A) {
                        e.e_addr = 0xE0;
                        e.e_mode = S_DIR;
                } else
                if ((t != S_DIR) && (t != S_EXT)) {
                        aerr();
                        break;
                }
                outab(op);
                outrb(&e, R_PAG0);
                break;

        /* XCHD A,@Rn */
        case S_XCHD:
                t = addr(&e);
                if (t != S_A)
                        aerr();
                comma(1);
                t1 = addr(&e1);
                switch (t1) {
                case S_AT_R:
                        outab(op + e1.e_addr);
                        break;

                default:
                        aerr();
                }
                break;

        default:
                opcycles = OPCY_ERR;
                err('o');
                break;
        }
        if (opcycles == OPCY_NONE) {
                opcycles = ds8pg1[cb[0] & 0xFF];
        }
}