📄 m68k.c
字号:
case '3': tmpreg&=0xFF; case '8': case 'C': install_operand(s[1],tmpreg); break; default: as_fatal("Internal error: Unknown mode #%c",s[1]); } break; case '+': case '-': case 'A': install_operand(s[1],opP->reg-ADDR); break; case 'B': tmpreg=get_num(opP->con1,80); switch(s[1]) { case 'g': if(opP->con1->e_siz) { /* Deal with fixed size stuff by hand */ switch(opP->con1->e_siz) { case 1: add_fix('b',opP->con1,1); break; case 2: add_fix('w',opP->con1,1); addword(0); break; case 3: add_fix('l',opP->con1,1); addword(0); addword(0); break; default: as_fatal("Bad size for expression %d",opP->con1->e_siz); } } else if(subs(opP->con1)) { /* We can't relax it */ the_ins.opcode[the_ins.numo-1]|=0xff; add_fix('l',opP->con1,1); addword(0); addword(0); } else if(adds(opP->con1)) { if (flagseen['m'] && (the_ins.opcode[0] >= 0x6200) && (the_ins.opcode[0] <= 0x6f00)) { add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF)); } else { add_frag(adds(opP->con1),offs(opP->con1),TAB(BRANCH,SZ_UNDEF)); } } else { /* JF: This is the WRONG thing to do add_frag((symbolS *)0,offs(opP->con1),TAB(BRANCH,BYTE)); */ the_ins.opcode[the_ins.numo-1]|=0xff; offs(opP->con1)+=4; add_fix('l',opP->con1,1); addword(0); addword(0); } break; case 'w': if(isvar(opP->con1)) { /* check for DBcc instruction */ if ((the_ins.opcode[0] & 0xf0f8) ==0x50c8) { /* size varies if patch */ /* needed for long form */ add_frag(adds(opP->con1),offs(opP->con1),TAB(DBCC,SZ_UNDEF)); break; } /* Don't ask! */ opP->con1->e_exp.X_add_number+=2; add_fix('w',opP->con1,1); } addword(0); break; case 'c': if(opP->con1->e_siz) { switch(opP->con1->e_siz) { case 2: add_fix('w',opP->con1,1) addword(0); break; case 3: the_ins.opcode[the_ins.numo-1]|=0x40; add_fix('l',opP->con1,1); addword(0); addword(0); break; default: as_bad("Bad size for offset, must be word or long"); break; } } else if(subs(opP->con1)) { add_fix('l',opP->con1,1); add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG)); } else if(adds(opP->con1)) { add_frag(adds(opP->con1),offs(opP->con1),TAB(FBRANCH,SZ_UNDEF)); } else { /* add_frag((symbolS *)0,offs(opP->con1),TAB(FBRANCH,SHORT)); */ the_ins.opcode[the_ins.numo-1]|=0x40; add_fix('l',opP->con1,1); addword(0); addword(4); } break; default: as_fatal("Internal error: operand type B%c unknown",s[1]); } break; case 'C': /* Ignore it */ break; case 'd': /* JF this is a kludge */ if(opP->mode==AOFF) { install_operand('s',opP->reg-ADDR); } else { char *tmpP; tmpP=opP->con1->e_end-2; opP->con1->e_beg++; opP->con1->e_end-=4; /* point to the , */ baseo=m68k_reg_parse(&tmpP); if(baseo<ADDR+0 || baseo>ADDR+7) { as_bad("Unknown address reg, using A0"); baseo=0; } else baseo-=ADDR; install_operand('s',baseo); } tmpreg=get_num(opP->con1,80); if(!issword(tmpreg)) { as_warn("Expression out of range, using 0"); tmpreg=0; } addword(tmpreg); break; case 'D': install_operand(s[1],opP->reg-DATA); break; case 'F': install_operand(s[1],opP->reg-FPREG); break; case 'I': tmpreg=1+opP->reg-COPNUM; if(tmpreg==8) tmpreg=0; install_operand(s[1],tmpreg); break; case 'J': /* JF foo */ switch(opP->reg) { case SFC: tmpreg=0; break; case DFC: tmpreg=0x001; break; case CACR: tmpreg=0x002; break; case USP: tmpreg=0x800; break; case VBR: tmpreg=0x801; break; case CAAR: tmpreg=0x802; break; case MSP: tmpreg=0x803; break; case ISP: tmpreg=0x804; break; default: abort(); } install_operand(s[1],tmpreg); break; case 'k': tmpreg=get_num(opP->con1,55); install_operand(s[1],tmpreg&0x7f); break; case 'l': tmpreg=opP->reg; if(s[1]=='w') { if(tmpreg&0x7FF0000) as_bad("Floating point register in register list"); insop(reverse_16_bits(tmpreg)); } else { if(tmpreg&0x700FFFF) as_bad("Wrong register in floating-point reglist"); install_operand(s[1],reverse_8_bits(tmpreg>>16)); } break; case 'L': tmpreg=opP->reg; if(s[1]=='w') { if(tmpreg&0x7FF0000) as_bad("Floating point register in register list"); insop(tmpreg); } else if(s[1]=='8') { if(tmpreg&0x0FFFFFF) as_bad("incorrect register in reglist"); install_operand(s[1],tmpreg>>24); } else { if(tmpreg&0x700FFFF) as_bad("wrong register in floating-point reglist"); else install_operand(s[1],tmpreg>>16); } break; case 'M': install_operand(s[1],get_num(opP->con1,60)); break; case 'O': tmpreg= (opP->mode==DREG) ? 0x20+opP->reg-DATA : (get_num(opP->con1,40)&0x1F); install_operand(s[1],tmpreg); break; case 'Q': tmpreg=get_num(opP->con1,10); if(tmpreg==8) tmpreg=0; install_operand(s[1],tmpreg); break; case 'R': /* This depends on the fact that ADDR registers are eight more than their corresponding DATA regs, so the result will have the ADDR_REG bit set */ install_operand(s[1],opP->reg-DATA); break; case 's': if(opP->reg==FPI) tmpreg=0x1; else if(opP->reg==FPS) tmpreg=0x2; else if(opP->reg==FPC) tmpreg=0x4; else abort(); install_operand(s[1],tmpreg); break; case 'S': /* Ignore it */ break; case 'T': install_operand(s[1],get_num(opP->con1,30)); break; case 'U': /* Ignore it */ break;#ifdef m68851 /* JF: These are out of order, I fear. */ case 'f': switch (opP->reg) { case SFC: tmpreg=0; break; case DFC: tmpreg=1; break; default: abort(); } install_operand(s[1],tmpreg); break; case 'P': switch(opP->reg) { case TC: tmpreg=0; break; case CAL: tmpreg=4; break; case VAL: tmpreg=5; break; case SCC: tmpreg=6; break; case AC: tmpreg=7; break; default: abort(); } install_operand(s[1],tmpreg); break; case 'V': if (opP->reg == VAL) break; abort(); case 'W': switch(opP->reg) { case DRP: tmpreg=1; break; case SRP: tmpreg=2; break; case CRP: tmpreg=3; break; default: abort(); } install_operand(s[1],tmpreg); break; case 'X': switch (opP->reg) { case BAD: case BAD+1: case BAD+2: case BAD+3: case BAD+4: case BAD+5: case BAD+6: case BAD+7: tmpreg = (4 << 10) | ((opP->reg - BAD) << 2); break; case BAC: case BAC+1: case BAC+2: case BAC+3: case BAC+4: case BAC+5: case BAC+6: case BAC+7: tmpreg = (5 << 10) | ((opP->reg - BAC) << 2); break; default: abort(); } install_operand(s[1], tmpreg); break; case 'Y': if (opP->reg == PSR) break; abort(); case 'Z': if (opP->reg == PCSR) break; abort();#endif /* m68851 */ default: as_fatal("Internal error: Operand type %c unknown",s[0]); } } /* By the time whe get here (FINALLY) the_ins contains the complete instruction, ready to be emitted. . . */}intget_regs(i,str,opP)struct m68k_op *opP;char *str;{ /* 26, 25, 24, 23-16, 15-8, 0-7 */ /* Low order 24 bits encoded fpc,fps,fpi,fp7-fp0,a7-a0,d7-d0 */ unsigned long int cur_regs = 0; int reg1, reg2;#define ADD_REG(x) { if(x==FPI) cur_regs|=(1<<24);\ else if(x==FPS) cur_regs|=(1<<25);\ else if(x==FPC) cur_regs|=(1<<26);\ else cur_regs|=(1<<(x-1)); } reg1=i; for(;;) { if(*str=='/') { ADD_REG(reg1); str++; } else if(*str=='-') { str++; reg2=m68k_reg_parse(&str); if(reg2<DATA || reg2>=FPREG+8 || reg1==FPI || reg1==FPS || reg1==FPC) { opP->error="unknown register in register list"; return FAIL; } while(reg1<=reg2) { ADD_REG(reg1); reg1++; } if(*str=='\0') break; } else if(*str=='\0') { ADD_REG(reg1); break; } else { opP->error="unknow character in register list"; return FAIL; }/* DJA -- Bug Fix. Did't handle d1-d2/a1 until the following instruction was added */ if (*str=='/') str ++; reg1=m68k_reg_parse(&str); if((reg1<DATA || reg1>=FPREG+8) && !(reg1==FPI || reg1==FPS || reg1==FPC)) { opP->error="unknown register in register list"; return FAIL; } } opP->reg=cur_regs; return OK;}intreverse_16_bits(in)int in;{ int out=0; int n; static int mask[16] = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000 }; for(n=0;n<16;n++) { if(in&mask[n]) out|=mask[15-n]; } return out;}intreverse_8_bits(in)int in;{ int out=0; int n; static int mask[8] = {0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, }; for(n=0;n<8;n++) { if(in&mask[n]) out|=mask[7-n]; } return out;}voidinstall_operand(mode,val)int mode;int val;{ switch(mode) { case 's': the_ins.opcode[0]|=val & 0xFF; /* JF FF is for M kludge */ break; case 'd': the_ins.opcode[0]|=val<<9; break; case '1': the_ins.opcode[1]|=val<<12; break; case '2': the_ins.opcode[1]|=val<<6; break; case '3': the_ins.opcode[1]|=val; break; case '4': the_ins.opcode[2]|=val<<12; break; case '5': the_ins.opcode[2]|=val<<6; break; case '6': /* DANGER! This is a hack to force cas2l and cas2w cmds to be three words long! */ the_ins.numo++; the_ins.opcode[2]|=val; break; case '7': the_ins.opcode[1]|=val<<7; break; case '8': the_ins.opcode[1]|=val<<10; break;#ifdef m68851 case '9': the_ins.opcode[1]|=val<<5; break;#endif case 't': the_ins.opcode[1]|=(val<<10)|(val<<7); break; case 'D': the_ins.opcode[1]|=(val<<12)|val; break; case 'g': the_ins.opcode[0]|=val=0xff; break; case 'i': the_ins.opcode[0]|=val<<9; break; case 'C': the_ins.opcode[1]|=val; break; case 'j': the_ins.opcode[1]|=val; the_ins.numo++; /* What a hack */ break; case 'k': the_ins.opcode[1]|=val<<4; break; case 'b': case 'w': case 'l': break; case 'c': default: abort(); }}voidinstall_gen_operand(mode,val)int mode;int val;{ switch(mode) { case 's': the_ins.opcode[0]|=val; break; case 'd': /* This is a kludge!!! */ the_ins.opcode[0]|=(val&0x07)<<9|(val&0x38)<<3; break; case 'b': case 'w': case 'l': case 'f': case 'F': case 'x': case 'p': the_ins.opcode[0]|=val; break; /* more stuff goes here */ default: abort(); }}char *crack_operand(str,opP)register char *str;register struct m68k_op *opP;{ register int parens; register int c; register char *beg_str; if(!str) { return str; } beg_str=str; for(parens=0;*str && (parens>0 || notend(str));str++) { if(*str=='(') parens++; else if(*str==')') { if(!parens) { /* ERROR */ opP->error="Extra )"; return str; } --parens; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -