home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
c
/
library
/
xplatfrm
/
motxas
/
do11.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-14
|
7KB
|
319 lines
/*
* 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 */
{
char *skip_white();
char c;
int dist; /* relative branch distance */
int amode; /* indicated addressing mode */
char *peek;
/* guess at addressing mode */
peek = Optr;
amode = OTHER;
if( head(Operand,"X") || head(Operand,"x") ) {
if( delim(*(Operand+1)) )
amode == INDX;
}
else if( head(Operand,"Y") || head(Operand,"y") ) {
if( delim(*(Operand+1)) )
amode == INDY;
}
else while( !delim(*peek) ) { /* check for comma in operand field */
if( *peek++ == ',' ){
if( mapdn(*peek) == 'y' )
amode = INDY;
else {
amode = INDX;
if( mapdn(*peek) != 'x' )
error("Must use X or Y register");
}
break;
}
}
if( *Optr == '#' ) amode = IMMED;
yflag = 0;
switch(class){
case P2INH:
emit(PAGE2);
case INH: /* inherent addressing */
emit(opcode);
return;
case REL: /* relative branches */
if( eval() )
dist = Result - (Pc+2);
else dist = -2;
emit(opcode);
if( (dist >127 || dist <-128) && Pass==2){
error("Branch out of Range");
dist = -2;
}
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++;
else if( amode == INDY ){
Cycles+=2;
emit(PAGE2);
amode = INDX;
}
emit(opcode);
Result = 0; /* setup in case eval() not called */
Force_byte = 0;
Force_word = 0;
c = mapdn(*Optr);
if( c != ',' ) {
if( c != 'x' && c != 'y' || !delim(*(Optr+1)) ) {
eval();
if( amode == INDX )
if( *Optr++ != ',')
error("Missing comma");
}
}
else Optr++;
if( Result < 0 || Result > 255)
warn("Value Truncated");
emit(lobyte(Result)); /* address */
if( amode == INDX )
Optr++; /* skip x or y */
Optr = skip_white(Optr);
eval();
if( (unsigned int)Result > 0xFF )
error("Bit mask more than 8 bits");
emit(lobyte(Result)); /* mask */
if( class == SETCLR )
return;
Optr = skip_white(Optr);
if( eval() )
dist = Result - (Pc+1);
else dist = Old_pc - (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("Assembler error in subroutine 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);
Result = 0; /* setup in case eval() not called */
Force_byte = 0;
Force_word = 0;
c = mapdn(*Optr);
if( c != ',' ) {
if( c != 'x' && c != 'y' || !delim(*(Optr+1)) ) {
eval();
if( *Optr++ != ',' )
error("Missing comma");
}
}
else Optr++;
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);
}