📄 i860.c
字号:
case 'c': /* next operand must be a control register */ if (strncmp(s, "fir", 3) == 0) { opcode |= 0x0 << 21; s += 3; continue; } if (strncmp(s, "psr", 3) == 0) { opcode |= 0x1 << 21; s += 3; continue; } if (strncmp(s, "dirbase", 7) == 0) { opcode |= 0x2 << 21; s += 7; continue; } if (strncmp(s, "db", 2) == 0) { opcode |= 0x3 << 21; s += 2; continue; } if (strncmp(s, "fsr", 3) == 0) { opcode |= 0x4 << 21; s += 3; continue; } if (strncmp(s, "epsr", 4) == 0) { opcode |= 0x5 << 21; s += 4; continue; } break; case '5': /* 5 bit immediate in src1 */ bzero(&the_insn, sizeof(the_insn)); if ( !getExpression(s)) { s = expr_end; if (the_insn.exp.X_add_number & ~0x1f) as_warn("5-bit immediate too large"); opcode |= (the_insn.exp.X_add_number & 0x1f) << 11; bzero(&the_insn, sizeof(the_insn)); the_insn.reloc = NO_RELOC; continue; } break; case 'l': /* 26 bit immediate, relative branch */ the_insn.reloc = BRADDR; the_insn.pcrel = TRUE; goto immediate; case 's': /* 16 bit immediate, split relative branch */ /* upper 5 bits of offset in dest field */ the_insn.pcrel = TRUE; the_insn.reloc = SPLIT0; goto immediate; case 'S': /* 16 bit immediate, split (st), aligned */ if (opcode & (1 << 28)) if (opcode & 0x1) the_insn.reloc = SPLIT2; else the_insn.reloc = SPLIT1; else the_insn.reloc = SPLIT0; goto immediate; case 'I': /* 16 bit immediate, aligned */ if (opcode & (1 << 28)) if (opcode & 0x1) the_insn.reloc = LOW2; else the_insn.reloc = LOW1; else the_insn.reloc = LOW0; goto immediate; case 'i': /* 16 bit immediate */ the_insn.reloc = LOW0; /*FALLTHROUGH*/ immediate: if(*s==' ') s++; if (strncmp(s, "ha%", 3) == 0) { the_insn.highlow = HIGHADJ; s += 3; } else if (strncmp(s, "h%", 2) == 0) { the_insn.highlow = HIGH; s += 2; } else if (strncmp(s, "l%", 2) == 0) { the_insn.highlow = PAIR; s += 2; } the_insn.expand = insn->expand; /* Note that if the getExpression() fails, we will still have created U entries in the symbol table for the 'symbols' in the input string. Try not to create U symbols for registers, etc. */ if ( !getExpression(s)) { s = expr_end; continue; } break; default: abort(); } break; } error: if (match == FALSE) { /* Args don't match. */ if (&insn[1] - i860_opcodes < NUMOPCODES && !strcmp(insn->name, insn[1].name)) { ++insn; s = argsStart; continue; } else { as_warn("Illegal operands"); return; } } break; } the_insn.opcode = opcode; return;}static intgetExpression(str) char *str;{ char *save_in; segT seg; save_in = input_line_pointer; input_line_pointer = str; switch (seg = expression(&the_insn.exp)) { case SEG_ABSOLUTE: case SEG_TEXT: case SEG_DATA: case SEG_BSS: case SEG_UNKNOWN: case SEG_DIFFERENCE: case SEG_BIG: case SEG_NONE: break; default: the_insn.error = "bad segment"; expr_end = input_line_pointer; input_line_pointer=save_in; return 1; } expr_end = input_line_pointer; input_line_pointer = save_in; return 0;}/* This is identical to the md_atof in m68k.c. I think this is right, but I'm not sure. Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS emitted is stored in *sizeP . An error message is returned, or NULL on OK. *//* Equal to MAX_PRECISION in atof-ieee.c */#define MAX_LITTLENUMS 6char *md_atof(type,litP,sizeP) char type; char *litP; int *sizeP;{ int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; char *atof_ieee(); switch(type) { case 'f': case 'F': case 's': case 'S': prec = 2; break; case 'd': case 'D': case 'r': case 'R': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP=0; return "Bad call to MD_ATOF()"; } t=atof_ieee(input_line_pointer,type,words); if(t) input_line_pointer=t; *sizeP=prec * sizeof(LITTLENUM_TYPE); for(wordP=words;prec--;) { md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); litP+=sizeof(LITTLENUM_TYPE); } return ""; /* Someone should teach Dean about null pointers */}/* * Write out big-endian. */voidmd_number_to_chars(buf,val,n) char *buf; long val; int n;{ switch(n) { case 4: *buf++ = val >> 24; *buf++ = val >> 16; case 2: *buf++ = val >> 8; case 1: *buf = val; break; default: abort(); } return;}voidmd_number_to_imm(buf,val,n, fixP, seg_type) char *buf; long val; int n; fixS *fixP; int seg_type;{ enum reloc_type reloc = fixP->fx_r_type & 0xf; enum highlow_type highlow = (fixP->fx_r_type >> 4) & 0x3; assert(buf); assert(n == 4); /* always on i860 */ switch(highlow) { case HIGHADJ: /* adjusts the high-order 16-bits */ if (val & (1 << 15)) val += (1 << 16); /*FALLTHROUGH*/ case HIGH: /* selects the high-order 16-bits */ val >>= 16; break; case PAIR: /* selects the low-order 16-bits */ val = val & 0xffff; break; default: break; } switch(reloc) { case BRADDR: /* br,call,bc,bc.t,bnc,bnc.t w/26-bit immediate */ if (fixP->fx_pcrel != TRUE) as_warn("26-bit branch w/o pc relative set: 0x%08x", val); val >>= 2; /* align pcrel offset, see manual */ if (val >= (1 << 25) || val < -(1 << 25)) /* check for overflow */ as_warn("26-bit branch offset overflow: 0x%08x", val); buf[0] = (buf[0] & 0xfc) | ((val >> 24) & 0x3); buf[1] = val >> 16; buf[2] = val >> 8; buf[3] = val; break; case SPLIT2: /* 16 bit immediate, 4-byte aligned */ if (val & 0x3) as_warn("16-bit immediate 4-byte alignment error: 0x%08x", val); val &= ~0x3; /* 4-byte align value */ /*FALLTHROUGH*/ case SPLIT1: /* 16 bit immediate, 2-byte aligned */ if (val & 0x1) as_warn("16-bit immediate 2-byte alignment error: 0x%08x", val); val &= ~0x1; /* 2-byte align value */ /*FALLTHROUGH*/ case SPLIT0: /* st,bla,bte,btne w/16-bit immediate */ if (fixP->fx_pcrel == TRUE) val >>= 2; /* align pcrel offset, see manual */ /* check for bounds */ if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15))) as_warn("16-bit branch offset overflow: 0x%08x", val); buf[1] = (buf[1] & ~0x1f) | ((val >> 11) & 0x1f); buf[2] = (buf[2] & ~0x7) | ((val >> 8) & 0x7); buf[3] |= val; /* perserve bottom opcode bits */ break; case LOW4: /* fld,pfld,pst,flush 16-byte aligned */ if (val & 0xf) as_warn("16-bit immediate 16-byte alignment error: 0x%08x", val); val &= ~0xf; /* 16-byte align value */ /*FALLTHROUGH*/ case LOW3: /* fld,pfld,pst,flush 8-byte aligned */ if (val & 0x7) as_warn("16-bit immediate 8-byte alignment error: 0x%08x", val); val &= ~0x7; /* 8-byte align value */ /*FALLTHROUGH*/ case LOW2: /* 16 bit immediate, 4-byte aligned */ if (val & 0x3) as_warn("16-bit immediate 4-byte alignment error: 0x%08x", val); val &= ~0x3; /* 4-byte align value */ /*FALLTHROUGH*/ case LOW1: /* 16 bit immediate, 2-byte aligned */ if (val & 0x1) as_warn("16-bit immediate 2-byte alignment error: 0x%08x", val); val &= ~0x1; /* 2-byte align value */ /*FALLTHROUGH*/ case LOW0: /* 16 bit immediate, byte aligned */ /* check for bounds */ if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15))) as_warn("16-bit immediate overflow: 0x%08x", val); buf[2] = val >> 8; buf[3] |= val; /* perserve bottom opcode bits */ break; case NO_RELOC: default: as_warn("bad relocation type: 0x%02x", reloc); break; } return;}/* should never be called for i860 */voidmd_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol) char *ptr; long from_addr, to_addr;{ fprintf(stderr, "i860_create_short_jmp\n"); abort();}/* should never be called for i860 */voidmd_number_to_disp(buf,val,n) char *buf; long val;{ fprintf(stderr, "md_number_to_disp\n"); abort();}/* should never be called for i860 */voidmd_number_to_field(buf,val,fix) char *buf; long val; void *fix;{ fprintf(stderr, "i860_number_to_field\n"); abort();}/* the bit-field entries in the relocation_info struct plays hell with the byte-order problems of cross-assembly. So as a hack, I added this mach. dependent ri twiddler. Ugly, but it gets you there. -KWK *//* on i860: first 4 bytes are normal unsigned long address, next three bytes are index, most sig. byte first. Byte 7 is broken up with bit 7 as pcrel, bit 6 as extern, and the lower six bits as relocation type (highlow 5-4). Next 4 bytes are long int addend. *//* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */voidmd_ri_to_chars(ri_p, ri) struct relocation_info *ri_p, ri;{#if 0 unsigned char the_bytes[sizeof(*ri_p)]; /* this is easy */ md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address)); /* now the fun stuff */ the_bytes[4] = (ri.r_index >> 16) & 0x0ff; the_bytes[5] = (ri.r_index >> 8) & 0x0ff; the_bytes[6] = ri.r_index & 0x0ff; the_bytes[7] = ((ri.r_extern << 7) & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F); /* Also easy */ md_number_to_chars(&the_bytes[8], ri.r_addend, sizeof(ri.r_addend)); /* now put it back where you found it, Junior... */ bcopy (the_bytes, (char *)ri_p, sizeof(*ri_p));#endif}/* should never be called for i860 */voidmd_convert_frag(fragP) register fragS *fragP;{ fprintf(stderr, "i860_convert_frag\n"); abort();}/* should never be called for i860 */voidmd_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol) char *ptr; long from_addr, to_addr; fragS *frag; symbolS *to_symbol;{ fprintf(stderr, "i860_create_long_jump\n"); abort();}/* should never be called for i860 */intmd_estimate_size_before_relax(fragP, segtype) register fragS *fragP;{ fprintf(stderr, "i860_estimate_size_before_relax\n"); abort(); return 0;}/* for debugging only, must match enum reloc_type */static char *Reloc[] = { "NO_RELOC", "BRADDR", "LOW0", "LOW1", "LOW2", "LOW3", "LOW4", "SPLIT0", "SPLIT1", "SPLIT2", "RELOC_32", };static char *Highlow[] = { "NO_SPEC", "PAIR", "HIGH", "HIGHADJ", };static voidprint_insn(insn) struct i860_it *insn;{ if (insn->error) { fprintf(stderr, "ERROR: %s\n"); } fprintf(stderr, "opcode=0x%08x\t", insn->opcode); fprintf(stderr, "expand=0x%08x\t", insn->expand); fprintf(stderr, "reloc = %s\t", Reloc[insn->reloc]); fprintf(stderr, "highlow = %s\n", Highlow[insn->highlow]); fprintf(stderr, "exp = {\n"); fprintf(stderr, "\t\tX_add_symbol = %s\n", insn->exp.X_add_symbol ? (insn->exp.X_add_symbol->sy_name ? insn->exp.X_add_symbol->sy_name : "???") : "0"); fprintf(stderr, "\t\tX_sub_symbol = %s\n", insn->exp.X_subtract_symbol ? (insn->exp.X_subtract_symbol->sy_name ? insn->exp.X_subtract_symbol->sy_name : "???") : "0"); fprintf(stderr, "\t\tX_add_number = %d\n", insn->exp.X_add_number); fprintf(stderr, "}\n"); return;}intmd_parse_option(argP,cntP,vecP) char **argP; int *cntP; char ***vecP;{ return 1;}/* * I860 relocations are completely different, so it needs * this machine dependent routine to emit them. */voidemit_relocations(fixP, segment_address_in_file) register fixS *fixP; relax_addressT segment_address_in_file;{ struct reloc_info_i860 ri; register symbolS *symbolP; extern char *next_object_file_charP; long add_number; bzero((char *) &ri, sizeof(ri)); for (; fixP; fixP = fixP->fx_next) { if (fixP->fx_r_type & ~0x3f) { fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); abort(); } ri.r_pcrel = fixP->fx_pcrel; ri.r_type = fixP->fx_r_type; if ((symbolP = fixP->fx_addsy) != NULL) { ri.r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file; if ((symbolP->sy_type & N_TYPE) == N_UNDF) { ri.r_extern = 1; ri.r_symbolnum = symbolP->sy_number; } else { ri.r_extern = 0; ri.r_symbolnum = symbolP->sy_type & N_TYPE; } if (symbolP && symbolP->sy_frag) { ri.r_addend = symbolP->sy_frag->fr_address; } ri.r_type = fixP->fx_r_type; if (fixP->fx_pcrel) { /* preserve actual offset vs. pc + 4 */ ri.r_addend -= (ri.r_address + 4); } else { ri.r_addend = fixP->fx_addnumber; } md_ri_to_chars((char *) &ri, ri); append(&next_object_file_charP, (char *)& ri, sizeof(ri)); } } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -