subsegs.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* subsegs.c - subsegments -
  2. Copyright (C) 1987 Free Software Foundation, Inc.
  3. This file is part of GAS, the GNU Assembler.
  4. GAS is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 1, or (at your option)
  7. any later version.
  8. GAS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GAS; see the file COPYING. If not, write to
  14. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  15. /*
  16. * Segments & sub-segments.
  17. */
  18. #include "as.h"
  19. #include "subsegs.h"
  20. #include "obstack.h"
  21. #include "frags.h"
  22. #include "struc-symbol.h"
  23. #include "write.h"
  24. frchainS* frchain_root,
  25. * frchain_now, /* Commented in "subsegs.h". */
  26. * data0_frchainP;
  27. int /* in: segT out: N_TYPE bits */
  28. seg_N_TYPE[] = {
  29. N_ABS,
  30. N_TEXT,
  31. N_DATA,
  32. N_BSS,
  33. N_UNDF,
  34. N_UNDF,
  35. N_UNDF,
  36. N_UNDF,
  37. N_UNDF,
  38. N_UNDF
  39. };
  40. char * /* in: segT out: char* */
  41. seg_name[] = {
  42. "absolute",
  43. "text",
  44. "data",
  45. "bss",
  46. "unknown",
  47. "absent",
  48. "pass1",
  49. "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
  50. "bignum/flonum",
  51. "difference",
  52. ""
  53. }; /* Used by error reporters, dumpers etc. */
  54. segT N_TYPE_seg [N_TYPE+2] = /* N_TYPE == 0x1E = 32-2 */
  55. {
  56. SEG_UNKNOWN, /* N_UNDF == 0 */
  57. SEG_GOOF,
  58. SEG_ABSOLUTE, /* N_ABS == 2 */
  59. SEG_GOOF,
  60. SEG_TEXT, /* N_TEXT == 4 */
  61. SEG_GOOF,
  62. SEG_DATA, /* N_DATA == 6 */
  63. SEG_GOOF,
  64. SEG_BSS, /* N_BSS == 8 */
  65. SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  66. SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
  67. SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF
  68. };
  69. void
  70. subsegs_begin()
  71. {
  72. /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
  73. know( SEG_ABSOLUTE ==0 );
  74. know( SEG_TEXT ==1 );
  75. know( SEG_DATA ==2 );
  76. know( SEG_BSS ==3 );
  77. know( SEG_UNKNOWN ==4 );
  78. know( SEG_NONE ==5 );
  79. know( SEG_PASS1 ==6 );
  80. know( SEG_GOOF ==7 );
  81. know( SEG_BIG ==8 );
  82. know( SEG_DIFFERENCE ==9 );
  83. know( SEG_MAXIMUM_ORDINAL == SEG_DIFFERENCE );
  84. know( seg_name [(int) SEG_MAXIMUM_ORDINAL + 1] [0] == 0 );
  85. obstack_begin( &frags, 5000);
  86. frchain_root = NULL;
  87. frchain_now = NULL; /* Warn new_subseg() that we are booting. */
  88. /* Fake up 1st frag. */
  89. /* It won't be used=> is ok if obstack... */
  90. /* pads the end of it for alignment. */
  91. frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
  92. /* obstack_1blank( &frags, SIZEOF_STRUCT_FRAG, & frag_now ); */
  93. /* This 1st frag will not be in any frchain. */
  94. /* We simply give subseg_new somewhere to scribble. */
  95. now_subseg = 42; /* Lie for 1st call to subseg_new. */
  96. subseg_new (SEG_DATA, 0); /* .data 0 */
  97. data0_frchainP = frchain_now;
  98. }
  99. /*
  100. * subseg_change()
  101. *
  102. * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
  103. * subsegment. If we are already in the correct subsegment, change nothing.
  104. * This is used eg as a worker for subseg_new [which does make a new frag_now]
  105. * and for changing segments after we have read the source. We construct eg
  106. * fixSs even after the source file is read, so we do have to keep the
  107. * segment context correct.
  108. */
  109. void
  110. subseg_change (seg, subseg)
  111. register segT seg;
  112. register int subseg;
  113. {
  114. now_seg = seg;
  115. now_subseg = subseg;
  116. if (seg == SEG_DATA)
  117. {
  118. seg_fix_rootP = & data_fix_root;
  119. }
  120. else
  121. {
  122. know (seg == SEG_TEXT);
  123. seg_fix_rootP = & text_fix_root;
  124. }
  125. }
  126. /*
  127. * subseg_new()
  128. *
  129. * If you attempt to change to the current subsegment, nothing happens.
  130. *
  131. * In: segT, subsegT code for new subsegment.
  132. * frag_now -> incomplete frag for current subsegment.
  133. * If frag_now==NULL, then there is no old, incomplete frag, so
  134. * the old frag is not closed off.
  135. *
  136. * Out: now_subseg, now_seg updated.
  137. * Frchain_now points to the (possibly new) struct frchain for this
  138. * sub-segment.
  139. * Frchain_root updated if needed.
  140. */
  141. void
  142. subseg_new (seg, subseg) /* begin assembly for a new sub-segment */
  143. register segT seg; /* SEG_DATA or SEG_TEXT */
  144. register subsegT subseg;
  145. {
  146. long tmp; /* JF for obstack alignment hacking */
  147. know( seg == SEG_DATA || seg == SEG_TEXT );
  148. if (seg != now_seg || subseg != now_subseg)
  149. { /* we just changed sub-segments */
  150. register frchainS * frcP; /* crawl frchain chain */
  151. register frchainS** lastPP; /* address of last pointer */
  152. frchainS * newP; /* address of new frchain */
  153. register fragS * former_last_fragP;
  154. register fragS * new_fragP;
  155. if (frag_now) /* If not bootstrapping. */
  156. {
  157. frag_now -> fr_fix = obstack_next_free(& frags) - frag_now -> fr_literal;
  158. frag_wane(frag_now); /* Close off any frag in old subseg. */
  159. }
  160. /*
  161. * It would be nice to keep an obstack for each subsegment, if we swap
  162. * subsegments a lot. Hence we would have much fewer frag_wanes().
  163. */
  164. {
  165. obstack_finish( &frags);
  166. /*
  167. * If we don't do the above, the next object we put on obstack frags
  168. * will appear to start at the fr_literal of the current frag.
  169. * Also, above ensures that the next object will begin on a
  170. * address that is aligned correctly for the engine that runs
  171. * this program.
  172. */
  173. }
  174. subseg_change (seg, (int)subseg);
  175. /*
  176. * Attempt to find or make a frchain for that sub seg.
  177. * Crawl along chain of frchainSs, begins @ frchain_root.
  178. * If we need to make a frchainS, link it into correct
  179. * position of chain rooted in frchain_root.
  180. */
  181. for (frcP = * (lastPP = & frchain_root);
  182. frcP
  183. && (int)(frcP -> frch_seg) <= (int)seg;
  184. frcP = * ( lastPP = & frcP -> frch_next)
  185. )
  186. {
  187. if ( (int)(frcP -> frch_seg) == (int)seg
  188. && frcP -> frch_subseg >= subseg)
  189. {
  190. break;
  191. }
  192. }
  193. /*
  194. * frcP: Address of the 1st frchainS in correct segment with
  195. * frch_subseg >= subseg.
  196. * We want to either use this frchainS, or we want
  197. * to insert a new frchainS just before it.
  198. *
  199. * If frcP==NULL, then we are at the end of the chain
  200. * of frchainS-s. A NULL frcP means we fell off the end
  201. * of the chain looking for a
  202. * frch_subseg >= subseg, so we
  203. * must make a new frchainS.
  204. *
  205. * If we ever maintain a pointer to
  206. * the last frchainS in the chain, we change that pointer
  207. * ONLY when frcP==NULL.
  208. *
  209. * lastPP: Address of the pointer with value frcP;
  210. * Never NULL.
  211. * May point to frchain_root.
  212. *
  213. */
  214. if ( ! frcP
  215. || ( (int)(frcP -> frch_seg) > (int)seg
  216. || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
  217. {
  218. /*
  219. * This should be the only code that creates a frchainS.
  220. */
  221. newP=(frchainS *)obstack_alloc(&frags,sizeof(frchainS));
  222. /* obstack_1blank( &frags, sizeof(frchainS), &newP); */
  223. /* This begines on a good boundary */
  224. /* because a obstack_done() preceeded it. */
  225. /* It implies an obstack_done(), so we */
  226. /* expect the next object allocated to */
  227. /* begin on a correct boundary. */
  228. *lastPP = newP;
  229. newP -> frch_next = frcP; /* perhaps NULL */
  230. (frcP = newP) -> frch_subseg = subseg;
  231. newP -> frch_seg = seg;
  232. newP -> frch_last = NULL;
  233. }
  234. /*
  235. * Here with frcP ->ing to the frchainS for subseg.
  236. */
  237. frchain_now = frcP;
  238. /*
  239. * Make a fresh frag for the subsegment.
  240. */
  241. /* We expect this to happen on a correct */
  242. /* boundary since it was proceeded by a */
  243. /* obstack_done(). */
  244. tmp=obstack_alignment_mask(&frags); /* JF disable alignment */
  245. obstack_alignment_mask(&frags)=0;
  246. frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
  247. obstack_alignment_mask(&frags)=tmp;
  248. /* know( frags . obstack_c_next_free == frag_now -> fr_literal ); */
  249. /* But we want any more chars to come */
  250. /* immediately after the structure we just made. */
  251. new_fragP = frag_now;
  252. new_fragP -> fr_next = NULL;
  253. /*
  254. * Append new frag to current frchain.
  255. */
  256. former_last_fragP = frcP -> frch_last;
  257. if (former_last_fragP)
  258. {
  259. know( former_last_fragP -> fr_next == NULL );
  260. know( frchain_now -> frch_root );
  261. former_last_fragP -> fr_next = new_fragP;
  262. }
  263. else
  264. {
  265. frcP -> frch_root = new_fragP;
  266. }
  267. frcP -> frch_last = new_fragP;
  268. } /* if (changing subsegments) */
  269. } /* subseg_new() */
  270. /* end: subsegs.c */