URL
https://opencores.org/ocsvn/System09/System09/trunk
Subversion Repositories System09
[/] [System09/] [trunk/] [Tools/] [as09/] [do09.c] - Rev 83
Compare with Previous | Blame | View Log
/* * 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. */ void do_op(int opcode,int 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(0); } else if( mode == IND ){ do_indexed(op+0x20); return(0); } else if( mode == INDIR){ Optr++; emit(op+0x20); emit(IPBYTE); eval(); eword(Result); Cycles += 7; if(*Optr == ']'){ Optr++; return(0); } error("Missing ']'"); return(0); } else if( mode == OTHER){ eval(); if(Force_word){ emit(op+0x30); eword(Result); Cycles += 3; return(0); } if(Force_byte){ emit(op+0x10); emit(lobyte(Result)); Cycles += 2; return(0); } if(Result>=0 && Result <=0xFF){ emit(op+0x10); emit(lobyte(Result)); Cycles += 2; return(0); } else { emit(op+0x30); eword(Result); Cycles += 3; return(0); } } else { error("Unknown Addressing Mode"); return(0); } } /* * 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(0); } if(j==RB){ Cycles++; abd_index(pbyte+5); return(0); } if(j==RD){ Cycles += 4; abd_index(pbyte+11); return(0); } 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(0); } if(j==RPC){ if(Force_word){ emit(pbyte+13); eword(Result); Cycles += 5; return(0); } if(Force_byte){ emit(pbyte+12); emit(lobyte(Result)); Cycles++; return(0); } if(Result>=-128 && Result <=127){ emit(pbyte+12); emit(lobyte(Result)); Cycles++; return(0); } else { emit(pbyte+13); eword(Result); Cycles += 5; return(0); } } /* PCR addressing */ if(Force_word){ emit(pbyte+13); eword(Result-(Pc+2)); Cycles += 5; return(0); } if(Force_byte){ emit(pbyte+12); emit(lobyte(Result-(Pc+1))); Cycles++; return(0); } k=Result-(Pc+2); if( k >= -128 && k <= 127){ emit(pbyte+12); emit(lobyte(Result-(Pc+1))); Cycles++; return(0); } else{ emit(pbyte+13); eword(Result-(Pc+2)); Cycles += 5; return(0); } } if(predec || pstinc){ if(Result != 0){ error("Offset must be Zero"); return(0); } if(predec>2 || pstinc>2){ error("Auto Inc/Dec by 1 or 2 only"); return(0); } if((predec==1 && (pbyte&0x10) != 0) || (pstinc==1 && (pbyte&0x10) != 0)){ error("No Auto Inc/Dec by 1 for Indirect"); return(0); } if(predec && pstinc){ error("Can't do both!"); return(0); } if(predec) pbyte += predec+1; if(pstinc) pbyte += pstinc-1; pbyte += rtype(j); emit(pbyte); Cycles += 1 + predec + pstinc; return(0); } pbyte += rtype(j); if(Force_word){ emit(pbyte+0x09); eword(Result); Cycles += 4; return(0); } if(Force_byte){ emit(pbyte+0x08); emit(lobyte(Result)); Cycles++; return(0); } if(Result==0){ emit(pbyte+0x04); return(0); } if((Result >= -16) && (Result <= 15) && ((pbyte&16)==0)){ pbyte &= 127; pbyte += Result&31; emit(pbyte); Cycles++; return(0); } if(Result >= -128 && Result <= 127){ emit(pbyte+0x08); emit(lobyte(Result)); Cycles++; return(0); } emit(pbyte+0x09); eword(Result); Cycles += 4; return(0); } /* * abd_index --- a,b or d indexed */ abd_index(pbyte) int pbyte; { int k; Optr += 2; k=regnum(); pbyte += rtype(k); emit(pbyte); return(0); } /* * 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); }