📄 m68k.c
字号:
opP->mode==IMMED || opP->mode==REGLST) losing++; break; case '~': /* For now! (JF FOO is this right?) */ if(opP->mode==MSCR || opP->mode==DREG || opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST) losing++; break; case 'A': if(opP->mode!=AREG) losing++; break; case 'B': /* FOO */ if(opP->mode!=ABSL) losing++; break; case 'C': if(opP->mode!=MSCR || opP->reg!=CCR) losing++; break; case 'd': /* FOO This mode is a KLUDGE!! */ if(opP->mode!=AOFF && (opP->mode!=ABSL || opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')')) losing++; break; case 'D': if(opP->mode!=DREG) losing++; break; case 'F': if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7)) losing++; break; case 'I': if(opP->mode!=MSCR || opP->reg<COPNUM || opP->reg>=COPNUM+7) losing++; break; case 'J': if(opP->mode!=MSCR || opP->reg<USP || opP->reg>MSP) losing++; break; case 'k': if(opP->mode!=IMMED) losing++; break; case 'l': case 'L': if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) { if(s[1]=='8') losing++; else { opP->mode=REGLST; opP->reg=1<<(opP->reg-DATA); } } else if(opP->mode!=REGLST) { losing++; } else if(s[1]=='8' && opP->reg&0x0FFffFF) losing++; else if(s[1]=='3' && opP->reg&0x7000000) losing++; break; case 'M': if(opP->mode!=IMMED) losing++; else { long t; t=get_num(opP->con1,80); if(!issbyte(t) || isvar(opP->con1)) losing++; } break; case 'O': if(opP->mode!=DREG && opP->mode!=IMMED) losing++; break; case 'Q': if(opP->mode!=IMMED) losing++; else { long t; t=get_num(opP->con1,80); if(t<1 || t>8 || isvar(opP->con1)) losing++; } break; case 'R': if(opP->mode!=DREG && opP->mode!=AREG) losing++; break; case 's': if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC)) losing++; break; case 'S': if(opP->mode!=MSCR || opP->reg!=SR) losing++; break; case 'U': if(opP->mode!=MSCR || opP->reg!=USP) losing++; break; /* JF these are out of order. We could put them in order if we were willing to put up with bunches of #ifdef m68851s in the code */#ifdef m68851 /* Memory addressing mode used by pflushr */ case '|': if(opP->mode==MSCR || opP->mode==DREG || opP->mode==AREG || opP->mode==REGLST) losing++; break; case 'f': if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC)) losing++; break; case 'P': if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL && opP->reg != VAL && opP->reg != SCC && opP->reg != AC)) losing++; break; case 'V': if (opP->reg != VAL) losing++; break; case 'W': if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP && opP->reg != CRP)) losing++; break; case 'X': if (opP->mode != MSCR || (!(opP->reg >= BAD && opP->reg <= BAD+7) && !(opP->reg >= BAC && opP->reg <= BAC+7))) losing++; break; case 'Y': if (opP->reg != PSR) losing++; break; case 'Z': if (opP->reg != PCSR) losing++; break;#endif default: as_fatal("Internal error: Operand mode %c unknown",*s); } } if(!losing) break; opcode=opcode->m_next; if(!opcode) { /* Fell off the end */ the_ins.error="instruction/operands mismatch"; return; } losing=0; } the_ins.args=opcode->m_operands; the_ins.numargs=opcode->m_opnum; the_ins.numo=opcode->m_codenum; the_ins.opcode[0]=getone(opcode); the_ins.opcode[1]=gettwo(opcode); for(s=the_ins.args,opP= &the_ins.operands[0];*s;s+=2,opP++) { /* This switch is a doozy. What the first step; its a big one! */ switch(s[0]) { case '*': case '~': case '%': case ';': case '@': case '!': case '&': case '$': case '?': case '/':#ifdef m68851 case '|':#endif switch(opP->mode) { case IMMED: tmpreg=0x3c; /* 7.4 */ if(index("bwl",s[1])) nextword=get_num(opP->con1,80); else nextword=nextword=get_num(opP->con1,0); if(isvar(opP->con1)) add_fix(s[1],opP->con1,0); switch(s[1]) { case 'b': if(!isbyte(nextword)) opP->error="operand out of range"; addword(nextword); baseo=0; break; case 'w': if(!isword(nextword)) opP->error="operand out of range"; addword(nextword); baseo=0; break; case 'l': addword(nextword>>16); addword(nextword); baseo=0; break; case 'f': baseo=2; outro=8; break; case 'F': baseo=4; outro=11; break; case 'x': baseo=6; outro=15; break; case 'p': baseo=6; outro= -1; break; default: as_fatal("Internal error: Can't decode %c%c",*s,s[1]); } if(!baseo) break; /* We gotta put out some float */ if(seg(opP->con1)!=SEG_BIG) { int_to_gen(nextword); gen_to_words(words,baseo,(long int)outro); for(wordp=words;baseo--;wordp++) addword(*wordp); break; } /* Its BIG */ if(offs(opP->con1)>0) { as_warn("Bignum assumed to be binary bit-pattern"); if(offs(opP->con1)>baseo) { as_warn("Bignum too big for %c format; truncated",s[1]); offs(opP->con1)=baseo; } baseo-=offs(opP->con1); for(wordp=generic_bignum+offs(opP->con1)-1;offs(opP->con1)--;--wordp) addword(*wordp); while(baseo--) addword(0); break; } gen_to_words(words,baseo,(long int)outro); for(wordp=words;baseo--;wordp++) addword(*wordp); break; case DREG: tmpreg=opP->reg-DATA; /* 0.dreg */ break; case AREG: tmpreg=0x08+opP->reg-ADDR; /* 1.areg */ break; case AINDR: tmpreg=0x10+opP->reg-ADDR; /* 2.areg */ break; case ADEC: tmpreg=0x20+opP->reg-ADDR; /* 4.areg */ break; case AINC: tmpreg=0x18+opP->reg-ADDR; /* 3.areg */ break; case AOFF: nextword=get_num(opP->con1,80); /* Force into index mode. Hope this works */ /* We do the first bit for 32-bit displacements, and the second bit for 16 bit ones. It is possible that we should make the default be WORD instead of LONG, but I think that'd break GCC, so we put up with a little inefficiency for the sake of working output. */ if( !issword(nextword) || ( isvar(opP->con1) && ( ( opP->con1->e_siz==0 && flagseen['l']==0) || opP->con1->e_siz==3))) { if(opP->reg==PC) tmpreg=0x3B; /* 7.3 */ else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */ if(isvar(opP->con1)) { if(opP->reg==PC) { add_frag(adds(opP->con1), offs(opP->con1), TAB(PCLEA,SZ_UNDEF)); break; } else { addword(0x0170); add_fix('l',opP->con1,1); } } else addword(0x0170); addword(nextword>>16); } else { if(opP->reg==PC) tmpreg=0x3A; /* 7.2 */ else tmpreg=0x28+opP->reg-ADDR; /* 5.areg */ if(isvar(opP->con1)) { if(opP->reg==PC) { add_fix('w',opP->con1,1); } else add_fix('w',opP->con1,0); } } addword(nextword); break; case AINDX: case APODX: case AMIND: case APRDX: nextword=0; baseo=get_num(opP->con1,80); outro=get_num(opP->con2,80); /* Figure out the 'addressing mode' */ /* Also turn on the BASE_DISABLE bit, if needed */ if(opP->reg==PC || opP->reg==ZPC) { tmpreg=0x3b; /* 7.3 */ if(opP->reg==ZPC) nextword|=0x80; } else if(opP->reg==FAIL) { nextword|=0x80; tmpreg=0x30; /* 6.garbage */ } else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */ siz1= (opP->con1) ? opP->con1->e_siz : 0; siz2= (opP->con2) ? opP->con2->e_siz : 0; /* Index register stuff */ if(opP->ireg>=DATA+0 && opP->ireg<=ADDR+7) { nextword|=(opP->ireg-DATA)<<12; if(opP->isiz==0 || opP->isiz==3) nextword|=0x800; switch(opP->imul) { case 1: break; case 2: nextword|=0x200; break; case 4: nextword|=0x400; break; case 8: nextword|=0x600; break; default: abort(); } /* IF its simple, GET US OUT OF HERE! */ /* Must be INDEX, with an index register. Address register cannot be ZERO-PC, and either :b was forced, or we know it will fit */ if( opP->mode==AINDX && opP->reg!=FAIL && opP->reg!=ZPC && ( siz1==1 || ( issbyte(baseo) && !isvar(opP->con1)))) { nextword +=baseo&0xff; addword(nextword); if(isvar(opP->con1)) add_fix('B',opP->con1,0); break; } } else nextword|=0x40; /* No index reg */ /* It aint simple */ nextword|=0x100; /* If the guy specified a width, we assume that it is wide enough. Maybe it isn't. Ifso, we lose */ switch(siz1) { case 0: if(isvar(opP->con1) || !issword(baseo)) { siz1=3; nextword|=0x30; } else if(baseo==0) nextword|=0x10; else { nextword|=0x20; siz1=2; } break; case 1: as_warn("Byte dispacement won't work. Defaulting to :w"); case 2: nextword|=0x20; break; case 3: nextword|=0x30; break; } /* Figure out innner displacement stuff */ if(opP->mode!=AINDX) { switch(siz2) { case 0: if(isvar(opP->con2) || !issword(outro)) { siz2=3; nextword|=0x3; } else if(outro==0) nextword|=0x1; else { nextword|=0x2; siz2=2; } break; case 1: as_warn("Byte dispacement won't work. Defaulting to :w"); case 2: nextword|=0x2; break; case 3: nextword|=0x3; break; } if(opP->mode==APODX) nextword|=0x04; else if(opP->mode==AMIND) nextword|=0x40; } addword(nextword); if(isvar(opP->con1)) { if(opP->reg==PC || opP->reg==ZPC) { add_fix(siz1==3 ? 'l' : 'w',opP->con1,1); opP->con1->e_exp.X_add_number+=6; } else add_fix(siz1==3 ? 'l' : 'w',opP->con1,0); } if(siz1==3) addword(baseo>>16); if(siz1) addword(baseo); if(isvar(opP->con2)) { if(opP->reg==PC || opP->reg==ZPC) { add_fix(siz2==3 ? 'l' : 'w',opP->con2,1); opP->con1->e_exp.X_add_number+=6; } else add_fix(siz2==3 ? 'l' : 'w',opP->con2,0); } if(siz2==3) addword(outro>>16); if(siz2) addword(outro); break; case ABSL: nextword=get_num(opP->con1,80); switch(opP->con1->e_siz) { default: as_warn("Unknown size for absolute reference"); case 0: if(!isvar(opP->con1) && issword(offs(opP->con1))) { tmpreg=0x38; /* 7.0 */ addword(nextword); break; } /* Don't generate pc relative code on 68010 and 68000 */ if(isvar(opP->con1) && !subs(opP->con1) && seg(opP->con1)==SEG_TEXT && now_seg==SEG_TEXT && flagseen['m']==0 && !index("~%&$?", s[0])) { tmpreg=0x3A; /* 7.2 */ add_frag(adds(opP->con1), offs(opP->con1), TAB(PCREL,SZ_UNDEF)); break; } case 3: /* Fall through into long */ if(isvar(opP->con1)) add_fix('l',opP->con1,0); tmpreg=0x39; /* 7.1 mode */ addword(nextword>>16); addword(nextword); break; case 2: /* Word */ if(isvar(opP->con1)) add_fix('w',opP->con1,0); tmpreg=0x38; /* 7.0 mode */ addword(nextword); break; } break; case MSCR: default: as_bad("unknown/incorrect operand"); /* abort(); */ } install_gen_operand(s[1],tmpreg); break; case '#': case '^': switch(s[1]) { /* JF: I hate floating point! */ case 'j': tmpreg=70; break; case '8': tmpreg=20; break; case 'C': tmpreg=50; break; case '3': default: tmpreg=80; break; } tmpreg=get_num(opP->con1,tmpreg); if(isvar(opP->con1)) add_fix(s[1],opP->con1,0); switch(s[1]) { case 'b': /* Danger: These do no check for certain types of overflow. user beware! */ if(!isbyte(tmpreg)) opP->error="out of range"; insop(tmpreg); if(isvar(opP->con1)) the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; break; case 'w': if(!isword(tmpreg)) opP->error="out of range"; insop(tmpreg); if(isvar(opP->con1)) the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; break; case 'l': insop(tmpreg); /* Because of the way insop works, we put these two out backwards */ insop(tmpreg>>16); if(isvar(opP->con1)) the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -