Beispiel #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( );
      }
Beispiel #2
0
/*  Classify argument as to address mode */
int
addr(struct expr *esp)
{
        int c;
        unsigned rd;

        if ((c = getnb()) == '#') {
                /*  Immediate mode */
                expr(esp, 0);
                esp->e_mode = S_IMMED;
        }
        else if (c == '@') {
                /* choices are @R0, @R1, @DPTR, @A+PC, @A+DPTR */
                switch (reg()) {
                case R0:
                        esp->e_mode = S_AT_R;
                        esp->e_addr = R0;
                        break;
                case R1:
                        esp->e_mode = S_AT_R;
                        esp->e_addr = R1;
                        break;
                case DPTR:
                        esp->e_mode = S_AT_DP;
                        esp->e_addr = DPTR;
                        break;
                case A:
                        if (getnb() == '+') {
                                rd = reg();
                                if (rd == PC) {
                                        esp->e_mode = S_AT_APC;
                                        esp->e_addr = 0;
                                } else if (rd == DPTR) {
                                        esp->e_mode = S_AT_ADP;
                                        esp->e_addr = 0;
                                } else {
                                        aerr();
                                }
                        } else
                                aerr();
                        break;
                }

                esp->e_flag = 0;
                esp->e_base.e_ap = NULL;
        }
        else if (c == '*') {
                if ((c = getnb()) == '/') {
                        /* Force inverted bit */
                        expr(esp, 0);
                        esp->e_mode = S_NOT_BIT;
                } else {
                        unget(c);
                        /* Force direct page */
                        expr(esp, 0);
                        esp->e_mode = S_DIR;
                }
                if (esp->e_addr & ~0xFF)
                        err('d');
        }
        else if (c == '/') {
                /* Force inverted bit  */
                expr(esp, 0);
                esp->e_mode = S_NOT_BIT;
        }
        else {
                unget(c);

                /* try for register: A, AB, R0-R7, DPTR, PC, Cy */
                if ((esp->e_addr = admode(reg51)) != -1) {
                        switch (esp->e_addr) {
                        case A:
                                esp->e_mode = S_A;
                                break;
                        case AB:
                                esp->e_mode = S_RAB;
                                break;
                        case DPTR:
                                esp->e_mode = S_DPTR;
                                break;
                        case PC:
                                esp->e_mode = S_PC;
                                break;
                        case C:
                                esp->e_mode = S_C;
                                break;
                        default:
                                /* R0-R7 */
                                esp->e_mode = S_REG;
                        }
                } else {
                        /* Must be an expression */
                        esp->e_addr = 0;
                        expr(esp, 0);
                        if ((!esp->e_flag)
                                && (esp->e_base.e_ap==NULL)
                                && !(esp->e_addr & ~0xFF)) {
                                esp->e_mode = S_DIR;
                        } else {
                                esp->e_mode = S_EXT;
                        }
                }
        }
        return (esp->e_mode);
}