📄 ns32k.c
字号:
with a size-tag. binary: msb -> lsb 0xxxxxxx byte 10xxxxxx xxxxxxxx word 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word This must be taken care of and we do it here! */void md_number_to_disp(buf,val,n) char *buf; long val; char n;{ switch(n) { case 1: if (val < -64 || val > 63) as_warn("Byte displacement out of range. line number not valid"); val&=0x7f;#ifdef SHOW_NUM printf("%x ",val & 0xff);#endif *buf++=val; break; case 2: if (val < -8192 || val > 8191) as_warn("Word displacement out of range. line number not valid"); val&=0x3fff; val|=0x8000;#ifdef SHOW_NUM printf("%x ",val>>8 & 0xff);#endif *buf++=(val>>8);#ifdef SHOW_NUM printf("%x ",val & 0xff);#endif *buf++=val; break; case 4: if (val < -0x1f000000 || val >= 0x20000000) /* if (val < -0x20000000 || val >= 0x20000000) */ as_warn("Double word displacement out of range"); val|=0xc0000000;#ifdef SHOW_NUM printf("%x ",val>>24 & 0xff);#endif *buf++=(val>>24);#ifdef SHOW_NUM printf("%x ",val>>16 & 0xff);#endif *buf++=(val>>16);#ifdef SHOW_NUM printf("%x ",val>>8 & 0xff);#endif *buf++=(val>>8);#ifdef SHOW_NUM printf("%x ",val & 0xff);#endif *buf++=val; break; default: as_fatal("Internal logic error"); }}void md_number_to_imm(buf,val,n) char *buf; long val; char n;{ switch(n) { case 1:#ifdef SHOW_NUM printf("%x ",val & 0xff);#endif *buf++=val; break; case 2:#ifdef SHOW_NUM printf("%x ",val>>8 & 0xff);#endif *buf++=(val>>8);#ifdef SHOW_NUM printf("%x ",val & 0xff);#endif *buf++=val; break; case 4:#ifdef SHOW_NUM printf("%x ",val>>24 & 0xff);#endif *buf++=(val>>24);#ifdef SHOW_NUM printf("%x ",val>>16 & 0xff);#endif *buf++=(val>>16);#ifdef SHOW_NUM printf("%x ",val>>8 & 0xff);#endif *buf++=(val>>8);#ifdef SHOW_NUM printf("%x ",val & 0xff);#endif *buf++=val; break; default: as_fatal("Internal logic error"); }}/* 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 *//* OVE: on a ns32k the twiddling continues at an even deeper level here we have to distinguish between displacements and immediates. The sequent has a bit for this. It also has a bit for relocobjects that points at the target for a bsr (BranchSubRoutine) !?!?!?! Using [] is importable but fast!! still, its rather funny :-) This md_ri.... is tailored for sequent. */void md_ri_to_chars(ri_p, ri) struct relocation_info *ri_p, ri;{ if (ri.r_bsr) {ri.r_pcrel=0;} /* sequent seems to want this */ md_number_to_chars((char*)ri_p, ri.r_address, sizeof(ri.r_address)); md_number_to_chars((char*)ri_p+4, (long)(ri.r_symbolnum ) | (long)(ri.r_pcrel << 24 ) | (long)(ri.r_length << 25 ) | (long)(ri.r_extern << 27 ) | (long)(ri.r_bsr << 28 ) | (long)(ri.r_disp << 29 ), 4); /* the first and second md_number_to_chars never overlaps (32bit cpu case) */}/* fast bitfiddling support *//* mask used to zero bitfield before oring in the true field */static unsigned long l_mask[]={ 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, };static unsigned long r_mask[]={ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, };#define MASK_BITS 31/* Insert bitfield described by field_ptr and val at buf This routine is written for modification of the first 4 bytes pointed to by buf, to yield speed. The ifdef stuff is for selection between a ns32k-dependent routine and a general version. (My advice: use the general version!) */void md_number_to_field(buf,val,field_ptr) register char *buf; register long val; register bit_fixS *field_ptr;{ register unsigned long object; register unsigned long mask;/* define ENDIAN on a ns32k machine */#ifdef ENDIAN register unsigned long *mem_ptr;#else register char *mem_ptr;#endif if (field_ptr->fx_bit_min<=val && val<=field_ptr->fx_bit_max) {#ifdef ENDIAN if (field_ptr->fx_bit_base) { /* override buf */ mem_ptr=(unsigned long*)field_ptr->fx_bit_base; } else { mem_ptr=(unsigned long*)buf; }#else if (field_ptr->fx_bit_base) { /* override buf */ mem_ptr=(char*)field_ptr->fx_bit_base; } else { mem_ptr=buf; }#endif mem_ptr+=field_ptr->fx_bit_base_adj;#ifdef ENDIAN /* we have a nice ns32k machine with lowbyte at low-physical mem */ object = *mem_ptr; /* get some bytes */#else /* OVE Goof! the machine is a m68k or dito */ /* That takes more byte fiddling */ object=0; object|=mem_ptr[3] & 0xff; object<<=8; object|=mem_ptr[2] & 0xff; object<<=8; object|=mem_ptr[1] & 0xff; object<<=8; object|=mem_ptr[0] & 0xff;#endif mask=0; mask|=(r_mask[field_ptr->fx_bit_offset]); mask|=(l_mask[field_ptr->fx_bit_offset+field_ptr->fx_bit_size]); object&=mask; val+=field_ptr->fx_bit_add; object|=((val<<field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));#ifdef ENDIAN *mem_ptr=object;#else mem_ptr[0]=(char)object; object>>=8; mem_ptr[1]=(char)object; object>>=8; mem_ptr[2]=(char)object; object>>=8; mem_ptr[3]=(char)object;#endif } else { as_warn("Bit field out of range"); }}/* Convert a relaxed displacement to dito in final output */void md_convert_frag(fragP)register fragS *fragP;{ long disp; long ext; /* Address in gas core of the place to store the displacement. */ register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal; /* Address in object code of the displacement. */ register int object_address = fragP -> fr_fix + fragP -> fr_address; know(fragP->fr_symbol); /* The displacement of the address, from current location. */ disp = (fragP->fr_symbol->sy_value + fragP->fr_offset) - object_address; disp+= fragP->fr_pcrel_adjust; switch(fragP->fr_subtype) { case IND(BRANCH,BYTE): ext=1; break; case IND(BRANCH,WORD): ext=2; break; case IND(BRANCH,DOUBLE): ext=4; break; } if(ext) { md_number_to_disp(buffer_address,(long)disp,(int)ext); fragP->fr_fix+=ext; }}/* This function returns the estimated size a variable object will occupy, one can say that we tries to guess the size of the objects before we actually know it */ md_estimate_size_before_relax(fragP,segtype) register fragS *fragP;{ int old_fix; old_fix=fragP->fr_fix; switch(fragP->fr_subtype) { case IND(BRANCH,UNDEF): if((fragP->fr_symbol->sy_type&N_TYPE)==segtype) { /* the symbol has been assigned a value */ fragP->fr_subtype=IND(BRANCH,BYTE); } else { /* we don't relax symbols defined in an other segment the thing to do is to assume the object will occupy 4 bytes */ fix_new_ns32k(fragP, (int)(fragP->fr_fix), 4, fragP->fr_symbol, (symbolS *)0, fragP->fr_offset, 1, fragP->fr_pcrel_adjust, 1, 0, fragP->fr_bsr); /*sequent hack */ fragP->fr_fix+=4; /* fragP->fr_opcode[1]=0xff; */ frag_wane(fragP); break; } case IND(BRANCH,BYTE): fragP->fr_var+=1; break; default: break; } return fragP->fr_var + fragP->fr_fix - old_fix;}int md_short_jump_size = 3;int md_long_jump_size = 5;voidmd_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol)char *ptr;long from_addr, to_addr;fragS *frag;symbolS *to_symbol;{ long offset; offset = to_addr - from_addr; md_number_to_chars(ptr, (long)0xEA ,1); md_number_to_disp(ptr+1,(long)offset,2);}voidmd_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)char *ptr;long from_addr, to_addr;fragS *frag;symbolS *to_symbol;{ long offset; offset= to_addr - from_addr; md_number_to_chars(ptr, (long)0xEA, 2); md_number_to_disp(ptr+2,(long)offset,4);}/* JF this is a new function to parse machine-dep options */intmd_parse_option(argP,cntP,vecP)char **argP;int *cntP;char ***vecP;{ switch(**argP) { case 'm': (*argP)++; if(!strcmp(*argP,"32032")) { cpureg = cpureg_032; mmureg = mmureg_032; } else if(!strcmp(*argP, "32532")) { cpureg = cpureg_532; mmureg = mmureg_532; } else as_warn("Unknown -m option ignored"); while(**argP) (*argP)++; break; default: return 0; } return 1;}/* * bit_fix_new() * * Create a bit_fixS in obstack 'notes'. * This struct is used to profile the normal fix. If the bit_fixP is a * valid pointer (not NULL) the bit_fix data will be used to format the fix. */bit_fixS *bit_fix_new (size,offset,min,max,add,base_type,base_adj) char size; /* Length of bitfield */ char offset; /* Bit offset to bitfield */ long base_type; /* 0 or 1, if 1 it's exploded to opcode ptr */ long base_adj; long min; /* Signextended min for bitfield */ long max; /* Signextended max for bitfield */ long add; /* Add mask, used for huffman prefix */{ register bit_fixS * bit_fixP; bit_fixP = (bit_fixS *)obstack_alloc(¬es,sizeof(bit_fixS)); bit_fixP -> fx_bit_size = size; bit_fixP -> fx_bit_offset = offset; bit_fixP -> fx_bit_base = base_type; bit_fixP -> fx_bit_base_adj = base_adj; bit_fixP -> fx_bit_max = max; bit_fixP -> fx_bit_min = min; bit_fixP -> fx_bit_add = add; return bit_fixP;}voidfix_new_ns32k (frag, where, size, add_symbol, sub_symbol, offset, pcrel, pcrel_adjust, im_disp, bit_fixP, bsr) fragS * frag; /* Which frag? */ int where; /* Where in that frag? */ short int size; /* 1, 2 or 4 usually. */ symbolS * add_symbol; /* X_add_symbol. */ symbolS * sub_symbol; /* X_subtract_symbol. */ long int offset; /* X_add_number. */ int pcrel; /* TRUE if PC-relative relocation. */ char pcrel_adjust; /* not zero if adjustment of pcrel offset is needed */ char im_disp; /* true if the value to write is a displacement */ bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if NULL */ char bsr; /* sequent-linker-hack: 1 when relocobject is a bsr */ { register fixS * fixP; fixP = (fixS *)obstack_alloc(¬es,sizeof(fixS)); fixP -> fx_frag = frag; fixP -> fx_where = where; fixP -> fx_size = size; fixP -> fx_addsy = add_symbol; fixP -> fx_subsy = sub_symbol; fixP -> fx_offset = offset; fixP -> fx_pcrel = pcrel; fixP -> fx_pcrel_adjust = pcrel_adjust; fixP -> fx_im_disp = im_disp; fixP -> fx_bit_fixP = bit_fixP; fixP -> fx_bsr = bsr; fixP -> fx_next = * seg_fix_rootP; * seg_fix_rootP = fixP;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -