Are you blogging on PH? Get your free blog.
*/
*/

View \DO11.C

68Hc11 Cross-assembler

Submitted By: WEBMASTER
Rating: starstarstar (Rate It)


/*
 *      MC68HC11 specific processing
 */

 
#define PAGE1   0x00
#define PAGE2   0x18
#define PAGE3   0x1A
#define PAGE4   0xCD
 
/* addressing modes */
#define IMMED   0
#define INDX    1
#define INDY    2
#define LIMMED  3       /* long immediate */
#define OTHER   4
 
int     yflag = 0;      /* YNOIMM, YLIMM, and CPD flag */
 
/*
 *      localinit --- machine specific initialization
 */

localinit()
{
}
 
/*
 *      do_op --- process mnemonic
 *
 * Called with the base opcode and it's class. Optr points to
 * the beginning of the operand field.
 */

do_op(opcode,class)
int opcode; /* base opcode */
int class; /* mnemonic class */
{
 int     dist;   /* relative branch distance */
 int     amode;  /* indicated addressing mode */
 char *peek;
 
 /* guess at addressing mode */
 peek = Optr;
 amode = OTHER;
 while( !delim(*peek) && *peek != EOS)  /* check for comma in operand field */
  if( *peek++ == ',' ){
   if( mapdn(*peek) == 'y' )
    amode = INDY;
   else
    amode = INDX;
   break;
   }
 if( *Optr == '#' ) amode = IMMED;
 
 yflag = 0;
 switch(class){
  case P2INH:
   emit(PAGE2);
  case INH:                       /* inherent addressing */
   emit(opcode);
   return;
  case REL:                       /* relative branches */
   eval();
   dist = Result - (Pc+2);
   emit(opcode);
   if( (dist >127 || dist <-128) && Pass==2){
    error("Branch out of Range");
    emit(lobyte(-2));
    return;
    }
   emit(lobyte(dist));
   return;
  case LONGIMM:
   if( amode == IMMED )
    amode = LIMMED;
  case NOIMM:
   if( amode == IMMED ){
    error("Immediate Addressing Illegal");
    return;
    }
  case GEN:                       /* general addressing */
   do_gen(opcode,amode,PAGE1,PAGE1,PAGE2);
   return;
  case GRP2:
   if( amode == INDY ){
    Cycles++;
    emit(PAGE2);
    amode = INDX;
    }
   if( amode == INDX )
    do_indexed(opcode);
   else{   /* extended addressing */
    eval();
    emit(opcode+0x10);
    eword(Result);
    }
   return;
  case CPD:               /* cmpd */
   if( amode == IMMED )
    amode = LIMMED;
   if( amode == INDY )
    yflag=1;
   do_gen(opcode,amode,PAGE3,PAGE3,PAGE4);
   return;
  case XNOIMM:            /* stx */
   if( amode == IMMED ){
    error("Immediate Addressing Illegal");
    return;
    }
  case XLIMM:             /* cpx, ldx */
   if( amode == IMMED )
    amode = LIMMED;
   do_gen(opcode,amode,PAGE1,PAGE1,PAGE4);
   return;
  case YNOIMM:            /* sty */
   if( amode == IMMED ){
    error("Immediate Addressing Illegal");
    return;
    }
  case YLIMM:             /* cpy, ldy */
   if(amode == INDY)
    yflag=1;
   if( amode == IMMED )
    amode = LIMMED;
   do_gen(opcode,amode,PAGE2,PAGE3,PAGE2);
   return;
  case BTB:               /* bset, bclr */
  case SETCLR:            /* brset, brclr */
   opcode = bitop(opcode,amode,class);
 
   if (amode == INDX)
    Cycles++;
   if( amode == INDY ){
    Cycles+=2;
    emit(PAGE2);
    amode = INDX;
    }
   emit(opcode);
   eval();
   emit(lobyte(Result));   /* address */
   if( amode == INDX )
    Optr += 2;      /* skip ,x or ,y */
   Optr = skip_white(Optr);
   eval();
   emit(lobyte(Result));   /* mask */
   if( class == SETCLR )
    return;
   Optr = skip_white(Optr);
   eval();
   dist = Result - (Pc+1);
   if( (dist >127 || dist <-128) && Pass==2){
    error("Branch out of Range");
    dist = Old_pc - (Pc+1);
    }
   emit(lobyte(dist));
   return;
  default:
   fatal("Error in Mnemonic table");
  }
}
 
/*
 *      bitop --- adjust opcode on bit manipulation instructions
 */

bitop(op,mode,class)
int op;
int mode;
int class;
{
 if( mode == INDX || mode == INDY )
  return(op);
 if( class == SETCLR )
  return(op-8);
 else if(class==BTB)
  return(op-12);
 else
  fatal("bitop");
}
 
/*
 *      do_gen --- process general addressing modes
 */

do_gen(op,mode,pnorm,px,py)
int     op;     /* base opcode */
int     mode;   /* addressing mode */
int     pnorm;  /* page for normal addressing modes: IMM,DIR,EXT */
int     px;     /* page for INDX addressing */
int     py;     /* page for INDY addressing */
{
 switch(mode){
 case LIMMED:
  Optr++;
  epage(pnorm);
  emit(op);
  eval();
  eword(Result);
  break;
 case IMMED:
  Optr++;
  epage(pnorm);
  emit(op);
  eval();
  emit(lobyte(Result));
  break;
 case INDY:
  if(yflag)
   Cycles += 2;
  else
   Cycles += 3;
  epage(py);
  do_indexed(op+0x20);
  break;
 case INDX:
  Cycles+=2;
  epage(px);
  do_indexed(op+0x20);
  break;
 case OTHER:
  eval();
  epage(pnorm);
  if(Force_word){
   emit(op+0x30);
   eword(Result);
   Cycles+=2;
   break;
   }
  if(Force_byte){
   emit(op+0x10);
   emit(lobyte(Result));
   Cycles++;
   break;
   }
  if(Result>=0 && Result <=0xFF){
   emit(op+0x10);
   emit(lobyte(Result));
   Cycles++;
   break;
   }
  else {
   emit(op+0x30);
   eword(Result);
   Cycles+=2;
   break;
   }
  break;
 default:
  error("Unknown Addressing Mode");
 }
}
 
/*
 *      do_indexed --- handle all wierd stuff for indexed addressing
 */

do_indexed(op)
int op;
{
 char c;
 
 emit(op);
 eval();
 if( *Optr++ != ',' )
  error("Syntax");
 c = mapdn(*Optr++);
 if( c != 'x' && c != 'y')
  warn("Indexed Addressing Assumed");
 if( Result < 0 || Result > 255)
  warn("Value Truncated");
 emit(lobyte(Result));
}
 
/*
 *      epage --- emit page prebyte
 */

epage(p)
int p;
{
 if( p != PAGE1 )        /* PAGE1 means no prebyte */
  emit(p);
}

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.
Resource Listings