asm.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "l.h"
  10. #define Dbufslop 100
  11. #define PADDR(a) ((a) & ~0xfffffffff0000000ull)
  12. int64_t
  13. entryvalue(void)
  14. {
  15. char *a;
  16. Sym *s;
  17. a = INITENTRY;
  18. if(*a >= '0' && *a <= '9')
  19. return atolwhex(a);
  20. s = lookup(a, 0);
  21. if(s->type == 0)
  22. return INITTEXT;
  23. switch(s->type) {
  24. case STEXT:
  25. break;
  26. case SDATA:
  27. if(dlm)
  28. return s->value+INITDAT;
  29. default:
  30. diag("entry not text: %s", s->name);
  31. }
  32. return s->value;
  33. }
  34. /* these need to take long arguments to be compatible with elf.c */void
  35. wputl(int32_t w)
  36. {
  37. cput(w);
  38. cput(w>>8);
  39. }
  40. void
  41. wput(int32_t w)
  42. {
  43. cput(w>>8);
  44. cput(w);
  45. }
  46. void
  47. lput(int32_t l)
  48. {
  49. cput(l>>24);
  50. cput(l>>16);
  51. cput(l>>8);
  52. cput(l);
  53. }
  54. void
  55. llput(int64_t v)
  56. {
  57. lput(v>>32);
  58. lput(v);
  59. }
  60. void
  61. lputl(int32_t l)
  62. {
  63. cput(l);
  64. cput(l>>8);
  65. cput(l>>16);
  66. cput(l>>24);
  67. }
  68. void
  69. llputl(int64_t v)
  70. {
  71. lputl(v);
  72. lputl(v>>32);
  73. }
  74. void
  75. strnput(char *s, int n)
  76. {
  77. for(; *s && n > 0; s++){
  78. cput(*s);
  79. n--;
  80. }
  81. while(n > 0){
  82. cput(0);
  83. n--;
  84. }
  85. }
  86. void
  87. asmb(void)
  88. {
  89. Prog *p;
  90. int32_t v, magic;
  91. int a;
  92. uint8_t *op1;
  93. int64_t vl;
  94. if(debug['v'])
  95. Bprint(&bso, "%5.2f asmb\n", cputime());
  96. Bflush(&bso);
  97. seek(cout, HEADR, 0);
  98. pc = INITTEXT;
  99. curp = firstp;
  100. for(p = firstp; p != P; p = p->link) {
  101. if(p->as == ATEXT)
  102. curtext = p;
  103. if(p->pc != pc) {
  104. if(!debug['a'])
  105. print("%P\n", curp);
  106. diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
  107. pc = p->pc;
  108. }
  109. curp = p;
  110. asmins(p);
  111. a = (andptr - and);
  112. if(cbc < a)
  113. cflush();
  114. if(debug['a']) {
  115. Bprint(&bso, pcstr, pc);
  116. for(op1 = and; op1 < andptr; op1++)
  117. Bprint(&bso, "%.2ux", *op1 & 0xff);
  118. Bprint(&bso, "\t%P\n", curp);
  119. }
  120. if(dlm) {
  121. if(p->as == ATEXT)
  122. reloca = nil;
  123. else if(reloca != nil)
  124. diag("reloc failure: %P", curp);
  125. }
  126. memmove(cbp, and, a);
  127. cbp += a;
  128. pc += a;
  129. cbc -= a;
  130. }
  131. cflush();
  132. switch(HEADTYPE) {
  133. default:
  134. diag("unknown header type %ld", HEADTYPE);
  135. case 2:
  136. case 5:
  137. case 6:
  138. seek(cout, HEADR+textsize, 0);
  139. break;
  140. }
  141. if(debug['v'])
  142. Bprint(&bso, "%5.2f datblk\n", cputime());
  143. Bflush(&bso);
  144. if(dlm){
  145. char buf[8];
  146. write(cout, buf, INITDAT-textsize);
  147. textsize = INITDAT;
  148. }
  149. for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
  150. if(datsize-v > sizeof(buf)-Dbufslop)
  151. datblk(v, sizeof(buf)-Dbufslop);
  152. else
  153. datblk(v, datsize-v);
  154. }
  155. symsize = 0;
  156. spsize = 0;
  157. lcsize = 0;
  158. if(!debug['s']) {
  159. if(debug['v'])
  160. Bprint(&bso, "%5.2f sym\n", cputime());
  161. Bflush(&bso);
  162. switch(HEADTYPE) {
  163. default:
  164. case 2:
  165. case 5:
  166. case 6:
  167. seek(cout, HEADR+textsize+datsize, 0);
  168. break;
  169. }
  170. if(!debug['s'])
  171. asmsym();
  172. if(debug['v'])
  173. Bprint(&bso, "%5.2f sp\n", cputime());
  174. Bflush(&bso);
  175. if(debug['v'])
  176. Bprint(&bso, "%5.2f pc\n", cputime());
  177. Bflush(&bso);
  178. if(!debug['s'])
  179. asmlc();
  180. if(dlm)
  181. asmdyn();
  182. cflush();
  183. }
  184. else if(dlm){
  185. seek(cout, HEADR+textsize+datsize, 0);
  186. asmdyn();
  187. cflush();
  188. }
  189. if(debug['v'])
  190. Bprint(&bso, "%5.2f headr\n", cputime());
  191. Bflush(&bso);
  192. seek(cout, 0L, 0);
  193. switch(HEADTYPE) {
  194. default:
  195. case 2: /* plan9 */
  196. magic = 4*26*26+7;
  197. magic |= 0x00008000; /* fat header */
  198. if(dlm)
  199. magic |= 0x80000000; /* dlm */
  200. lput(magic); /* magic */
  201. lput(textsize); /* sizes */
  202. lput(datsize);
  203. lput(bsssize);
  204. lput(symsize); /* nsyms */
  205. vl = entryvalue();
  206. lput(PADDR(vl)); /* va of entry */
  207. lput(spsize); /* sp offsets */
  208. lput(lcsize); /* line offsets */
  209. llput(vl); /* va of entry */
  210. break;
  211. case 5:
  212. elf32(debug['8']? I386: AMD64, ELFDATA2LSB, 0, nil);
  213. break;
  214. case 6:
  215. elf64(AMD64, ELFDATA2LSB, 0, nil);
  216. break;
  217. }
  218. cflush();
  219. }
  220. void
  221. cflush(void)
  222. {
  223. int n;
  224. n = sizeof(buf.cbuf) - cbc;
  225. if(n)
  226. write(cout, buf.cbuf, n);
  227. cbp = buf.cbuf;
  228. cbc = sizeof(buf.cbuf);
  229. }
  230. void
  231. datblk(int32_t s, int32_t n)
  232. {
  233. Prog *p;
  234. uint8_t *cast;
  235. int32_t l, fl, j;
  236. int64_t o;
  237. int i, c;
  238. memset(buf.dbuf, 0, n+Dbufslop);
  239. for(p = datap; p != P; p = p->link) {
  240. curp = p;
  241. l = p->from.sym->value + p->from.offset - s;
  242. c = p->from.scale;
  243. i = 0;
  244. if(l < 0) {
  245. if(l+c <= 0)
  246. continue;
  247. while(l < 0) {
  248. l++;
  249. i++;
  250. }
  251. }
  252. if(l >= n)
  253. continue;
  254. if(p->as != AINIT && p->as != ADYNT) {
  255. for(j=l+(c-i)-1; j>=l; j--)
  256. if(buf.dbuf[j]) {
  257. print("%P\n", p);
  258. diag("multiple initialization");
  259. break;
  260. }
  261. }
  262. switch(p->to.type) {
  263. case D_FCONST:
  264. switch(c) {
  265. default:
  266. case 4:
  267. fl = ieeedtof(&p->to.ieee);
  268. cast = (uint8_t*)&fl;
  269. if(debug['a'] && i == 0) {
  270. Bprint(&bso, pcstr, l+s+INITDAT);
  271. for(j=0; j<c; j++)
  272. Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
  273. Bprint(&bso, "\t%P\n", curp);
  274. }
  275. for(; i<c; i++) {
  276. buf.dbuf[l] = cast[fnuxi4[i]];
  277. l++;
  278. }
  279. break;
  280. case 8:
  281. cast = (uint8_t*)&p->to.ieee;
  282. if(debug['a'] && i == 0) {
  283. Bprint(&bso, pcstr, l+s+INITDAT);
  284. for(j=0; j<c; j++)
  285. Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
  286. Bprint(&bso, "\t%P\n", curp);
  287. }
  288. for(; i<c; i++) {
  289. buf.dbuf[l] = cast[fnuxi8[i]];
  290. l++;
  291. }
  292. break;
  293. }
  294. break;
  295. case D_SCONST:
  296. if(debug['a'] && i == 0) {
  297. Bprint(&bso, pcstr, l+s+INITDAT);
  298. for(j=0; j<c; j++)
  299. Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
  300. Bprint(&bso, "\t%P\n", curp);
  301. }
  302. for(; i<c; i++) {
  303. buf.dbuf[l] = p->to.scon[i];
  304. l++;
  305. }
  306. break;
  307. default:
  308. o = p->to.offset;
  309. if(p->to.type == D_ADDR) {
  310. if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
  311. diag("DADDR type%P", p);
  312. if(p->to.sym) {
  313. if(p->to.sym->type == SUNDEF)
  314. ckoff(p->to.sym, o);
  315. o += p->to.sym->value;
  316. if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
  317. o += INITDAT;
  318. if(dlm)
  319. dynreloc(p->to.sym, l+s+INITDAT, 1);
  320. }
  321. }
  322. fl = o;
  323. cast = (uint8_t*)&fl;
  324. switch(c) {
  325. default:
  326. diag("bad nuxi %d %d\n%P", c, i, curp);
  327. break;
  328. case 1:
  329. if(debug['a'] && i == 0) {
  330. Bprint(&bso, pcstr, l+s+INITDAT);
  331. for(j=0; j<c; j++)
  332. Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
  333. Bprint(&bso, "\t%P\n", curp);
  334. }
  335. for(; i<c; i++) {
  336. buf.dbuf[l] = cast[inuxi1[i]];
  337. l++;
  338. }
  339. break;
  340. case 2:
  341. if(debug['a'] && i == 0) {
  342. Bprint(&bso, pcstr, l+s+INITDAT);
  343. for(j=0; j<c; j++)
  344. Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
  345. Bprint(&bso, "\t%P\n", curp);
  346. }
  347. for(; i<c; i++) {
  348. buf.dbuf[l] = cast[inuxi2[i]];
  349. l++;
  350. }
  351. break;
  352. case 4:
  353. if(debug['a'] && i == 0) {
  354. Bprint(&bso, pcstr, l+s+INITDAT);
  355. for(j=0; j<c; j++)
  356. Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
  357. Bprint(&bso, "\t%P\n", curp);
  358. }
  359. for(; i<c; i++) {
  360. buf.dbuf[l] = cast[inuxi4[i]];
  361. l++;
  362. }
  363. break;
  364. case 8:
  365. cast = (uint8_t*)&o;
  366. if(debug['a'] && i == 0) {
  367. Bprint(&bso, pcstr, l+s+INITDAT);
  368. for(j=0; j<c; j++)
  369. Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
  370. Bprint(&bso, "\t%P\n", curp);
  371. }
  372. for(; i<c; i++) {
  373. buf.dbuf[l] = cast[inuxi8[i]];
  374. l++;
  375. }
  376. break;
  377. }
  378. break;
  379. }
  380. }
  381. write(cout, buf.dbuf, n);
  382. }
  383. int64_t
  384. rnd(int64_t v, int64_t r)
  385. {
  386. int64_t c;
  387. if(r <= 0)
  388. return v;
  389. v += r - 1;
  390. c = v % r;
  391. if(c < 0)
  392. c += r;
  393. v -= c;
  394. return v;
  395. }