home *** CD-ROM | disk | FTP | other *** search
- /*
- * MC6809 specific processing
- */
-
- #define PAGE2 0x10
- #define PAGE3 0x11
- #define IPBYTE 0x9F /* extended indirect postbyte */
- #define SWI 0x3F
-
- /* register names */
-
- #define RD 0
- #define RX 1
- #define RY 2
- #define RU 3
- #define RS 4
- #define RPC 5
- #define RA 8
- #define RB 9
- #define RCC 10
- #define RDP 11
- #define RPCR 12
-
- /* convert tfr/exg reg number into psh/pul format */
- int regs[] = { 6,16,32,64,64,128,0,0,2,4,1,8,0};
- int rcycl[]= { 2,2, 2, 2, 2, 2, 0,0,1,1,1,1,0};
-
- /* addressing modes */
- #define IMMED 0 /* immediate */
- #define IND 1 /* indexed */
- #define INDIR 2 /* indirect */
- #define OTHER 3 /* NOTA */
-
- /*
- * 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 src,dst;/* source and destination registers */
- int pbyte; /* postbyte value */
- int amode; /* indicated addressing mode */
- int j;
-
- amode = set_mode(); /* pickup indicated addressing mode */
-
- switch(class){
- case INH: /* inherent addressing */
- emit(opcode);
- return;
- case GEN: /* general addressing */
- do_gen(opcode,amode);
- return;
- case IMM: /* immediate addressing */
- if( amode != IMMED ){
- error("Immediate Operand Required");
- return;
- }
- Optr++;
- eval();
- emit(opcode);
- emit(lobyte(Result));
- return;
- case REL: /* short 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 P2REL: /* long relative branches */
- eval();
- dist = Result - (Pc+4);
- emit(PAGE2);
- emit(opcode);
- eword(dist);
- return;
- case P1REL: /* lbra and lbsr */
- if( amode == IMMED)
- Optr++; /* kludge for C compiler */
- eval();
- dist = Result - (Pc+3);
- emit(opcode);
- eword(dist);
- return;
- case NOIMM:
- if( amode == IMMED ){
- error("Immediate Addressing Illegal");
- return;
- }
- do_gen(opcode,amode);
- return;
- case P2GEN:
- emit(PAGE2);
- if( amode == IMMED ){
- emit(opcode);
- Optr++;
- eval();
- eword(Result);
- return;
- }
- do_gen(opcode,amode);
- return;
- case P3GEN:
- emit(PAGE3);
- if( amode == IMMED ){
- emit(opcode);
- Optr++;
- eval();
- eword(Result);
- return;
- }
- do_gen(opcode,amode);
- return;
- case RTOR: /* tfr and exg */
- emit(opcode);
- src = regnum();
- while(alpha(*Optr))Optr++;
- if(src==ERR){
- error("Register Name Required");
- emit(0);
- return;
- }
- if(*Optr++ != ','){
- error("Missing ,");
- emit(0);
- return;
- }
- dst = regnum();
- while(alpha(*Optr))Optr++;
- if(dst==ERR){
- error("Register Name Required");
- emit(0);
- return;
- }
- if( src==RPCR || dst==RPCR){
- error("PCR illegal here");
- emit(0);
- return;
- }
- if( (src <=5 && dst >=8) ||
- (src >=8 && dst <=5)){
- error("Register Size Mismatch");
- emit(0);
- return;
- }
- emit( (src<<4)+dst );
- return;
- case INDEXED: /* indexed addressing only */
- if( *Optr == '#'){
- Optr++; /* kludge city */
- amode = IND;
- }
- if( amode != IND ){
- error("Indexed Addressing Required");
- return;
- }
- do_indexed(opcode);
- return;
- case RLIST: /* pushes and pulls */
- if(*Operand == EOS){
- error("Register List Required");
- return;
- }
- emit(opcode);
- pbyte = 0;
- do{
- j = regnum();
- if( j == ERR || j==RPCR)
- error("Illegal Register Name");
- else if(j==RS && (opcode==52))
- error("Can't Push S on S");
- else if(j==RU && (opcode==54))
- error("Can't Push U on U");
- else if(j==RS && (opcode==53))
- error("Can't Pull S from S");
- else if(j==RU && (opcode==55))
- error("Can't Pull U from U");
- else{
- pbyte |= regs[j];
- Cycles += rcycl[j];
- }
- while(*Optr != EOS && alpha(*Optr))Optr++;
- }while( *Optr++ == ',' );
- emit(lobyte(pbyte));
- return;
- case P2NOIMM:
- if( amode == IMMED )
- error("Immediate Addressing Illegal");
- else{
- emit(PAGE2);
- do_gen(opcode,amode);
- }
- return;
- case P2INH: /* Page 2 inherent */
- emit(PAGE2);
- emit(opcode);
- return;
- case P3INH: /* Page 3 inherent */
- emit(PAGE3);
- emit(opcode);
- return;
- case LONGIMM:
- if( amode == IMMED ){
- emit(opcode);
- Optr++;
- eval();
- eword(Result);
- }
- else
- do_gen(opcode,amode);
- return;
- case GRP2:
- if( amode == IND ){
- do_indexed(opcode+0x60);
- return;
- }
- else if( amode == INDIR){
- Optr++;
- emit(opcode + 0x60);
- emit(IPBYTE);
- eval();
- eword(Result);
- Cycles += 7;
- if(*Optr == ']'){
- Optr++;
- return;
- }
- error("Missing ']'");
- return;
- }
- eval();
- if(Force_word){
- emit(opcode+0x70);
- eword(Result);
- Cycles += 3;
- return;
- }
- if(Force_byte){
- emit(opcode);
- emit(lobyte(Result));
- Cycles += 2;
- return;
- }
- if(Result>=0 && Result <=0xFF){
- emit(opcode);
- emit(lobyte(Result));
- Cycles += 2;
- return;
- }
- else {
- emit(opcode+0x70);
- eword(Result);
- Cycles += 3;
- return;
- }
- case SYS: /* system call */
- emit(SWI);
- eval();
- emit(lobyte(Result));
- return;
- default:
- fatal("Error in Mnemonic table");
- }
- }
-
-
- /*
- * do_gen --- process general addressing mode stuff
- */
- do_gen(op,mode)
- int op;
- int mode;
- {
- if( mode == IMMED){
- Optr++;
- emit(op);
- eval();
- emit(lobyte(Result));
- return;
- }
- else if( mode == IND ){
- do_indexed(op+0x20);
- return;
- }
- else if( mode == INDIR){
- Optr++;
- emit(op+0x20);
- emit(IPBYTE);
- eval();
- eword(Result);
- Cycles += 7;
- if(*Optr == ']'){
- Optr++;
- return;
- }
- error("Missing ']'");
- return;
- }
- else if( mode == OTHER){
- eval();
- if(Force_word){
- emit(op+0x30);
- eword(Result);
- Cycles += 3;
- return;
- }
- if(Force_byte){
- emit(op+0x10);
- emit(lobyte(Result));
- Cycles += 2;
- return;
- }
- if(Result>=0 && Result <=0xFF){
- emit(op+0x10);
- emit(lobyte(Result));
- Cycles += 2;
- return;
- }
- else {
- emit(op+0x30);
- eword(Result);
- Cycles += 3;
- return;
- }
- }
- else {
- error("Unknown Addressing Mode");
- return;
- }
- }
-
- /*
- * do_indexed --- handle all wierd stuff for indexed addressing
- */
- do_indexed(op)
- int op;
- {
- int pbyte;
- int j,k;
- int predec,pstinc;
-
- Cycles += 2; /* indexed is always 2+ base cycle count */
- predec=0;
- pstinc=0;
- pbyte=128;
- emit(op);
- if(*Optr=='['){
- pbyte |= 0x10; /* set indirect bit */
- Optr++;
- if( !any((char)']',Optr))
- error("Missing ']'");
- Cycles += 3; /* indirection takes this much longer */
- }
- j=regnum();
- if(j==RA){
- Cycles++;
- abd_index(pbyte+6);
- return;
- }
- if(j==RB){
- Cycles++;
- abd_index(pbyte+5);
- return;
- }
- if(j==RD){
- Cycles += 4;
- abd_index(pbyte+11);
- return;
- }
- eval();
- Optr++;
- while(*Optr=='-'){
- predec++;
- Optr++;
- }
- j=regnum();
- while( alpha(*Optr) )Optr++;
- while(*Optr=='+'){
- pstinc++;
- Optr++;
- }
- if(j==RPC || j==RPCR){
- if( pstinc || predec ){
- error("Auto Inc/Dec Illegal on PC");
- return;
- }
- if(j==RPC){
- if(Force_word){
- emit(pbyte+13);
- eword(Result);
- Cycles += 5;
- return;
- }
- if(Force_byte){
- emit(pbyte+12);
- emit(lobyte(Result));
- Cycles++;
- return;
- }
- if(Result>=-128 && Result <=127){
- emit(pbyte+12);
- emit(lobyte(Result));
- Cycles++;
- return;
- }
- else {
- emit(pbyte+13);
- eword(Result);
- Cycles += 5;
- return;
- }
- }
- /* PCR addressing */
- if(Force_word){
- emit(pbyte+13);
- eword(Result-(Pc+2));
- Cycles += 5;
- return;
- }
- if(Force_byte){
- emit(pbyte+12);
- emit(lobyte(Result-(Pc+1)));
- Cycles++;
- return;
- }
- k=Result-(Pc+2);
- if( k >= -128 && k <= 127){
- emit(pbyte+12);
- emit(lobyte(Result-(Pc+1)));
- Cycles++;
- return;
- }
- else{
- emit(pbyte+13);
- eword(Result-(Pc+2));
- Cycles += 5;
- return;
- }
- }
- if(predec || pstinc){
- if(Result != 0){
- error("Offset must be Zero");
- return;
- }
- if(predec>2 || pstinc>2){
- error("Auto Inc/Dec by 1 or 2 only");
- return;
- }
- if((predec==1 && (pbyte&0x10) != 0) ||
- (pstinc==1 && (pbyte&0x10) != 0)){
- error("No Auto Inc/Dec by 1 for Indirect");
- return;
- }
- if(predec && pstinc){
- error("Can't do both!");
- return;
- }
- if(predec)
- pbyte += predec+1;
- if(pstinc)
- pbyte += pstinc-1;
- pbyte += rtype(j);
- emit(pbyte);
- Cycles += 1 + predec + pstinc;
- return;
- }
- pbyte += rtype(j);
- if(Force_word){
- emit(pbyte+0x09);
- eword(Result);
- Cycles += 4;
- return;
- }
- if(Force_byte){
- emit(pbyte+0x08);
- emit(lobyte(Result));
- Cycles++;
- return;
- }
- if(Result==0){
- emit(pbyte+0x04);
- return;
- }
- if((Result >= -16) && (Result <= 15) && ((pbyte&16)==0)){
- pbyte &= 127;
- pbyte += Result&31;
- emit(pbyte);
- Cycles++;
- return;
- }
- if(Result >= -128 && Result <= 127){
- emit(pbyte+0x08);
- emit(lobyte(Result));
- Cycles++;
- return;
- }
- emit(pbyte+0x09);
- eword(Result);
- Cycles += 4;
- return;
- }
-
-
- /*
- * abd_index --- a,b or d indexed
- */
-
- abd_index(pbyte)
- int pbyte;
- {
- int k;
-
- Optr += 2;
- k=regnum();
- pbyte += rtype(k);
- emit(pbyte);
- return;
- }
-
- /*
- * rtype --- return register type in post-byte format
- */
- rtype(r)
- int r;
- {
- switch(r){
- case RX: return(0x00);
- case RY: return(0x20);
- case RU: return(0x40);
- case RS: return(0x60);
- }
- error("Illegal Register for Indexed");
- return(0);
- }
-
- /*
- * set_mode --- determine addressing mode from operand field
- */
- set_mode()
- {
- register char *p;
-
- if( *Operand == '#' )
- return(IMMED); /* immediate addressing */
- p = Operand;
- while( *p != EOS && *p != BLANK && *p != TAB){/* any , before break */
- if( *p == ',')
- return(IND); /* indexed addressing */
- p++;
- }
- if( *Operand == '[')
- return(INDIR); /* indirect addressing */
- return(OTHER); /* NOTA */
- }
-
- /*
- * regnum --- return register number of *Optr
- */
- regnum()
- {
- if( head(Optr,"D" ))return(RD);
- if( head(Optr,"d" ))return(RD);
- if( head(Optr,"X" ))return(RX);
- if( head(Optr,"x" ))return(RX);
- if( head(Optr,"Y" ))return(RY);
- if( head(Optr,"y" ))return(RY);
- if( head(Optr,"U" ))return(RU);
- if( head(Optr,"u" ))return(RU);
- if( head(Optr,"S" ))return(RS);
- if( head(Optr,"s" ))return(RS);
- if( head(Optr,"PC" ))return(RPC);
- if( head(Optr,"pc" ))return(RPC);
- if( head(Optr,"PCR" ))return(RPCR);
- if( head(Optr,"pcr" ))return(RPCR);
- if( head(Optr,"A" ))return(RA);
- if( head(Optr,"a" ))return(RA);
- if( head(Optr,"B" ))return(RB);
- if( head(Optr,"b" ))return(RB);
- if( head(Optr,"CC" ))return(RCC);
- if( head(Optr,"cc" ))return(RCC);
- if( head(Optr,"DP" ))return(RDP);
- if( head(Optr,"dp" ))return(RDP);
- return(ERR);
- }
-