📄 sparc.c
字号:
if (mask >= 32) { break; } } else { mask -= '0'; } switch (*args) { case 'e': opcode |= mask << 14; continue; case 'f': opcode |= mask; continue; case 'g': opcode |= mask << 25; continue; } } break; case 'F': if (strncmp(s, "%fsr", 4) == 0) { s += 4; continue; } break; case 'h': /* high 22 bits */ the_insn.reloc = RELOC_HI22; goto immediate; case 'l': /* 22 bit PC relative immediate */ the_insn.reloc = RELOC_WDISP22; the_insn.pcrel = 1; goto immediate; case 'L': /* 30 bit immediate */ the_insn.reloc = RELOC_WDISP30; the_insn.pcrel = 1; goto immediate; case 'i': /* 13 bit immediate */ the_insn.reloc = RELOC_BASE13; /*FALLTHROUGH*/ immediate: if(*s==' ') s++; if (*s == '%') { if ((c = s[1]) == 'h' && s[2] == 'i') { the_insn.reloc = RELOC_HI22; s+=3; } else if (c == 'l' && s[2] == 'o') { the_insn.reloc = RELOC_LO10; s+=3; } else break; } /* 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. */ { /* This stuff checks to see if the expression ends in +%reg If it does, it removes the register from the expression, and re-sets 's' to point to the right place */ char *s1; for(s1=s;*s1 && *s1!=','&& *s1!=']';s1++) ; if(s1!=s && isdigit(s1[-1])) { if(s1[-2]=='%' && s1[-3]=='+') { s1-=3; *s1='\0'; (void)getExpression(s); *s1='+'; s=s1; continue; } else if(index("goli0123456789",s1[-2]) && s1[-3]=='%' && s1[-4]=='+') { s1-=4; *s1='\0'; (void)getExpression(s); *s1='+'; s=s1; continue; } } } (void)getExpression(s); s = expr_end; continue; case 'a': if (*s++ == 'a') { opcode |= ANNUL; continue; } break; case 'A': /* alternate space */ if (isdigit(*s)) { long num; num=0; while (isdigit(*s)) { num= num*10 + *s-'0'; ++s; } opcode |= num<<5; continue; } break; /* abort(); */ case 'p': if (strncmp(s, "%psr", 4) == 0) { s += 4; continue; } break; case 'q': /* floating point queue */ if (strncmp(s, "%fq", 3) == 0) { s += 3; continue; } break; case 'Q': /* coprocessor queue */ if (strncmp(s, "%cq", 3) == 0) { s += 3; continue; } break; case 'S': if (strcmp(str, "set") == 0) { special_case = SPECIAL_CASE_SET; continue; } break; case 't': if (strncmp(s, "%tbr", 4) != 0) break; s += 4; continue; case 'w': if (strncmp(s, "%wim", 4) != 0) break; s += 4; continue; case 'y': if (strncmp(s, "%y", 2) != 0) break; s += 2; continue; default: abort(); } break; } error: if (match == FALSE) { /* Args don't match. */ if (&insn[1] - sparc_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;{ if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC) { switch (n) { case 1: *buf = val; break; case 2: *buf++ = (val>>8); *buf = val; break; case 4: *buf++ = (val>>24); *buf++ = (val>>16); *buf++ = (val>>8); *buf = val; break; default: abort(); } return; } assert(n == 4); assert(fixP->fx_r_type < NO_RELOC); /* * This is a hack. There should be a better way to * handle this. */ if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) { val += fixP->fx_where + fixP->fx_frag->fr_address; } switch (fixP->fx_r_type) { case RELOC_32: buf[0] = val >> 24; buf[1] = val >> 16; buf[2] = val >> 8; buf[3] = val; break;#if 0 case RELOC_8: /* These don't seem to ever be needed. */ case RELOC_16: case RELOC_DISP8: case RELOC_DISP16: case RELOC_DISP32:#endif case RELOC_WDISP30: val = (val >>= 2) + 1; buf[0] |= (val >> 24) & 0x3f; buf[1]= (val >> 16); buf[2] = val >> 8; buf[3] = val; break; case RELOC_HI22: if(!fixP->fx_addsy) { buf[1] |= (val >> 26) & 0x3f; buf[2] = val >> 18; buf[3] = val >> 10; } else { buf[2]=0; buf[3]=0; } break;#if 0 case RELOC_22: case RELOC_13:#endif case RELOC_LO10: if(!fixP->fx_addsy) { buf[2] |= (val >> 8) & 0x03; buf[3] = val; } else buf[3]=0; break;#if 0 case RELOC_SFA_BASE: case RELOC_SFA_OFF13: case RELOC_BASE10:#endif case RELOC_BASE13: buf[2] |= (val >> 8) & 0x1f; buf[3] = val; break; case RELOC_WDISP22: val = (val >>= 2) + 1; /* FALLTHROUGH */ case RELOC_BASE22: buf[1] |= (val >> 16) & 0x3f; buf[2] = val >> 8; buf[3] = val; break;#if 0 case RELOC_PC10: case RELOC_PC22: case RELOC_JMP_TBL: case RELOC_SEGOFF16: case RELOC_GLOB_DAT: case RELOC_JMP_SLOT: case RELOC_RELATIVE:#endif case NO_RELOC: default: as_warn("bad relocation type: 0x%02x", fixP->fx_r_type); break; } return;}/* should never be called for sparc */voidmd_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol) char *ptr; long from_addr, to_addr;{ fprintf(stderr, "sparc_create_short_jmp\n"); abort();}/* should never be called for sparc */voidmd_number_to_disp(buf,val,n) char *buf; long val;{ fprintf(stderr, "md_number_to_disp\n"); abort();}/* should never be called for sparc */voidmd_number_to_field(buf,val,fix) char *buf; long val; void *fix;{ fprintf(stderr, "sparc_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 sparc: 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 external, bits 6 & 5 unused, and the lower five bits as relocation type. 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 reloc_info_sparc *ri_p, ri;{ 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));}/* should never be called for sparc */voidmd_convert_frag(fragP) register fragS *fragP;{ fprintf(stderr, "sparc_convert_frag\n"); abort();}/* should never be called for sparc */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, "sparc_create_long_jump\n"); abort();}/* should never be called for sparc */intmd_estimate_size_before_relax(fragP, segtype) register fragS *fragP;{ fprintf(stderr, "sparc_estimate_size_before_relax\n"); abort(); return 0;}#if 0/* for debugging only */static voidprint_insn(insn) struct sparc_it *insn;{ char *Reloc[] = { "RELOC_8", "RELOC_16", "RELOC_32", "RELOC_DISP8", "RELOC_DISP16", "RELOC_DISP32", "RELOC_WDISP30", "RELOC_WDISP22", "RELOC_HI22", "RELOC_22", "RELOC_13", "RELOC_LO10", "RELOC_SFA_BASE", "RELOC_SFA_OFF13", "RELOC_BASE10", "RELOC_BASE13", "RELOC_BASE22", "RELOC_PC10", "RELOC_PC22", "RELOC_JMP_TBL", "RELOC_SEGOFF16", "RELOC_GLOB_DAT", "RELOC_JMP_SLOT", "RELOC_RELATIVE", "NO_RELOC" }; if (insn->error) { fprintf(stderr, "ERROR: %s\n"); } fprintf(stderr, "opcode=0x%08x\n", insn->opcode); fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]); 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;}#endif/* * Sparc 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_sparc 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 >= NO_RELOC) { fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); abort(); } 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_index = symbolP->sy_number; } else { ri.r_extern = 0; ri.r_index = 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) {/* ri.r_addend -= fixP->fx_where; */ ri.r_addend -= ri.r_address; } else { ri.r_addend = fixP->fx_addnumber; }/* md_ri_to_chars((char *) &ri, ri); */ append(&next_object_file_charP, (char *)& ri, sizeof(ri)); } } return;}intmd_parse_option(argP,cntP,vecP) char **argP; int *cntP; char ***vecP;{ return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -