asm.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830
  1. #include "l.h"
  2. long OFFSET;
  3. static Prog *PP;
  4. long
  5. entryvalue(void)
  6. {
  7. char *a;
  8. Sym *s;
  9. a = INITENTRY;
  10. if(*a >= '0' && *a <= '9')
  11. return atolwhex(a);
  12. s = lookup(a, 0);
  13. if(s->type == 0)
  14. return INITTEXT;
  15. switch(s->type) {
  16. case STEXT:
  17. case SLEAF:
  18. break;
  19. case SDATA:
  20. if(dlm)
  21. return s->value+INITDAT;
  22. default:
  23. diag("entry not text: %s", s->name);
  24. }
  25. return s->value;
  26. }
  27. void
  28. asmb(void)
  29. {
  30. Prog *p;
  31. long t, etext;
  32. Optab *o;
  33. if(debug['v'])
  34. Bprint(&bso, "%5.2f asm\n", cputime());
  35. Bflush(&bso);
  36. OFFSET = HEADR;
  37. seek(cout, OFFSET, 0);
  38. pc = INITTEXT;
  39. for(p = firstp; p != P; p = p->link) {
  40. if(p->as == ATEXT) {
  41. curtext = p;
  42. autosize = p->to.offset + 4;
  43. }
  44. if(p->pc != pc) {
  45. diag("phase error %lux sb %lux",
  46. p->pc, pc);
  47. if(!debug['a'])
  48. prasm(curp);
  49. pc = p->pc;
  50. }
  51. curp = p;
  52. o = oplook(p); /* could probably avoid this call */
  53. asmout(p, o);
  54. pc += o->size;
  55. }
  56. if(debug['a'])
  57. Bprint(&bso, "\n");
  58. Bflush(&bso);
  59. cflush();
  60. /* output strings in text segment */
  61. etext = INITTEXT + textsize;
  62. for(t = pc; t < etext; t += sizeof(buf)-100) {
  63. if(etext-t > sizeof(buf)-100)
  64. datblk(t, sizeof(buf)-100, 1);
  65. else
  66. datblk(t, etext-t, 1);
  67. }
  68. curtext = P;
  69. switch(HEADTYPE) {
  70. case 0:
  71. case 1:
  72. case 2:
  73. case 5:
  74. case 7:
  75. OFFSET = HEADR+textsize;
  76. seek(cout, OFFSET, 0);
  77. break;
  78. case 3:
  79. case 6: /* no header, padded segments */
  80. OFFSET = rnd(HEADR+textsize, 4096);
  81. seek(cout, OFFSET, 0);
  82. break;
  83. }
  84. if(dlm){
  85. char buf[8];
  86. write(cout, buf, INITDAT-textsize);
  87. textsize = INITDAT;
  88. }
  89. for(t = 0; t < datsize; t += sizeof(buf)-100) {
  90. if(datsize-t > sizeof(buf)-100)
  91. datblk(t, sizeof(buf)-100, 0);
  92. else
  93. datblk(t, datsize-t, 0);
  94. }
  95. symsize = 0;
  96. lcsize = 0;
  97. if(!debug['s']) {
  98. if(debug['v'])
  99. Bprint(&bso, "%5.2f sym\n", cputime());
  100. Bflush(&bso);
  101. switch(HEADTYPE) {
  102. case 0:
  103. case 1:
  104. case 4:
  105. case 5:
  106. debug['s'] = 1;
  107. break;
  108. case 2:
  109. OFFSET = HEADR+textsize+datsize;
  110. seek(cout, OFFSET, 0);
  111. break;
  112. case 3:
  113. case 6: /* no header, padded segments */
  114. OFFSET += rnd(datsize, 4096);
  115. seek(cout, OFFSET, 0);
  116. break;
  117. case 7:
  118. break;
  119. }
  120. if(!debug['s'])
  121. asmsym();
  122. if(debug['v'])
  123. Bprint(&bso, "%5.2f pc\n", cputime());
  124. Bflush(&bso);
  125. if(!debug['s'])
  126. asmlc();
  127. if(dlm)
  128. asmdyn();
  129. cflush();
  130. }
  131. else if(dlm){
  132. seek(cout, HEADR+textsize+datsize, 0);
  133. asmdyn();
  134. cflush();
  135. }
  136. if(debug['v'])
  137. Bprint(&bso, "%5.2f header\n", cputime());
  138. Bflush(&bso);
  139. OFFSET = 0;
  140. seek(cout, OFFSET, 0);
  141. switch(HEADTYPE) {
  142. case 0: /* no header */
  143. case 6: /* no header, padded segments */
  144. break;
  145. case 1: /* aif for risc os */
  146. lputl(0xe1a00000); /* NOP - decompress code */
  147. lputl(0xe1a00000); /* NOP - relocation code */
  148. lputl(0xeb000000 + 12); /* BL - zero init code */
  149. lputl(0xeb000000 +
  150. (entryvalue()
  151. - INITTEXT
  152. + HEADR
  153. - 12
  154. - 8) / 4); /* BL - entry code */
  155. lputl(0xef000011); /* SWI - exit code */
  156. lputl(textsize+HEADR); /* text size */
  157. lputl(datsize); /* data size */
  158. lputl(0); /* sym size */
  159. lputl(bsssize); /* bss size */
  160. lputl(0); /* sym type */
  161. lputl(INITTEXT-HEADR); /* text addr */
  162. lputl(0); /* workspace - ignored */
  163. lputl(32); /* addr mode / data addr flag */
  164. lputl(0); /* data addr */
  165. for(t=0; t<2; t++)
  166. lputl(0); /* reserved */
  167. for(t=0; t<15; t++)
  168. lputl(0xe1a00000); /* NOP - zero init code */
  169. lputl(0xe1a0f00e); /* B (R14) - zero init return */
  170. break;
  171. case 2: /* plan 9 */
  172. if(dlm)
  173. lput(0x80000000|0x647); /* magic */
  174. else
  175. lput(0x647); /* magic */
  176. lput(textsize); /* sizes */
  177. lput(datsize);
  178. lput(bsssize);
  179. lput(symsize); /* nsyms */
  180. lput(entryvalue()); /* va of entry */
  181. lput(0L);
  182. lput(lcsize);
  183. break;
  184. case 3: /* boot for NetBSD */
  185. lput((143<<16)|0413); /* magic */
  186. lputl(rnd(HEADR+textsize, 4096));
  187. lputl(rnd(datsize, 4096));
  188. lputl(bsssize);
  189. lputl(symsize); /* nsyms */
  190. lputl(entryvalue()); /* va of entry */
  191. lputl(0L);
  192. lputl(0L);
  193. break;
  194. case 4: /* boot for IXP1200 */
  195. break;
  196. case 5: /* boot for ipaq */
  197. lputl(0xe3300000); /* nop */
  198. lputl(0xe3300000); /* nop */
  199. lputl(0xe3300000); /* nop */
  200. lputl(0xe3300000); /* nop */
  201. break;
  202. case 7: /* elf */
  203. strnput("\177ELF", 4); /* e_ident */
  204. cput(1); /* class = 32 bit */
  205. cput(2); /* data = MSB */
  206. cput(1); /* version = CURRENT */
  207. strnput("", 9);
  208. lput((2L<<16)|40); /* type = EXEC; machine = ARM */
  209. lput(1L); /* version = CURRENT */
  210. lput(entryvalue()); /* entry vaddr */
  211. lput(52L); /* offset to first phdr */
  212. debug['S'] = 1; /* no symbol table */
  213. if(debug['S']){
  214. lput(HEADR+textsize+datsize+symsize); /* offset to first shdr */
  215. lput(0L); /* flags = PPC */
  216. lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/
  217. lput((4L<<16)|40L); /* # Phdrs & Shdr size */
  218. lput((4L<<16)|2L); /* # Shdrs & shdr string size */
  219. }
  220. else{
  221. lput(0L);
  222. lput(0L); /* flags = PPC */
  223. lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/
  224. lput((4L<<16)|0L); /* # Phdrs & Shdr size */
  225. lput((4L<<16)|0L); /* # Shdrs & shdr string size */
  226. }
  227. lput(1L); /* text - type = PT_LOAD */
  228. lput(HEADR); /* file offset */
  229. lput(INITTEXT); /* vaddr */
  230. lput(INITTEXT); /* paddr */
  231. lput(textsize); /* file size */
  232. lput(textsize); /* memory size */
  233. lput(0x05L); /* protections = RX */
  234. lput(0); /* alignment */
  235. lput(1L); /* data - type = PT_LOAD */
  236. lput(HEADR+textsize); /* file offset */
  237. lput(INITDAT); /* vaddr */
  238. lput(INITDAT); /* paddr */
  239. lput(datsize); /* file size */
  240. lput(datsize+bsssize); /* memory size */
  241. lput(0x07L); /* protections = RWX */
  242. lput(0); /* alignment */
  243. lput(0L); /* data - type = PT_NULL */
  244. lput(HEADR+textsize+datsize); /* file offset */
  245. lput(0L); /* vaddr */
  246. lput(0L); /* paddr */
  247. lput(symsize); /* symbol table size */
  248. lput(lcsize); /* line number size */
  249. lput(0x04L); /* protections = R */
  250. lput(0x04L); /* alignment code?? */
  251. break;
  252. }
  253. cflush();
  254. }
  255. void
  256. strnput(char *s, int n)
  257. {
  258. for(; *s; s++){
  259. cput(*s);
  260. n--;
  261. }
  262. for(; n > 0; n--)
  263. cput(0);
  264. }
  265. void
  266. cput(int c)
  267. {
  268. cbp[0] = c;
  269. cbp++;
  270. cbc--;
  271. if(cbc <= 0)
  272. cflush();
  273. }
  274. void
  275. wput(long l)
  276. {
  277. cbp[0] = l>>8;
  278. cbp[1] = l;
  279. cbp += 2;
  280. cbc -= 2;
  281. if(cbc <= 0)
  282. cflush();
  283. }
  284. void
  285. lput(long l)
  286. {
  287. cbp[0] = l>>24;
  288. cbp[1] = l>>16;
  289. cbp[2] = l>>8;
  290. cbp[3] = l;
  291. cbp += 4;
  292. cbc -= 4;
  293. if(cbc <= 0)
  294. cflush();
  295. }
  296. void
  297. lputl(long l)
  298. {
  299. cbp[3] = l>>24;
  300. cbp[2] = l>>16;
  301. cbp[1] = l>>8;
  302. cbp[0] = l;
  303. cbp += 4;
  304. cbc -= 4;
  305. if(cbc <= 0)
  306. cflush();
  307. }
  308. void
  309. cflush(void)
  310. {
  311. int n;
  312. n = sizeof(buf.cbuf) - cbc;
  313. if(n)
  314. write(cout, buf.cbuf, n);
  315. cbp = buf.cbuf;
  316. cbc = sizeof(buf.cbuf);
  317. }
  318. void
  319. nopstat(char *f, Count *c)
  320. {
  321. if(c->outof)
  322. Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
  323. c->outof - c->count, c->outof,
  324. (double)(c->outof - c->count)/c->outof);
  325. }
  326. void
  327. asmsym(void)
  328. {
  329. Prog *p;
  330. Auto *a;
  331. Sym *s;
  332. int h;
  333. s = lookup("etext", 0);
  334. if(s->type == STEXT)
  335. putsymb(s->name, 'T', s->value, s->version);
  336. for(h=0; h<NHASH; h++)
  337. for(s=hash[h]; s!=S; s=s->link)
  338. switch(s->type) {
  339. case SCONST:
  340. putsymb(s->name, 'D', s->value, s->version);
  341. continue;
  342. case SDATA:
  343. putsymb(s->name, 'D', s->value+INITDAT, s->version);
  344. continue;
  345. case SBSS:
  346. putsymb(s->name, 'B', s->value+INITDAT, s->version);
  347. continue;
  348. case SSTRING:
  349. putsymb(s->name, 'T', s->value, s->version);
  350. continue;
  351. case SFILE:
  352. putsymb(s->name, 'f', s->value, s->version);
  353. continue;
  354. }
  355. for(p=textp; p!=P; p=p->cond) {
  356. s = p->from.sym;
  357. if(s->type != STEXT && s->type != SLEAF)
  358. continue;
  359. /* filenames first */
  360. for(a=p->to.autom; a; a=a->link)
  361. if(a->type == D_FILE)
  362. putsymb(a->asym->name, 'z', a->aoffset, 0);
  363. else
  364. if(a->type == D_FILE1)
  365. putsymb(a->asym->name, 'Z', a->aoffset, 0);
  366. if(s->type == STEXT)
  367. putsymb(s->name, 'T', s->value, s->version);
  368. else
  369. putsymb(s->name, 'L', s->value, s->version);
  370. /* frame, auto and param after */
  371. putsymb(".frame", 'm', p->to.offset+4, 0);
  372. for(a=p->to.autom; a; a=a->link)
  373. if(a->type == D_AUTO)
  374. putsymb(a->asym->name, 'a', -a->aoffset, 0);
  375. else
  376. if(a->type == D_PARAM)
  377. putsymb(a->asym->name, 'p', a->aoffset, 0);
  378. }
  379. if(debug['v'] || debug['n'])
  380. Bprint(&bso, "symsize = %lud\n", symsize);
  381. Bflush(&bso);
  382. }
  383. void
  384. putsymb(char *s, int t, long v, int ver)
  385. {
  386. int i, f;
  387. if(t == 'f')
  388. s++;
  389. lput(v);
  390. if(ver)
  391. t += 'a' - 'A';
  392. cput(t+0x80); /* 0x80 is variable length */
  393. if(t == 'Z' || t == 'z') {
  394. cput(s[0]);
  395. for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
  396. cput(s[i]);
  397. cput(s[i+1]);
  398. }
  399. cput(0);
  400. cput(0);
  401. i++;
  402. }
  403. else {
  404. for(i=0; s[i]; i++)
  405. cput(s[i]);
  406. cput(0);
  407. }
  408. symsize += 4 + 1 + i + 1;
  409. if(debug['n']) {
  410. if(t == 'z' || t == 'Z') {
  411. Bprint(&bso, "%c %.8lux ", t, v);
  412. for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
  413. f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
  414. Bprint(&bso, "/%x", f);
  415. }
  416. Bprint(&bso, "\n");
  417. return;
  418. }
  419. if(ver)
  420. Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
  421. else
  422. Bprint(&bso, "%c %.8lux %s\n", t, v, s);
  423. }
  424. }
  425. #define MINLC 4
  426. void
  427. asmlc(void)
  428. {
  429. long oldpc, oldlc;
  430. Prog *p;
  431. long v, s;
  432. oldpc = INITTEXT;
  433. oldlc = 0;
  434. for(p = firstp; p != P; p = p->link) {
  435. if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
  436. if(p->as == ATEXT)
  437. curtext = p;
  438. if(debug['V'])
  439. Bprint(&bso, "%6lux %P\n",
  440. p->pc, p);
  441. continue;
  442. }
  443. if(debug['V'])
  444. Bprint(&bso, "\t\t%6ld", lcsize);
  445. v = (p->pc - oldpc) / MINLC;
  446. while(v) {
  447. s = 127;
  448. if(v < 127)
  449. s = v;
  450. cput(s+128); /* 129-255 +pc */
  451. if(debug['V'])
  452. Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
  453. v -= s;
  454. lcsize++;
  455. }
  456. s = p->line - oldlc;
  457. oldlc = p->line;
  458. oldpc = p->pc + MINLC;
  459. if(s > 64 || s < -64) {
  460. cput(0); /* 0 vv +lc */
  461. cput(s>>24);
  462. cput(s>>16);
  463. cput(s>>8);
  464. cput(s);
  465. if(debug['V']) {
  466. if(s > 0)
  467. Bprint(&bso, " lc+%ld(%d,%ld)\n",
  468. s, 0, s);
  469. else
  470. Bprint(&bso, " lc%ld(%d,%ld)\n",
  471. s, 0, s);
  472. Bprint(&bso, "%6lux %P\n",
  473. p->pc, p);
  474. }
  475. lcsize += 5;
  476. continue;
  477. }
  478. if(s > 0) {
  479. cput(0+s); /* 1-64 +lc */
  480. if(debug['V']) {
  481. Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
  482. Bprint(&bso, "%6lux %P\n",
  483. p->pc, p);
  484. }
  485. } else {
  486. cput(64-s); /* 65-128 -lc */
  487. if(debug['V']) {
  488. Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
  489. Bprint(&bso, "%6lux %P\n",
  490. p->pc, p);
  491. }
  492. }
  493. lcsize++;
  494. }
  495. while(lcsize & 1) {
  496. s = 129;
  497. cput(s);
  498. lcsize++;
  499. }
  500. if(debug['v'] || debug['V'])
  501. Bprint(&bso, "lcsize = %ld\n", lcsize);
  502. Bflush(&bso);
  503. }
  504. void
  505. datblk(long s, long n, int str)
  506. {
  507. Sym *v;
  508. Prog *p;
  509. char *cast;
  510. long a, l, fl, j, d;
  511. int i, c;
  512. memset(buf.dbuf, 0, n+100);
  513. for(p = datap; p != P; p = p->link) {
  514. if(str != (p->from.sym->type == SSTRING))
  515. continue;
  516. curp = p;
  517. a = p->from.sym->value + p->from.offset;
  518. l = a - s;
  519. c = p->reg;
  520. i = 0;
  521. if(l < 0) {
  522. if(l+c <= 0)
  523. continue;
  524. while(l < 0) {
  525. l++;
  526. i++;
  527. }
  528. }
  529. if(l >= n)
  530. continue;
  531. if(p->as != AINIT && p->as != ADYNT) {
  532. for(j=l+(c-i)-1; j>=l; j--)
  533. if(buf.dbuf[j]) {
  534. print("%P\n", p);
  535. diag("multiple initialization");
  536. break;
  537. }
  538. }
  539. switch(p->to.type) {
  540. default:
  541. diag("unknown mode in initialization%P", p);
  542. break;
  543. case D_FCONST:
  544. switch(c) {
  545. default:
  546. case 4:
  547. fl = ieeedtof(p->to.ieee);
  548. cast = (char*)&fl;
  549. for(; i<c; i++) {
  550. buf.dbuf[l] = cast[fnuxi4[i]];
  551. l++;
  552. }
  553. break;
  554. case 8:
  555. cast = (char*)p->to.ieee;
  556. for(; i<c; i++) {
  557. buf.dbuf[l] = cast[fnuxi8[i]];
  558. l++;
  559. }
  560. break;
  561. }
  562. break;
  563. case D_SCONST:
  564. for(; i<c; i++) {
  565. buf.dbuf[l] = p->to.sval[i];
  566. l++;
  567. }
  568. break;
  569. case D_CONST:
  570. d = p->to.offset;
  571. v = p->to.sym;
  572. if(v) {
  573. switch(v->type) {
  574. case SUNDEF:
  575. ckoff(v, d);
  576. case STEXT:
  577. case SLEAF:
  578. case SSTRING:
  579. d += p->to.sym->value;
  580. break;
  581. case SDATA:
  582. case SBSS:
  583. d += p->to.sym->value + INITDAT;
  584. }
  585. if(dlm)
  586. dynreloc(v, a+INITDAT, 1);
  587. }
  588. cast = (char*)&d;
  589. switch(c) {
  590. default:
  591. diag("bad nuxi %d %d%P", c, i, curp);
  592. break;
  593. case 1:
  594. for(; i<c; i++) {
  595. buf.dbuf[l] = cast[inuxi1[i]];
  596. l++;
  597. }
  598. break;
  599. case 2:
  600. for(; i<c; i++) {
  601. buf.dbuf[l] = cast[inuxi2[i]];
  602. l++;
  603. }
  604. break;
  605. case 4:
  606. for(; i<c; i++) {
  607. buf.dbuf[l] = cast[inuxi4[i]];
  608. l++;
  609. }
  610. break;
  611. }
  612. break;
  613. }
  614. }
  615. write(cout, buf.dbuf, n);
  616. }
  617. void
  618. asmout(Prog *p, Optab *o)
  619. {
  620. long o1, o2, o3, o4, o5, o6, v;
  621. int r, rf, rt, rt2;
  622. Sym *s;
  623. PP = p;
  624. o1 = 0;
  625. o2 = 0;
  626. o3 = 0;
  627. o4 = 0;
  628. o5 = 0;
  629. o6 = 0;
  630. switch(o->type) {
  631. default:
  632. diag("unknown asm %d", o->type);
  633. prasm(p);
  634. break;
  635. case 0: /* pseudo ops */
  636. break;
  637. case 1: /* op R,[R],R */
  638. o1 = oprrr(p->as, p->scond);
  639. rf = p->from.reg;
  640. rt = p->to.reg;
  641. r = p->reg;
  642. if(p->to.type == D_NONE)
  643. rt = 0;
  644. if(p->as == AMOVW || p->as == AMVN)
  645. r = 0;
  646. else if(r == NREG)
  647. r = rt;
  648. o1 |= rf | (r<<16) | (rt<<12);
  649. break;
  650. case 2: /* movbu $I,[R],R */
  651. aclass(&p->from);
  652. o1 = oprrr(p->as, p->scond);
  653. o1 |= immrot(instoffset);
  654. rt = p->to.reg;
  655. r = p->reg;
  656. if(p->to.type == D_NONE)
  657. rt = 0;
  658. if(p->as == AMOVW || p->as == AMVN)
  659. r = 0;
  660. else if(r == NREG)
  661. r = rt;
  662. o1 |= (r<<16) | (rt<<12);
  663. break;
  664. case 3: /* add R<<[IR],[R],R */
  665. mov:
  666. aclass(&p->from);
  667. o1 = oprrr(p->as, p->scond);
  668. o1 |= p->from.offset;
  669. rt = p->to.reg;
  670. r = p->reg;
  671. if(p->to.type == D_NONE)
  672. rt = 0;
  673. if(p->as == AMOVW || p->as == AMVN)
  674. r = 0;
  675. else if(r == NREG)
  676. r = rt;
  677. o1 |= (r<<16) | (rt<<12);
  678. break;
  679. case 4: /* add $I,[R],R */
  680. aclass(&p->from);
  681. o1 = oprrr(AADD, p->scond);
  682. o1 |= immrot(instoffset);
  683. r = p->from.reg;
  684. if(r == NREG)
  685. r = o->param;
  686. o1 |= r << 16;
  687. o1 |= p->to.reg << 12;
  688. break;
  689. case 5: /* bra s */
  690. v = -8;
  691. if(p->cond == UP) {
  692. s = p->to.sym;
  693. if(s->type != SUNDEF)
  694. diag("bad branch sym type");
  695. v = (ulong)s->value >> (Roffset-2);
  696. dynreloc(s, p->pc, 0);
  697. }
  698. else if(p->cond != P)
  699. v = (p->cond->pc - pc) - 8;
  700. o1 = opbra(p->as, p->scond);
  701. o1 |= (v >> 2) & 0xffffff;
  702. break;
  703. case 6: /* b ,O(R) -> add $O,R,PC */
  704. aclass(&p->to);
  705. o1 = oprrr(AADD, p->scond);
  706. o1 |= immrot(instoffset);
  707. o1 |= p->to.reg << 16;
  708. o1 |= REGPC << 12;
  709. break;
  710. case 7: /* bl ,O(R) -> mov PC,link; add $O,R,PC */
  711. aclass(&p->to);
  712. o1 = oprrr(AADD, p->scond);
  713. o1 |= immrot(0);
  714. o1 |= REGPC << 16;
  715. o1 |= REGLINK << 12;
  716. o2 = oprrr(AADD, p->scond);
  717. o2 |= immrot(instoffset);
  718. o2 |= p->to.reg << 16;
  719. o2 |= REGPC << 12;
  720. break;
  721. case 8: /* sll $c,[R],R -> mov (R<<$c),R */
  722. aclass(&p->from);
  723. o1 = oprrr(p->as, p->scond);
  724. r = p->reg;
  725. if(r == NREG)
  726. r = p->to.reg;
  727. o1 |= r;
  728. o1 |= (instoffset&31) << 7;
  729. o1 |= p->to.reg << 12;
  730. break;
  731. case 9: /* sll R,[R],R -> mov (R<<R),R */
  732. o1 = oprrr(p->as, p->scond);
  733. r = p->reg;
  734. if(r == NREG)
  735. r = p->to.reg;
  736. o1 |= r;
  737. o1 |= (p->from.reg << 8) | (1<<4);
  738. o1 |= p->to.reg << 12;
  739. break;
  740. case 10: /* swi [$con] */
  741. o1 = oprrr(p->as, p->scond);
  742. if(p->to.type != D_NONE) {
  743. aclass(&p->to);
  744. o1 |= instoffset & 0xffffff;
  745. }
  746. break;
  747. case 11: /* word */
  748. switch(aclass(&p->to)) {
  749. case C_LCON:
  750. if(!dlm)
  751. break;
  752. if(p->to.name != D_EXTERN && p->to.name != D_STATIC)
  753. break;
  754. case C_ADDR:
  755. if(p->to.sym->type == SUNDEF)
  756. ckoff(p->to.sym, p->to.offset);
  757. dynreloc(p->to.sym, p->pc, 1);
  758. }
  759. o1 = instoffset;
  760. break;
  761. case 12: /* movw $lcon, reg */
  762. o1 = omvl(p, &p->from, p->to.reg);
  763. break;
  764. case 13: /* op $lcon, [R], R */
  765. o1 = omvl(p, &p->from, REGTMP);
  766. if(!o1)
  767. break;
  768. o2 = oprrr(p->as, p->scond);
  769. o2 |= REGTMP;
  770. r = p->reg;
  771. if(p->as == AMOVW || p->as == AMVN)
  772. r = 0;
  773. else if(r == NREG)
  774. r = p->to.reg;
  775. o2 |= r << 16;
  776. if(p->to.type != D_NONE)
  777. o2 |= p->to.reg << 12;
  778. break;
  779. case 14: /* movb/movbu/movh/movhu R,R */
  780. o1 = oprrr(ASLL, p->scond);
  781. if(p->as == AMOVBU || p->as == AMOVHU)
  782. o2 = oprrr(ASRL, p->scond);
  783. else
  784. o2 = oprrr(ASRA, p->scond);
  785. r = p->to.reg;
  786. o1 |= (p->from.reg)|(r<<12);
  787. o2 |= (r)|(r<<12);
  788. if(p->as == AMOVB || p->as == AMOVBU) {
  789. o1 |= (24<<7);
  790. o2 |= (24<<7);
  791. } else {
  792. o1 |= (16<<7);
  793. o2 |= (16<<7);
  794. }
  795. break;
  796. case 15: /* mul r,[r,]r */
  797. o1 = oprrr(p->as, p->scond);
  798. rf = p->from.reg;
  799. rt = p->to.reg;
  800. r = p->reg;
  801. if(r == NREG)
  802. r = rt;
  803. if(rt == r) {
  804. r = rf;
  805. rf = rt;
  806. }
  807. if(0)
  808. if(rt == r || rf == REGPC || r == REGPC || rt == REGPC) {
  809. diag("bad registers in MUL");
  810. prasm(p);
  811. }
  812. o1 |= (rf<<8) | r | (rt<<16);
  813. break;
  814. case 16: /* div r,[r,]r */
  815. o1 = 0xf << 28;
  816. o2 = 0;
  817. break;
  818. case 17:
  819. o1 = oprrr(p->as, p->scond);
  820. rf = p->from.reg;
  821. rt = p->to.reg;
  822. rt2 = p->to.offset;
  823. r = p->reg;
  824. o1 |= (rf<<8) | r | (rt<<16) | (rt2<<12);
  825. break;
  826. case 20: /* mov/movb/movbu R,O(R) */
  827. aclass(&p->to);
  828. r = p->to.reg;
  829. if(r == NREG)
  830. r = o->param;
  831. o1 = osr(p->as, p->from.reg, instoffset, r, p->scond);
  832. break;
  833. case 21: /* mov/movbu O(R),R -> lr */
  834. aclass(&p->from);
  835. r = p->from.reg;
  836. if(r == NREG)
  837. r = o->param;
  838. o1 = olr(instoffset, r, p->to.reg, p->scond);
  839. if(p->as != AMOVW)
  840. o1 |= 1<<22;
  841. break;
  842. case 22: /* movb/movh/movhu O(R),R -> lr,shl,shr */
  843. aclass(&p->from);
  844. r = p->from.reg;
  845. if(r == NREG)
  846. r = o->param;
  847. o1 = olr(instoffset, r, p->to.reg, p->scond);
  848. o2 = oprrr(ASLL, p->scond);
  849. o3 = oprrr(ASRA, p->scond);
  850. r = p->to.reg;
  851. if(p->as == AMOVB) {
  852. o2 |= (24<<7)|(r)|(r<<12);
  853. o3 |= (24<<7)|(r)|(r<<12);
  854. } else {
  855. o2 |= (16<<7)|(r)|(r<<12);
  856. if(p->as == AMOVHU)
  857. o3 = oprrr(ASRL, p->scond);
  858. o3 |= (16<<7)|(r)|(r<<12);
  859. }
  860. break;
  861. case 23: /* movh/movhu R,O(R) -> sb,sb */
  862. aclass(&p->to);
  863. r = p->to.reg;
  864. if(r == NREG)
  865. r = o->param;
  866. o1 = osr(AMOVH, p->from.reg, instoffset, r, p->scond);
  867. o2 = oprrr(ASRL, p->scond);
  868. o2 |= (8<<7)|(p->from.reg)|(REGTMP<<12);
  869. o3 = osr(AMOVH, REGTMP, instoffset+1, r, p->scond);
  870. break;
  871. case 30: /* mov/movb/movbu R,L(R) */
  872. o1 = omvl(p, &p->to, REGTMP);
  873. if(!o1)
  874. break;
  875. r = p->to.reg;
  876. if(r == NREG)
  877. r = o->param;
  878. o2 = osrr(p->from.reg, REGTMP,r, p->scond);
  879. if(p->as != AMOVW)
  880. o2 |= 1<<22;
  881. break;
  882. case 31: /* mov/movbu L(R),R -> lr[b] */
  883. case 32: /* movh/movb L(R),R -> lr[b] */
  884. o1 = omvl(p, &p->from, REGTMP);
  885. if(!o1)
  886. break;
  887. r = p->from.reg;
  888. if(r == NREG)
  889. r = o->param;
  890. o2 = olrr(REGTMP,r, p->to.reg, p->scond);
  891. if(p->as == AMOVBU || p->as == AMOVB)
  892. o2 |= 1<<22;
  893. if(o->type == 31)
  894. break;
  895. o3 = oprrr(ASLL, p->scond);
  896. if(p->as == AMOVBU || p->as == AMOVHU)
  897. o4 = oprrr(ASRL, p->scond);
  898. else
  899. o4 = oprrr(ASRA, p->scond);
  900. r = p->to.reg;
  901. o3 |= (r)|(r<<12);
  902. o4 |= (r)|(r<<12);
  903. if(p->as == AMOVB || p->as == AMOVBU) {
  904. o3 |= (24<<7);
  905. o4 |= (24<<7);
  906. } else {
  907. o3 |= (16<<7);
  908. o4 |= (16<<7);
  909. }
  910. break;
  911. case 33: /* movh/movhu R,L(R) -> sb, sb */
  912. o1 = omvl(p, &p->to, REGTMP);
  913. if(!o1)
  914. break;
  915. r = p->to.reg;
  916. if(r == NREG)
  917. r = o->param;
  918. o2 = osrr(p->from.reg, REGTMP, r, p->scond);
  919. o2 |= (1<<22) ;
  920. o3 = oprrr(ASRL, p->scond);
  921. o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12);
  922. o3 |= (1<<6); /* ROR 8 */
  923. o4 = oprrr(AADD, p->scond);
  924. o4 |= (REGTMP << 12) | (REGTMP << 16);
  925. o4 |= immrot(1);
  926. o5 = osrr(p->from.reg, REGTMP,r,p->scond);
  927. o5 |= (1<<22);
  928. o6 = oprrr(ASRL, p->scond);
  929. o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12);
  930. o6 |= (1<<6); /* ROL 8 */
  931. break;
  932. case 34: /* mov $lacon,R */
  933. o1 = omvl(p, &p->from, REGTMP);
  934. if(!o1)
  935. break;
  936. o2 = oprrr(AADD, p->scond);
  937. o2 |= REGTMP;
  938. r = p->from.reg;
  939. if(r == NREG)
  940. r = o->param;
  941. o2 |= r << 16;
  942. if(p->to.type != D_NONE)
  943. o2 |= p->to.reg << 12;
  944. break;
  945. case 35: /* mov PSR,R */
  946. o1 = (2<<23) | (0xf<<16) | (0<<0);
  947. o1 |= (p->scond & C_SCOND) << 28;
  948. o1 |= (p->from.reg & 1) << 22;
  949. o1 |= p->to.reg << 12;
  950. break;
  951. case 36: /* mov R,PSR */
  952. o1 = (2<<23) | (0x29f<<12) | (0<<4);
  953. if(p->scond & C_FBIT)
  954. o1 ^= 0x010 << 12;
  955. o1 |= (p->scond & C_SCOND) << 28;
  956. o1 |= (p->to.reg & 1) << 22;
  957. o1 |= p->from.reg << 0;
  958. break;
  959. case 37: /* mov $con,PSR */
  960. aclass(&p->from);
  961. o1 = (2<<23) | (0x29f<<12) | (0<<4);
  962. if(p->scond & C_FBIT)
  963. o1 ^= 0x010 << 12;
  964. o1 |= (p->scond & C_SCOND) << 28;
  965. o1 |= immrot(instoffset);
  966. o1 |= (p->to.reg & 1) << 22;
  967. o1 |= p->from.reg << 0;
  968. break;
  969. case 38: /* movm $con,oreg -> stm */
  970. o1 = (0x4 << 25);
  971. o1 |= p->from.offset & 0xffff;
  972. o1 |= p->to.reg << 16;
  973. aclass(&p->to);
  974. goto movm;
  975. case 39: /* movm oreg,$con -> ldm */
  976. o1 = (0x4 << 25) | (1 << 20);
  977. o1 |= p->to.offset & 0xffff;
  978. o1 |= p->from.reg << 16;
  979. aclass(&p->from);
  980. movm:
  981. if(instoffset != 0)
  982. diag("offset must be zero in MOVM");
  983. o1 |= (p->scond & C_SCOND) << 28;
  984. if(p->scond & C_PBIT)
  985. o1 |= 1 << 24;
  986. if(p->scond & C_UBIT)
  987. o1 |= 1 << 23;
  988. if(p->scond & C_SBIT)
  989. o1 |= 1 << 22;
  990. if(p->scond & C_WBIT)
  991. o1 |= 1 << 21;
  992. break;
  993. case 40: /* swp oreg,reg,reg */
  994. aclass(&p->from);
  995. if(instoffset != 0)
  996. diag("offset must be zero in SWP");
  997. o1 = (0x2<<23) | (0x9<<4);
  998. if(p->as != ASWPW)
  999. o1 |= 1 << 22;
  1000. o1 |= p->from.reg << 16;
  1001. o1 |= p->reg << 0;
  1002. o1 |= p->to.reg << 12;
  1003. o1 |= (p->scond & C_SCOND) << 28;
  1004. break;
  1005. case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
  1006. o1 = 0xe8fd8000;
  1007. break;
  1008. case 50: /* floating point store */
  1009. v = regoff(&p->to);
  1010. r = p->to.reg;
  1011. if(r == NREG)
  1012. r = o->param;
  1013. o1 = ofsr(p->as, p->from.reg, v, r, p->scond, p);
  1014. break;
  1015. case 51: /* floating point load */
  1016. v = regoff(&p->from);
  1017. r = p->from.reg;
  1018. if(r == NREG)
  1019. r = o->param;
  1020. o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<20);
  1021. break;
  1022. case 52: /* floating point store, long offset UGLY */
  1023. o1 = omvl(p, &p->to, REGTMP);
  1024. if(!o1)
  1025. break;
  1026. r = p->to.reg;
  1027. if(r == NREG)
  1028. r = o->param;
  1029. o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
  1030. o3 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
  1031. break;
  1032. case 53: /* floating point load, long offset UGLY */
  1033. o1 = omvl(p, &p->from, REGTMP);
  1034. if(!o1)
  1035. break;
  1036. r = p->from.reg;
  1037. if(r == NREG)
  1038. r = o->param;
  1039. o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
  1040. o3 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
  1041. break;
  1042. case 54: /* floating point arith */
  1043. o1 = oprrr(p->as, p->scond);
  1044. if(p->from.type == D_FCONST) {
  1045. rf = chipfloat(p->from.ieee);
  1046. if(rf < 0){
  1047. diag("invalid floating-point immediate\n%P", p);
  1048. rf = 0;
  1049. }
  1050. rf |= (1<<3);
  1051. } else
  1052. rf = p->from.reg;
  1053. rt = p->to.reg;
  1054. r = p->reg;
  1055. if(p->to.type == D_NONE)
  1056. rt = 0; /* CMP[FD] */
  1057. else if(o1 & (1<<15))
  1058. r = 0; /* monadic */
  1059. else if(r == NREG)
  1060. r = rt;
  1061. o1 |= rf | (r<<16) | (rt<<12);
  1062. break;
  1063. case 55: /* floating point fix and float */
  1064. o1 = oprrr(p->as, p->scond);
  1065. rf = p->from.reg;
  1066. rt = p->to.reg;
  1067. if(p->to.type == D_NONE){
  1068. rt = 0;
  1069. diag("to.type==D_NONE (asm/fp)");
  1070. }
  1071. if(p->from.type == D_REG)
  1072. o1 |= (rf<<12) | (rt<<16);
  1073. else
  1074. o1 |= rf | (rt<<12);
  1075. break;
  1076. /* old arm 7500 fp using coproc 1 (1<<8) */
  1077. case 56: /* move to FP[CS]R */
  1078. o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
  1079. o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12);
  1080. break;
  1081. case 57: /* move from FP[CS]R */
  1082. o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
  1083. o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20);
  1084. break;
  1085. case 58: /* movbu R,R */
  1086. o1 = oprrr(AAND, p->scond);
  1087. o1 |= immrot(0xff);
  1088. rt = p->to.reg;
  1089. r = p->from.reg;
  1090. if(p->to.type == D_NONE)
  1091. rt = 0;
  1092. if(r == NREG)
  1093. r = rt;
  1094. o1 |= (r<<16) | (rt<<12);
  1095. break;
  1096. case 59: /* movw/bu R<<I(R),R -> ldr indexed */
  1097. if(p->from.reg == NREG) {
  1098. if(p->as != AMOVW)
  1099. diag("byte MOV from shifter operand");
  1100. goto mov;
  1101. }
  1102. if(p->from.offset&(1<<4))
  1103. diag("bad shift in LDR");
  1104. o1 = olrr(p->from.offset, p->from.reg, p->to.reg, p->scond);
  1105. if(p->as == AMOVBU)
  1106. o1 |= 1<<22;
  1107. break;
  1108. case 60: /* movb R(R),R -> ldrsb indexed */
  1109. if(p->from.reg == NREG) {
  1110. diag("byte MOV from shifter operand");
  1111. goto mov;
  1112. }
  1113. if(p->from.offset&(~0xf))
  1114. diag("bad shift in LDRSB");
  1115. o1 = olhrr(p->from.offset, p->from.reg, p->to.reg, p->scond);
  1116. o1 ^= (1<<5)|(1<<6);
  1117. break;
  1118. case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
  1119. if(p->to.reg == NREG)
  1120. diag("MOV to shifter operand");
  1121. o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond);
  1122. if(p->as == AMOVB || p->as == AMOVBU)
  1123. o1 |= 1<<22;
  1124. break;
  1125. case 62: /* case R -> movw R<<2(PC),PC */
  1126. o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
  1127. o1 |= 2<<7;
  1128. break;
  1129. case 63: /* bcase */
  1130. if(p->cond != P) {
  1131. o1 = p->cond->pc;
  1132. if(dlm)
  1133. dynreloc(S, p->pc, 1);
  1134. }
  1135. break;
  1136. /* reloc ops */
  1137. case 64: /* mov/movb/movbu R,addr */
  1138. o1 = omvl(p, &p->to, REGTMP);
  1139. if(!o1)
  1140. break;
  1141. o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
  1142. break;
  1143. case 65: /* mov/movbu addr,R */
  1144. case 66: /* movh/movhu/movb addr,R */
  1145. o1 = omvl(p, &p->from, REGTMP);
  1146. if(!o1)
  1147. break;
  1148. o2 = olr(0, REGTMP, p->to.reg, p->scond);
  1149. if(p->as == AMOVBU || p->as == AMOVB)
  1150. o2 |= 1<<22;
  1151. if(o->type == 65)
  1152. break;
  1153. o3 = oprrr(ASLL, p->scond);
  1154. if(p->as == AMOVBU || p->as == AMOVHU)
  1155. o4 = oprrr(ASRL, p->scond);
  1156. else
  1157. o4 = oprrr(ASRA, p->scond);
  1158. r = p->to.reg;
  1159. o3 |= (r)|(r<<12);
  1160. o4 |= (r)|(r<<12);
  1161. if(p->as == AMOVB || p->as == AMOVBU) {
  1162. o3 |= (24<<7);
  1163. o4 |= (24<<7);
  1164. } else {
  1165. o3 |= (16<<7);
  1166. o4 |= (16<<7);
  1167. }
  1168. break;
  1169. case 67: /* movh/movhu R,addr -> sb, sb */
  1170. o1 = omvl(p, &p->to, REGTMP);
  1171. if(!o1)
  1172. break;
  1173. o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
  1174. o3 = oprrr(ASRL, p->scond);
  1175. o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12);
  1176. o3 |= (1<<6); /* ROR 8 */
  1177. o4 = oprrr(AADD, p->scond);
  1178. o4 |= (REGTMP << 12) | (REGTMP << 16);
  1179. o4 |= immrot(1);
  1180. o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
  1181. o6 = oprrr(ASRL, p->scond);
  1182. o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12);
  1183. o6 |= (1<<6); /* ROL 8 */
  1184. break;
  1185. case 68: /* floating point store -> ADDR */
  1186. o1 = omvl(p, &p->to, REGTMP);
  1187. if(!o1)
  1188. break;
  1189. o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
  1190. break;
  1191. case 69: /* floating point load <- ADDR */
  1192. o1 = omvl(p, &p->from, REGTMP);
  1193. if(!o1)
  1194. break;
  1195. o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
  1196. break;
  1197. /* ArmV4 ops: */
  1198. case 70: /* movh/movhu R,O(R) -> strh */
  1199. aclass(&p->to);
  1200. r = p->to.reg;
  1201. if(r == NREG)
  1202. r = o->param;
  1203. o1 = oshr(p->from.reg, instoffset, r, p->scond);
  1204. break;
  1205. case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
  1206. aclass(&p->from);
  1207. r = p->from.reg;
  1208. if(r == NREG)
  1209. r = o->param;
  1210. o1 = olhr(instoffset, r, p->to.reg, p->scond);
  1211. if(p->as == AMOVB)
  1212. o1 ^= (1<<5)|(1<<6);
  1213. else if(p->as == AMOVH)
  1214. o1 ^= (1<<6);
  1215. break;
  1216. case 72: /* movh/movhu R,L(R) -> strh */
  1217. o1 = omvl(p, &p->to, REGTMP);
  1218. if(!o1)
  1219. break;
  1220. r = p->to.reg;
  1221. if(r == NREG)
  1222. r = o->param;
  1223. o2 = oshrr(p->from.reg, REGTMP,r, p->scond);
  1224. break;
  1225. case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
  1226. o1 = omvl(p, &p->from, REGTMP);
  1227. if(!o1)
  1228. break;
  1229. r = p->from.reg;
  1230. if(r == NREG)
  1231. r = o->param;
  1232. o2 = olhrr(REGTMP, r, p->to.reg, p->scond);
  1233. if(p->as == AMOVB)
  1234. o2 ^= (1<<5)|(1<<6);
  1235. else if(p->as == AMOVH)
  1236. o2 ^= (1<<6);
  1237. break;
  1238. /* VFP ops: */
  1239. case 74: /* vfp floating point arith */
  1240. o1 = opvfprrr(p->as, p->scond);
  1241. rf = p->from.reg;
  1242. if(p->from.type == D_FCONST) {
  1243. diag("invalid floating-point immediate\n%P", p);
  1244. rf = 0;
  1245. }
  1246. rt = p->to.reg;
  1247. r = p->reg;
  1248. if(r == NREG)
  1249. r = rt;
  1250. o1 |= rt<<12;
  1251. if(((o1>>20)&0xf) == 0xb)
  1252. o1 |= rf<<0;
  1253. else
  1254. o1 |= r<<16 | rf<<0;
  1255. break;
  1256. case 75: /* vfp floating point compare */
  1257. o1 = opvfprrr(p->as, p->scond);
  1258. rf = p->from.reg;
  1259. if(p->from.type == D_FCONST) {
  1260. if(p->from.ieee->h != 0 || p->from.ieee->l != 0)
  1261. diag("invalid floating-point immediate\n%P", p);
  1262. o1 |= 1<<16;
  1263. rf = 0;
  1264. }
  1265. rt = p->reg;
  1266. o1 |= rt<<12 | rf<<0;
  1267. o2 = 0x0ef1fa10; /* MRS APSR_nzcv, FPSCR */
  1268. o2 |= (p->scond & C_SCOND) << 28;
  1269. break;
  1270. case 76: /* vfp floating point fix and float */
  1271. o1 = opvfprrr(p->as, p->scond);
  1272. rf = p->from.reg;
  1273. rt = p->to.reg;
  1274. if(p->from.type == D_REG) {
  1275. o2 = o1 | rt<<12 | rt<<0;
  1276. o1 = 0x0e000a10; /* VMOV F,R */
  1277. o1 |= (p->scond & C_SCOND) << 28 | rt<<16 | rf<<12;
  1278. } else {
  1279. o1 |= FREGTMP<<12 | rf<<0;
  1280. o2 = 0x0e100a10; /* VMOV R,F */
  1281. o2 |= (p->scond & C_SCOND) << 28 | FREGTMP<<16 | rt<<12;
  1282. }
  1283. break;
  1284. }
  1285. if(debug['a'] > 1)
  1286. Bprint(&bso, "%2d ", o->type);
  1287. v = p->pc;
  1288. switch(o->size) {
  1289. default:
  1290. if(debug['a'])
  1291. Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
  1292. break;
  1293. case 4:
  1294. if(debug['a'])
  1295. Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
  1296. lputl(o1);
  1297. break;
  1298. case 8:
  1299. if(debug['a'])
  1300. Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
  1301. lputl(o1);
  1302. lputl(o2);
  1303. break;
  1304. case 12:
  1305. if(debug['a'])
  1306. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
  1307. lputl(o1);
  1308. lputl(o2);
  1309. lputl(o3);
  1310. break;
  1311. case 16:
  1312. if(debug['a'])
  1313. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
  1314. v, o1, o2, o3, o4, p);
  1315. lputl(o1);
  1316. lputl(o2);
  1317. lputl(o3);
  1318. lputl(o4);
  1319. break;
  1320. case 20:
  1321. if(debug['a'])
  1322. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
  1323. v, o1, o2, o3, o4, o5, p);
  1324. lputl(o1);
  1325. lputl(o2);
  1326. lputl(o3);
  1327. lputl(o4);
  1328. lputl(o5);
  1329. break;
  1330. case 24:
  1331. if(debug['a'])
  1332. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
  1333. v, o1, o2, o3, o4, o5, o6, p);
  1334. lputl(o1);
  1335. lputl(o2);
  1336. lputl(o3);
  1337. lputl(o4);
  1338. lputl(o5);
  1339. lputl(o6);
  1340. break;
  1341. }
  1342. }
  1343. long
  1344. oprrr(int a, int sc)
  1345. {
  1346. long o;
  1347. o = (sc & C_SCOND) << 28;
  1348. if(sc & C_SBIT)
  1349. o |= 1 << 20;
  1350. if(sc & (C_PBIT|C_WBIT))
  1351. diag(".P/.W on dp instruction");
  1352. switch(a) {
  1353. case AMULU:
  1354. case AMUL: return o | (0x0<<21) | (0x9<<4);
  1355. case AMULA: return o | (0x1<<21) | (0x9<<4);
  1356. case AMULLU: return o | (0x4<<21) | (0x9<<4);
  1357. case AMULL: return o | (0x6<<21) | (0x9<<4);
  1358. case AMULALU: return o | (0x5<<21) | (0x9<<4);
  1359. case AMULAL: return o | (0x7<<21) | (0x9<<4);
  1360. case AAND: return o | (0x0<<21);
  1361. case AEOR: return o | (0x1<<21);
  1362. case ASUB: return o | (0x2<<21);
  1363. case ARSB: return o | (0x3<<21);
  1364. case AADD: return o | (0x4<<21);
  1365. case AADC: return o | (0x5<<21);
  1366. case ASBC: return o | (0x6<<21);
  1367. case ARSC: return o | (0x7<<21);
  1368. case ATST: return o | (0x8<<21) | (1<<20);
  1369. case ATEQ: return o | (0x9<<21) | (1<<20);
  1370. case ACMP: return o | (0xa<<21) | (1<<20);
  1371. case ACMN: return o | (0xb<<21) | (1<<20);
  1372. case AORR: return o | (0xc<<21);
  1373. case AMOVW: return o | (0xd<<21);
  1374. case ABIC: return o | (0xe<<21);
  1375. case AMVN: return o | (0xf<<21);
  1376. case ASLL: return o | (0xd<<21) | (0<<5);
  1377. case ASRL: return o | (0xd<<21) | (1<<5);
  1378. case ASRA: return o | (0xd<<21) | (2<<5);
  1379. case ASWI: return o | (0xf<<24);
  1380. /* old arm 7500 fp using coproc 1 (1<<8) */
  1381. case AADDD: return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7);
  1382. case AADDF: return o | (0xe<<24) | (0x0<<20) | (1<<8);
  1383. case AMULD: return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7);
  1384. case AMULF: return o | (0xe<<24) | (0x1<<20) | (1<<8);
  1385. case ASUBD: return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7);
  1386. case ASUBF: return o | (0xe<<24) | (0x2<<20) | (1<<8);
  1387. case ADIVD: return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7);
  1388. case ADIVF: return o | (0xe<<24) | (0x4<<20) | (1<<8);
  1389. case ACMPD:
  1390. case ACMPF: return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4); /* arguably, ACMPF should expand to RNDF, CMPD */
  1391. case AMOVF:
  1392. case AMOVDF: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8);
  1393. case AMOVD:
  1394. case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7);
  1395. case AMOVWF: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4);
  1396. case AMOVWD: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7);
  1397. case AMOVFW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4);
  1398. case AMOVDW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7);
  1399. }
  1400. diag("bad rrr %d", a);
  1401. prasm(curp);
  1402. return 0;
  1403. }
  1404. long
  1405. opvfprrr(int a, int sc)
  1406. {
  1407. long o;
  1408. o = (sc & C_SCOND) << 28;
  1409. if(sc & (C_SBIT|C_PBIT|C_WBIT))
  1410. diag(".S/.P/.W on vfp instruction");
  1411. o |= 0xe<<24;
  1412. switch(a) {
  1413. case AMOVWD: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x8<<16 | 1<<7;
  1414. case AMOVWF: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x8<<16 | 1<<7;
  1415. case AMOVDW: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0xD<<16 | 1<<7;
  1416. case AMOVFW: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0xD<<16 | 1<<7;
  1417. case AMOVFD: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x7<<16 | 1<<7;
  1418. case AMOVDF: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x7<<16 | 1<<7;
  1419. case AMOVF: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x0<<16 | 0<<7;
  1420. case AMOVD: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x0<<16 | 0<<7;
  1421. case ACMPF: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x4<<16 | 0<<7;
  1422. case ACMPD: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x4<<16 | 0<<7;
  1423. case AADDF: return o | 0xa<<8 | 0x3<<20;
  1424. case AADDD: return o | 0xb<<8 | 0x3<<20;
  1425. case ASUBF: return o | 0xa<<8 | 0x3<<20 | 1<<6;
  1426. case ASUBD: return o | 0xb<<8 | 0x3<<20 | 1<<6;
  1427. case AMULF: return o | 0xa<<8 | 0x2<<20;
  1428. case AMULD: return o | 0xb<<8 | 0x2<<20;
  1429. case ADIVF: return o | 0xa<<8 | 0x8<<20;
  1430. case ADIVD: return o | 0xb<<8 | 0x8<<20;
  1431. }
  1432. diag("bad vfp rrr %d", a);
  1433. prasm(curp);
  1434. return 0;
  1435. }
  1436. long
  1437. opbra(int a, int sc)
  1438. {
  1439. if(sc & (C_SBIT|C_PBIT|C_WBIT))
  1440. diag(".S/.P/.W on bra instruction");
  1441. sc &= C_SCOND;
  1442. if(a == ABL)
  1443. return (sc<<28)|(0x5<<25)|(0x1<<24);
  1444. if(sc != 0xe)
  1445. diag(".COND on bcond instruction");
  1446. switch(a) {
  1447. case ABEQ: return (0x0<<28)|(0x5<<25);
  1448. case ABNE: return (0x1<<28)|(0x5<<25);
  1449. case ABCS: return (0x2<<28)|(0x5<<25);
  1450. case ABHS: return (0x2<<28)|(0x5<<25);
  1451. case ABCC: return (0x3<<28)|(0x5<<25);
  1452. case ABLO: return (0x3<<28)|(0x5<<25);
  1453. case ABMI: return (0x4<<28)|(0x5<<25);
  1454. case ABPL: return (0x5<<28)|(0x5<<25);
  1455. case ABVS: return (0x6<<28)|(0x5<<25);
  1456. case ABVC: return (0x7<<28)|(0x5<<25);
  1457. case ABHI: return (0x8<<28)|(0x5<<25);
  1458. case ABLS: return (0x9<<28)|(0x5<<25);
  1459. case ABGE: return (0xa<<28)|(0x5<<25);
  1460. case ABLT: return (0xb<<28)|(0x5<<25);
  1461. case ABGT: return (0xc<<28)|(0x5<<25);
  1462. case ABLE: return (0xd<<28)|(0x5<<25);
  1463. case AB: return (0xe<<28)|(0x5<<25);
  1464. }
  1465. diag("bad bra %A", a);
  1466. prasm(curp);
  1467. return 0;
  1468. }
  1469. long
  1470. olr(long v, int b, int r, int sc)
  1471. {
  1472. long o;
  1473. if(sc & C_SBIT)
  1474. diag(".S on LDR/STR instruction");
  1475. o = (sc & C_SCOND) << 28;
  1476. if(!(sc & C_PBIT))
  1477. o |= 1 << 24;
  1478. if(!(sc & C_UBIT))
  1479. o |= 1 << 23;
  1480. if(sc & C_WBIT)
  1481. o |= 1 << 21;
  1482. o |= (0x1<<26) | (1<<20);
  1483. if(v < 0) {
  1484. v = -v;
  1485. o ^= 1 << 23;
  1486. }
  1487. if(v >= (1<<12))
  1488. diag("literal span too large: %ld (R%d)\n%P", v, b, PP);
  1489. o |= v;
  1490. o |= b << 16;
  1491. o |= r << 12;
  1492. return o;
  1493. }
  1494. long
  1495. olhr(long v, int b, int r, int sc)
  1496. {
  1497. long o;
  1498. if(sc & C_SBIT)
  1499. diag(".S on LDRH/STRH instruction");
  1500. o = (sc & C_SCOND) << 28;
  1501. if(!(sc & C_PBIT))
  1502. o |= 1 << 24;
  1503. if(sc & C_WBIT)
  1504. o |= 1 << 21;
  1505. o |= (1<<23) | (1<<20)|(0xb<<4);
  1506. if(v < 0) {
  1507. v = -v;
  1508. o ^= 1 << 23;
  1509. }
  1510. if(v >= (1<<8))
  1511. diag("literal span too large: %ld (R%d)\n%P", v, b, PP);
  1512. o |= (v&0xf)|((v>>4)<<8)|(1<<22);
  1513. o |= b << 16;
  1514. o |= r << 12;
  1515. return o;
  1516. }
  1517. long
  1518. osr(int a, int r, long v, int b, int sc)
  1519. {
  1520. long o;
  1521. o = olr(v, b, r, sc) ^ (1<<20);
  1522. if(a != AMOVW)
  1523. o |= 1<<22;
  1524. return o;
  1525. }
  1526. long
  1527. oshr(int r, long v, int b, int sc)
  1528. {
  1529. long o;
  1530. o = olhr(v, b, r, sc) ^ (1<<20);
  1531. return o;
  1532. }
  1533. long
  1534. osrr(int r, int i, int b, int sc)
  1535. {
  1536. return olr(i, b, r, sc) ^ ((1<<25) | (1<<20));
  1537. }
  1538. long
  1539. oshrr(int r, int i, int b, int sc)
  1540. {
  1541. return olhr(i, b, r, sc) ^ ((1<<22) | (1<<20));
  1542. }
  1543. long
  1544. olrr(int i, int b, int r, int sc)
  1545. {
  1546. return olr(i, b, r, sc) ^ (1<<25);
  1547. }
  1548. long
  1549. olhrr(int i, int b, int r, int sc)
  1550. {
  1551. return olhr(i, b, r, sc) ^ (1<<22);
  1552. }
  1553. long
  1554. ovfpmem(int a, int r, long v, int b, int sc, Prog *p)
  1555. {
  1556. long o;
  1557. if(sc & (C_SBIT|C_PBIT|C_WBIT))
  1558. diag(".S/.P/.W on VLDR/VSTR instruction");
  1559. o = (sc & C_SCOND) << 28;
  1560. o |= 0xd<<24 | (1<<23);
  1561. if(v < 0) {
  1562. v = -v;
  1563. o ^= 1 << 23;
  1564. }
  1565. if(v & 3)
  1566. diag("odd offset for floating point op: %ld\n%P", v, p);
  1567. else if(v >= (1<<10))
  1568. diag("literal span too large: %ld\n%P", v, p);
  1569. o |= (v>>2) & 0xFF;
  1570. o |= b << 16;
  1571. o |= r << 12;
  1572. switch(a) {
  1573. default:
  1574. diag("bad fst %A", a);
  1575. case AMOVD:
  1576. o |= 0xb<<8;
  1577. break;
  1578. case AMOVF:
  1579. o |= 0xa<<8;
  1580. break;
  1581. }
  1582. return o;
  1583. }
  1584. long
  1585. ofsr(int a, int r, long v, int b, int sc, Prog *p)
  1586. {
  1587. long o;
  1588. if(vfp)
  1589. return ovfpmem(a, r, v, b, sc, p);
  1590. if(sc & C_SBIT)
  1591. diag(".S on FLDR/FSTR instruction");
  1592. o = (sc & C_SCOND) << 28;
  1593. if(!(sc & C_PBIT))
  1594. o |= 1 << 24;
  1595. if(sc & C_WBIT)
  1596. o |= 1 << 21;
  1597. o |= (6<<25) | (1<<24) | (1<<23);
  1598. if(v < 0) {
  1599. v = -v;
  1600. o ^= 1 << 23;
  1601. }
  1602. if(v & 3)
  1603. diag("odd offset for floating point op: %ld\n%P", v, p);
  1604. else if(v >= (1<<10))
  1605. diag("literal span too large: %ld\n%P", v, p);
  1606. o |= (v>>2) & 0xFF;
  1607. o |= b << 16;
  1608. o |= r << 12;
  1609. o |= 1 << 8;
  1610. switch(a) {
  1611. default:
  1612. diag("bad fst %A", a);
  1613. case AMOVD:
  1614. o |= 1<<15;
  1615. case AMOVF:
  1616. break;
  1617. }
  1618. return o;
  1619. }
  1620. long
  1621. omvl(Prog *p, Adr *a, int dr)
  1622. {
  1623. long v, o1;
  1624. if(!p->cond) {
  1625. aclass(a);
  1626. v = immrot(~instoffset);
  1627. if(v == 0) {
  1628. diag("missing literal");
  1629. prasm(p);
  1630. return 0;
  1631. }
  1632. o1 = oprrr(AMVN, p->scond&C_SCOND);
  1633. o1 |= v;
  1634. o1 |= dr << 12;
  1635. } else {
  1636. v = p->cond->pc - p->pc - 8;
  1637. o1 = olr(v, REGPC, dr, p->scond&C_SCOND);
  1638. }
  1639. return o1;
  1640. }
  1641. static Ieee chipfloats[] = {
  1642. {0x00000000, 0x00000000}, /* 0 */
  1643. {0x00000000, 0x3ff00000}, /* 1 */
  1644. {0x00000000, 0x40000000}, /* 2 */
  1645. {0x00000000, 0x40080000}, /* 3 */
  1646. {0x00000000, 0x40100000}, /* 4 */
  1647. {0x00000000, 0x40140000}, /* 5 */
  1648. {0x00000000, 0x3fe00000}, /* .5 */
  1649. {0x00000000, 0x40240000}, /* 10 */
  1650. };
  1651. int
  1652. chipfloat(Ieee *e)
  1653. {
  1654. Ieee *p;
  1655. int n;
  1656. if(vfp)
  1657. return -1;
  1658. for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){
  1659. p = &chipfloats[n];
  1660. if(p->l == e->l && p->h == e->h)
  1661. return n;
  1662. }
  1663. return -1;
  1664. }