home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
language
/
motasms.zoo
/
do9.c
< prev
next >
Wrap
Text File
|
1990-12-16
|
12KB
|
602 lines
/*
* 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);
}