bootgram.y 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. %{
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. *
  6. * Author: Hans van Staveren
  7. */
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <assert.h>
  12. #include <em_spec.h>
  13. #include <em_flag.h>
  14. #include <em_reg.h>
  15. #define extern
  16. #include "booth.h"
  17. #undef extern
  18. %}
  19. %union {
  20. int yy_int;
  21. int *yy_intp;
  22. string yy_string;
  23. list1 yy_list1;
  24. list2 yy_list2;
  25. expr_t yy_expr;
  26. cost_t yy_cost;
  27. set_t yy_set;
  28. ident_p yy_ident;
  29. char yy_char;
  30. inst_t yy_instance;
  31. }
  32. %type <yy_list1> list1 structlistel
  33. %type <yy_list2> structlist structdecl
  34. %type <yy_expr> expr optexpr
  35. %type <yy_cost> optcost cost optcommacost
  36. %type <yy_int> optboolexpr optnocoerc mnem emargno tokargno optprop
  37. %type <yy_int> optcommabool optstack subreg tokenexpressionno optregvar
  38. %type <yy_int> tokeninstanceno code stackreplacement optslashnumber
  39. %type <yy_set> tokenexpression
  40. %type <yy_instance> tokeninstance
  41. %type <yy_string> optformat
  42. %token <yy_string> IDENT TYPENAME
  43. %token <yy_ident> RIDENT PIDENT TIDENT EIDENT
  44. %token <yy_string> LSTRING STRING
  45. %token <yy_int> NUMBER
  46. %token <yy_intp> CIDENT
  47. %token REGISTERHEAD TOKENHEAD EXPRESSIONHEAD CODEHEAD MOVEHEAD TESTHEAD STACKHEAD
  48. %token REGVAR INREG LOOP POINTER FLOAT
  49. %token TIMEFAC SIZEFAC FORMAT RETURN
  50. %token MOVE ERASE ALLOCATE ELLIPS COST REMOVE STACK
  51. %token SEP SAMESIGN SFIT UFIT ROM DEFINED TOSTRING LOWW HIGHW
  52. %token NOCC SETCC SAMECC TEST NOCOERC
  53. %token <yy_char> LCASELETTER
  54. %start machinespec
  55. %left OR2
  56. %left AND2
  57. %left CMPEQ CMPNE
  58. %left CMPLT CMPLE CMPGT CMPGE
  59. %left RSHIFT LSHIFT
  60. %left '+' '-'
  61. %left '*' '/' '%'
  62. %nonassoc NOT COMP UMINUS
  63. %nonassoc '$'
  64. %%
  65. machinespec
  66. : rcsid constants registersection tokensection
  67. { inbetween(); }
  68. expressionsection codesection movesection testsection stacksection
  69. ;
  70. rcsid
  71. : /* empty */
  72. | STRING
  73. { strlookup($1); }
  74. ;
  75. constants
  76. : /* empty */
  77. | constants CIDENT '=' NUMBER
  78. { *$2 = $4; }
  79. | constants SIZEFAC '=' NUMBER optslashnumber
  80. { cc1 = $4; cc2 = $5; }
  81. | constants TIMEFAC '=' NUMBER optslashnumber
  82. { cc3 = $4; cc4 = $5; }
  83. | constants FORMAT '=' STRING
  84. { fmt = $4; }
  85. ;
  86. optslashnumber
  87. : /* empty */
  88. { $$ = 1; }
  89. | '/' NUMBER
  90. { $$ = $2; }
  91. ;
  92. registersection
  93. : REGISTERHEAD registerdefs
  94. ;
  95. registerdefs
  96. : /* empty */
  97. | registerdefs registerdef
  98. ;
  99. registerdef
  100. : IDENT '=' '(' STRING ',' NUMBER list1 ')' optregvar list1 '.'
  101. { ident_p ip;
  102. list1 l;
  103. reginfo r;
  104. int i;
  105. r=(reginfo) myalloc(sizeof(struct reginfo));
  106. r->rname = $1;
  107. r->rrepr = $4;
  108. r->rsize = $6;
  109. if($9>=0 && $7!=0)
  110. yyerror("No subregisters allowed in regvar");
  111. for (i=0;i<MAXMEMBERS;i++)
  112. r->rmembers[i] = 0;
  113. i=0;
  114. for (l=$7;l!=0;l=l->l1next) {
  115. ip=ilookup(l->l1name,LOOKUP);
  116. if (ip->i_type != IREG)
  117. yyerror("Bad member of set");
  118. chktabsiz(i,MAXMEMBERS,"Member of register");
  119. r->rmembers[i++] = ip->i_i.i_regno;
  120. }
  121. maxmembers=max(maxmembers,i);
  122. r->rregvar=$9;
  123. if ($9>=0) {
  124. rvused=1;
  125. chktabsiz(nregvar[$9],MAXREGVARS,"Regvar");
  126. rvnumbers[$9][nregvar[$9]++] = nmachregs;
  127. }
  128. for(i=0;i<PROPSETSIZE;i++)
  129. r->rprop[i] = 0;
  130. ip=ilookup($1,ENTER);
  131. ip->i_type=IREG;
  132. ip->i_i.i_regno=nmachregs;
  133. for (l = $10; l!= 0; l=l->l1next) {
  134. ip = ilookup(l->l1name,HALFWAY);
  135. if (ip->i_type) {
  136. if (ip->i_type != IPRP)
  137. yyerror("Multiple defined symbol");
  138. else if(machprops[ip->i_i.i_prpno].propset.set_size != r->rsize)
  139. yyerror("property has more than 1 size");
  140. } else {
  141. chktabsiz(nprops,MAXPROPS,"Property");
  142. ip->i_type = IPRP;
  143. ip->i_i.i_prpno = nprops;
  144. machprops[nprops].propname = ip;
  145. machprops[nprops++].propset.set_size = r->rsize;
  146. }
  147. r->rprop[ip->i_i.i_prpno>>4] |= (1<<(ip->i_i.i_prpno&017));
  148. }
  149. chktabsiz(nmachregs,MAXREGS,"Register table");
  150. machregs[nmachregs++] = r;
  151. }
  152. | error '.'
  153. ;
  154. optregvar
  155. : /* nothing */
  156. { $$ = -1; }
  157. | REGVAR
  158. { $$ = reg_any; }
  159. | REGVAR '(' LOOP ')'
  160. { $$ = reg_loop; }
  161. | REGVAR '(' POINTER ')'
  162. { $$ = reg_pointer; }
  163. | REGVAR '(' FLOAT ')'
  164. { $$ = reg_float; }
  165. ;
  166. tokensection
  167. : TOKENHEAD tkdefs
  168. ;
  169. tkdefs
  170. : /* empty */
  171. | tkdefs tkdef
  172. ;
  173. tkdef
  174. : IDENT '=' structdecl NUMBER optcost optformat
  175. { token_p tp;
  176. ident_p ip;
  177. chktabsiz(nmachtokens,MAXTOKENS,"Token table");
  178. tp = &machtokens[nmachtokens];
  179. tp->t_name = $1;
  180. tp->t_struct = $3;
  181. tp->t_size = $4;
  182. tp->t_cost = $5;
  183. ip = ilookup($1,ENTER);
  184. ip->i_type = ITOK;
  185. ip->i_i.i_tokno = nmachtokens++;
  186. maxtokensize=max(maxtokensize,structsize($3));
  187. setfields(tp,$6);
  188. }
  189. | error
  190. ;
  191. structdecl
  192. : '{' structlist '}'
  193. { $$ = lookstruct($2); }
  194. ;
  195. structlist
  196. : /* empty */
  197. { $$=0; }
  198. | structlistel structlist
  199. { $$=(list2) myalloc(sizeof(struct list2str));
  200. $$->l2next = $2;
  201. $$->l2list = $1;
  202. }
  203. ;
  204. structlistel
  205. : TYPENAME list1 ';'
  206. { $$=(list1) myalloc(sizeof(struct list1str));
  207. $$->l1next = $2;
  208. $$->l1name = $1;
  209. }
  210. ;
  211. optcost : /* empty */
  212. { $$.c_size = $$.c_time = 0; }
  213. | COST '=' '(' expr ',' expr ')'
  214. { MUST2BEINT($4,$6);
  215. $$.c_size = exp1;
  216. $$.c_time = exp2;
  217. }
  218. ;
  219. optformat
  220. : /* empty */
  221. { $$ = 0; }
  222. | STRING
  223. ;
  224. expressionsection
  225. : /* empty */
  226. | EXPRESSIONHEAD tokenexpressions
  227. ;
  228. tokenexpressions
  229. : tokenexpressionline
  230. | tokenexpressionline tokenexpressions
  231. ;
  232. tokenexpressionline
  233. : IDENT '=' tokenexpression
  234. {
  235. { ident_p ip;
  236. chktabsiz(nmachsets,MAXSETS,"Expression table");
  237. machsets[nmachsets] = $3;
  238. ip=ilookup($1,ENTER);
  239. ip->i_type = IEXP;
  240. ip->i_i.i_expno = nmachsets++;
  241. }
  242. }
  243. | error
  244. ;
  245. tokenexpression
  246. : PIDENT
  247. { $$ = machprops[$1->i_i.i_prpno].propset; }
  248. | TIDENT
  249. { int i;
  250. for(i=0;i<SETSIZE;i++) $$.set_val[i]=0;
  251. $$.set_val[($1->i_i.i_tokno+nmachregs+1)>>4] |=
  252. 01<<(($1->i_i.i_tokno+nmachregs+1)&017);
  253. $$.set_size = machtokens[$1->i_i.i_tokno].t_size;
  254. }
  255. | EIDENT
  256. { $$=machsets[$1->i_i.i_expno]; }
  257. | tokenexpression '*' tokenexpression
  258. { int i;
  259. if (($$.set_size=$1.set_size)==0)
  260. $$.set_size = $3.set_size;
  261. for (i=0;i<SETSIZE;i++)
  262. $$.set_val[i] = $1.set_val[i] & $3.set_val[i];
  263. }
  264. | tokenexpression '+' tokenexpression
  265. { int i;
  266. if ($1.set_size == -1)
  267. $$.set_size = $3.set_size;
  268. else if ($3.set_size == -1)
  269. $$.set_size = $1.set_size;
  270. else if ($1.set_size == $3.set_size)
  271. $$.set_size = $1.set_size;
  272. else
  273. $$.set_size = 0;
  274. for (i=0;i<SETSIZE;i++)
  275. $$.set_val[i] = $1.set_val[i] | $3.set_val[i];
  276. }
  277. | tokenexpression '-' tokenexpression
  278. { int i;
  279. if ($1.set_size == -1)
  280. $$.set_size = $3.set_size;
  281. else if ($3.set_size == -1)
  282. $$.set_size = $1.set_size;
  283. else if ($1.set_size == $3.set_size)
  284. $$.set_size = $1.set_size;
  285. else
  286. $$.set_size = 0;
  287. for (i=0;i<SETSIZE;i++)
  288. $$.set_val[i] = $1.set_val[i] & ~ $3.set_val[i];
  289. }
  290. | '(' tokenexpression ')'
  291. { $$ = $2; }
  292. ;
  293. codesection
  294. : CODEHEAD coderules
  295. ;
  296. coderules
  297. : coderule
  298. | coderules coderule
  299. ;
  300. coderule
  301. : { nallreg=emrepllen=tokrepllen=0; }
  302. empattern SEP stackpattern SEP code SEP stackreplacement SEP
  303. emreplacement SEP cost
  304. { int i;
  305. if (emrepllen) {
  306. outbyte(DO_EMREPLACE+(emrepllen<<5));
  307. for (i=0;i<emrepllen;i++) {
  308. out(replmnem[i]);
  309. out(replexpr[i]);
  310. }
  311. }
  312. if ($8==0) {
  313. outbyte(DO_TOKREPLACE+(tokrepllen<<5));
  314. for(i=0;i<tokrepllen;i++)
  315. out(replinst[i]);
  316. } else {
  317. static int warncount=0;
  318. if (!warncount++)
  319. fprintf(stderr,
  320. "WARNING: convert to stacksection, will disappear soon");
  321. outbyte(DO_TOKREPLACE);
  322. }
  323. if ($12.c_size!=0 || $12.c_time!=0) {
  324. outbyte(DO_COST);
  325. out($12.c_size);
  326. out($12.c_time);
  327. }
  328. outbyte(empatlen==0? DO_RETURN : DO_NEXTEM);
  329. fprintf(cfile,"\n");
  330. ncoderules++;
  331. maxallreg=max(maxallreg,nallreg);
  332. if (empatlen==0) { /* coercion */
  333. if (tokrepllen<1 && $8==0)
  334. yyerror("No replacement in coercion");
  335. if (tokpatlen>1)
  336. yyerror("Token pattern too long");
  337. if ($8!=0) { /* stacking */
  338. c1_p cp;
  339. chktabsiz(nc1,MAXC1,"Coerc table 1");
  340. cp = &c1coercs[nc1++];
  341. cp->c1_texpno = pattokexp[1];
  342. cp->c1_prop = -1;
  343. cp->c1_codep = $6;
  344. } else if (tokrepllen>1) { /* splitting */
  345. c2_p cp;
  346. chktabsiz(nc2,MAXC2,"Coerc table 2");
  347. cp= &c2coercs[nc2++];
  348. cp->c2_texpno = pattokexp[1];
  349. cp->c2_nsplit = tokrepllen;
  350. maxsplit=max(maxsplit,tokrepllen);
  351. for (i=0;i<tokrepllen;i++)
  352. cp->c2_repl[i] = replinst[i];
  353. cp->c2_codep = $6;
  354. if (nallreg>0)
  355. yyerror("No allocates allowed here");
  356. } else { /* one to one coercion */
  357. c3_p cp;
  358. chktabsiz(nc3,MAXC3,"Coerc table 3");
  359. cp= &c3coercs[nc3++];
  360. if (tokpatlen)
  361. cp->c3_texpno = pattokexp[1];
  362. else
  363. cp->c3_texpno = 0;
  364. if (nallreg>1)
  365. yyerror("Too many allocates in coercion");
  366. cp->c3_prop = nallreg==0 ? 0 : allreg[0];
  367. cp->c3_repl = replinst[0];
  368. cp->c3_codep = $6;
  369. }
  370. }
  371. }
  372. | error
  373. ;
  374. empattern
  375. : /* empty */
  376. { empatlen=0; }
  377. | mnemlist optboolexpr
  378. { int i;
  379. empatexpr = $2;
  380. patbyte(0);
  381. patshort(prevind);
  382. prevind = npatbytes - 3;
  383. maxempatlen = max(empatlen,maxempatlen);
  384. pat(empatlen);
  385. for(i=1;i<=empatlen;i++)
  386. patbyte(patmnem[i]);
  387. pat(empatexpr);
  388. rulecount = npatbytes;
  389. patbyte(1); /* number of different rules with this pattern */
  390. pat(codebytes); /* first rule */
  391. }
  392. | ELLIPS
  393. { pattern[rulecount]++;
  394. maxrule= max(maxrule,pattern[rulecount]);
  395. pat(codebytes);
  396. }
  397. ;
  398. mnemlist
  399. : mnem
  400. { empatlen = 1; patmnem[empatlen] = $1; }
  401. | mnemlist mnem
  402. { chktabsiz(empatlen+1,MAXEMPATLEN,"EM pattern");
  403. patmnem[++empatlen] = $2;
  404. }
  405. ;
  406. mnem : IDENT
  407. { if(strlen($1)!=3 || ($$=mlookup($1))==0)
  408. yyerror("not an EM-mnemonic");
  409. }
  410. ;
  411. stackpattern
  412. : optnocoerc tokenexpressionlist optstack
  413. { int i;
  414. if (tokpatlen != 0) {
  415. outbyte(($1 ? ( $3 ? DO_XXMATCH: DO_XMATCH ) : DO_MATCH)+(tokpatlen<<5));
  416. for(i=1;i<=tokpatlen;i++) {
  417. out(pattokexp[i]);
  418. }
  419. }
  420. if ($3 && tokpatlen==0 && empatlen==0) {
  421. outbyte(DO_COERC);
  422. }
  423. if ($3 && !$1 && empatlen!=0) {
  424. outbyte(DO_REMOVE);
  425. out(allexpno);
  426. }
  427. }
  428. ;
  429. optnocoerc
  430. : /* empty */
  431. { $$ = 0; }
  432. | NOCOERC ':'
  433. { $$ = 1; }
  434. ;
  435. tokenexpressionlist
  436. : /* empty */
  437. { tokpatlen = 0; }
  438. | tokenexpressionlist tokenexpressionno
  439. { chktabsiz(tokpatlen+1,MAXPATLEN,"Token pattern");
  440. pattokexp[++tokpatlen] = $2;
  441. if (machsets[$2].set_size==0)
  442. yyerror("Various sized set in tokenpattern");
  443. }
  444. ;
  445. tokenexpressionno
  446. : tokenexpression
  447. { $$ = exprlookup($1); }
  448. ;
  449. optstack
  450. : /* empty */
  451. { $$ = 0; }
  452. | STACK
  453. { $$ = 1; }
  454. ;
  455. code :
  456. { $<yy_int>$ = codebytes; cchandled=ccspoiled=0; }
  457. initcode restcode
  458. { if (cchandled==0 && ccspoiled!=0) {
  459. outbyte(DO_ERASE);
  460. out(ccregexpr);
  461. }
  462. }
  463. ;
  464. initcode
  465. : /* empty */
  466. | initcode remove
  467. | initcode allocate
  468. ;
  469. remove
  470. : REMOVE '(' tokenexpressionno
  471. { curtokexp = $3; }
  472. optcommabool ')'
  473. { outbyte(DO_REMOVE+ ($5!=0 ? 32 : 0));
  474. out($3);
  475. if ($5!=0) out($5);
  476. }
  477. | REMOVE '(' expr ')'
  478. { if ($3.expr_typ != TYPREG)
  479. yyerror("Expression must be register");
  480. outbyte(DO_RREMOVE);
  481. out($3.expr_index);
  482. }
  483. ;
  484. optcommabool
  485. : /* empty */
  486. { $$ = 0; }
  487. | ',' expr
  488. { MUST1BEBOOL($2);
  489. $$ = exp1;
  490. }
  491. ;
  492. restcode: /* empty */
  493. | restcode LSTRING expr
  494. { outbyte(DO_LOUTPUT);
  495. out(stringno($2));
  496. free($2);
  497. out($3.expr_index);
  498. ccspoiled++;
  499. }
  500. | restcode stringlist
  501. { int i;
  502. for(i=0;nstr>0;i++,nstr--) {
  503. if (i%8==0) outbyte(DO_ROUTPUT+(nstr>7 ? 7 : nstr-1)*32);
  504. out(strar[i]);
  505. }
  506. ccspoiled++;
  507. }
  508. | restcode RETURN
  509. { outbyte(DO_PRETURN); }
  510. | restcode move
  511. | restcode erase
  512. | restcode NOCC
  513. { outbyte(DO_ERASE);
  514. out(ccregexpr);
  515. cchandled++;
  516. }
  517. | restcode SAMECC
  518. { cchandled++; }
  519. | restcode SETCC '(' tokeninstanceno ')'
  520. { outbyte(DO_MOVE);
  521. out(ccinstanceno);
  522. out($4);
  523. cchandled++;
  524. }
  525. | restcode TEST '(' tokeninstanceno ')'
  526. { outbyte(DO_MOVE);
  527. out($4);
  528. out(ccinstanceno);
  529. ccspoiled=0;
  530. }
  531. ;
  532. stringlist
  533. : STRING
  534. { nstr=1;
  535. strar[0]=stringno($1);
  536. free($1);
  537. }
  538. | stringlist STRING
  539. { chktabsiz(nstr,MAXNSTR,"Consecutiv strings");
  540. strar[nstr++] = stringno($2);
  541. free($2);
  542. }
  543. ;
  544. move
  545. : MOVE '(' tokeninstanceno ',' tokeninstanceno ')'
  546. { outbyte(DO_MOVE);
  547. out($3);
  548. out($5);
  549. }
  550. ;
  551. erase
  552. : ERASE '(' expr ')'
  553. { outbyte(DO_ERASE);
  554. out($3.expr_index);
  555. if($3.expr_typ != TYPREG)
  556. yyerror("Bad argument of erase");
  557. }
  558. ;
  559. allocate
  560. : ALLOCATE { dealflag=0; } '(' alloclist ')'
  561. { if (dealflag)
  562. outbyte(DO_REALLOCATE);
  563. }
  564. ;
  565. alloclist
  566. : allocel
  567. | alloclist optcomma allocel
  568. ;
  569. allocel
  570. : tokeninstanceno /* deallocate */
  571. { outbyte(DO_DEALLOCATE);
  572. out($1);
  573. dealflag++;
  574. }
  575. | PIDENT
  576. { allreg[nallreg++] = $1->i_i.i_prpno;
  577. outbyte(DO_ALLOCATE);
  578. out($1->i_i.i_prpno);
  579. }
  580. | PIDENT '=' tokeninstanceno
  581. { allreg[nallreg++] = $1->i_i.i_prpno;
  582. outbyte(DO_ALLOCATE+32);
  583. out($1->i_i.i_prpno);
  584. out($3);
  585. }
  586. ;
  587. stackreplacement
  588. : /* empty */
  589. { $$=0; }
  590. | STACK
  591. { $$=1; }
  592. | '{' STACK '}'
  593. { $$=1; }
  594. | stackrepllist
  595. { $$=0; }
  596. ;
  597. stackrepllist
  598. : tokeninstanceno
  599. { tokrepllen=1; replinst[0] = $1; }
  600. | stackrepllist tokeninstanceno
  601. { chktabsiz(tokrepllen+1,MAXPATLEN,"Stack replacement");
  602. replinst[tokrepllen++] = $2;
  603. }
  604. ;
  605. emreplacement
  606. : /* empty, normal case */
  607. | emrepllist
  608. ;
  609. emrepllist
  610. : mnem optexpr
  611. { emrepllen=1;
  612. replmnem[0]=$1;
  613. replexpr[0]=$2.expr_index;
  614. }
  615. | emrepllist mnem optexpr
  616. { chktabsiz(emrepllen+1,MAXEMPATLEN,"EM replacement");
  617. replmnem[emrepllen]=$2;
  618. replexpr[emrepllen]=$3.expr_index;
  619. emrepllen++;
  620. }
  621. ;
  622. cost : /* empty */
  623. { $$.c_size = $$.c_time = 0;
  624. }
  625. | '(' expr ',' expr ')'
  626. { MUST2BEINT($2,$4);
  627. $$.c_size = exp1;
  628. $$.c_time = exp2;
  629. }
  630. | cost '+' '%' '[' tokargno ']'
  631. { $$.c_size = lookup(1,EX_PLUS,$1.c_size,
  632. lookup(0,EX_COST,$5,0));
  633. $$.c_time = lookup(1,EX_PLUS,$1.c_time,
  634. lookup(0,EX_COST,$5,1));
  635. }
  636. ;
  637. movesection
  638. : MOVEHEAD movedefs
  639. ;
  640. movedefs
  641. : movedef
  642. | movedefs movedef
  643. ;
  644. movedef
  645. : '(' tokenexpressionno
  646. { curtokexp = $2; }
  647. optboolexpr ',' tokenexpressionno
  648. { curtokexp = $6;
  649. pattokexp[1] = $2;
  650. pattokexp[2] = $6;
  651. tokpatlen=2;
  652. }
  653. optboolexpr ',' code optcommacost ')'
  654. { move_p mp;
  655. outbyte(DO_RETURN);
  656. fprintf(cfile,"\n");
  657. chktabsiz(nmoves,NMOVES,"Move definition table");
  658. mp = &machmoves[nmoves++];
  659. mp->m_set1 = $2;
  660. mp->m_expr1= $4;
  661. mp->m_set2 = $6;
  662. mp->m_expr2= $8;
  663. mp->m_cindex=$10;
  664. mp->m_cost = $11;
  665. }
  666. | error
  667. ;
  668. testsection
  669. : /* empty */
  670. | TESTHEAD testdefs
  671. ;
  672. testdefs: testdef
  673. | testdefs testdef
  674. ;
  675. testdef : '(' tokenexpressionno
  676. { curtokexp = $2;
  677. pattokexp[1] = $2;
  678. pattokexp[2] = cocosetno;
  679. tokpatlen=2;
  680. }
  681. optboolexpr ',' code optcommacost ')'
  682. { move_p mp;
  683. outbyte(DO_RETURN);
  684. fprintf(cfile,"\n");
  685. chktabsiz(nmoves,NMOVES,"Move definition table(tests)");
  686. mp = &machmoves[nmoves++];
  687. mp->m_set1 = $2;
  688. mp->m_expr1 = $4;
  689. mp->m_set2 = cocosetno;
  690. mp->m_expr2 = 0;
  691. mp->m_cindex = $6;
  692. mp->m_cost = $7;
  693. }
  694. ;
  695. stacksection
  696. : STACKHEAD stackdefs
  697. | /* empty */
  698. ;
  699. stackdefs
  700. : stackdef
  701. | stackdefs stackdef
  702. ;
  703. stackdef
  704. : '(' tokenexpressionno
  705. { curtokexp = $2;
  706. pattokexp[1] = $2;
  707. tokpatlen=1;
  708. }
  709. optboolexpr ',' optprop ',' code optcommacost ')'
  710. { c1_p cp;
  711. outbyte(DO_TOKREPLACE);
  712. outbyte(DO_RETURN);
  713. fprintf(cfile,"\n");
  714. chktabsiz(nc1,MAXC1,"Stacking table");
  715. cp = &c1coercs[nc1++];
  716. cp->c1_texpno = $2;
  717. cp->c1_expr = $4;
  718. cp->c1_prop = $6;
  719. cp->c1_codep = $8;
  720. cp->c1_cost = $9;
  721. }
  722. ;
  723. optprop
  724. : /* empty */
  725. { $$ = -1; }
  726. | PIDENT
  727. { $$ = $1->i_i.i_prpno; }
  728. ;
  729. optcommacost
  730. : /* empty */
  731. { $$.c_size = 0; $$.c_time = 0;}
  732. | ',' cost
  733. { $$ = $2; }
  734. ;
  735. list1 : /* empty */
  736. { $$ = 0; }
  737. | optcomma IDENT list1
  738. { $$=(list1) myalloc(sizeof(struct list1str));
  739. $$->l1next = $3;
  740. $$->l1name = $2;
  741. }
  742. ;
  743. optcomma: /* nothing */
  744. | ','
  745. ;
  746. emargno : NUMBER
  747. { if ($1<1 || $1>empatlen)
  748. yyerror("Number after $ out of range");
  749. $$ = $1;
  750. }
  751. ;
  752. tokargno
  753. : NUMBER
  754. { if ($1<1 || $1>tokpatlen)
  755. yyerror("Number within %[] out of range");
  756. $$ = $1;
  757. }
  758. ;
  759. expr : '$' emargno
  760. { $$.expr_index = lookup(0,EX_ARG,$2,0); $$.expr_typ = argtyp(patmnem[$2]);
  761. }
  762. | NUMBER
  763. { $$.expr_index = lookup(0,EX_CON,(int)($1&0177777),(int)($1>>16));
  764. $$.expr_typ = TYPINT;
  765. }
  766. | STRING
  767. { $$.expr_index = lookup(0,EX_STRING,strlookup($1),0);
  768. $$.expr_typ = TYPSTR;
  769. }
  770. | RIDENT
  771. { $$.expr_index = lookup(0,EX_REG,$1->i_i.i_regno,0);
  772. $$.expr_typ = TYPREG;
  773. }
  774. | '%' '[' tokargno '.' IDENT ']'
  775. { $$.expr_index = lookup(0,EX_TOKFIELD,$3,
  776. findstructel(pattokexp[$3],$5,&$$.expr_typ));
  777. }
  778. | '%' '[' tokargno subreg ']'
  779. { chkregexp(pattokexp[$3]);
  780. $$.expr_index = lookup(0,EX_SUBREG,$3,$4);
  781. $$.expr_typ = TYPREG;
  782. }
  783. | '%' '[' LCASELETTER subreg ']'
  784. { if ($3 >= 'a'+nallreg)
  785. yyerror("Bad letter in %[x] construct");
  786. $$.expr_index = lookup(0,EX_ALLREG,$3-'a'+1,$4);
  787. $$.expr_typ = TYPREG;
  788. }
  789. | '%' '[' IDENT ']'
  790. { $$.expr_index = lookup(0,EX_TOKFIELD,0,
  791. findstructel(curtokexp,$3,&$$.expr_typ));
  792. }
  793. | TOSTRING '(' expr ')'
  794. { MUST1BEINT($3);
  795. $$.expr_index = lookup(0,EX_TOSTRING,exp1,0);
  796. $$.expr_typ = TYPSTR;
  797. }
  798. | DEFINED '(' expr ')'
  799. { $$.expr_index = lookup(0,EX_DEFINED,$3.expr_index,0);
  800. $$.expr_typ = TYPBOOL;
  801. }
  802. | SAMESIGN '(' expr ',' expr ')'
  803. { MUST2BEINT($3,$5);
  804. $$.expr_index = lookup(1,EX_SAMESIGN,exp1,exp2);
  805. $$.expr_typ = TYPBOOL;
  806. }
  807. | SFIT '(' expr ',' expr ')'
  808. { MUST2BEINT($3,$5);
  809. $$.expr_index = lookup(0,EX_SFIT,exp1,exp2);
  810. $$.expr_typ = TYPBOOL;
  811. }
  812. | UFIT '(' expr ',' expr ')'
  813. { MUST2BEINT($3,$5);
  814. $$.expr_index = lookup(0,EX_UFIT,exp1,exp2);
  815. $$.expr_typ = TYPBOOL;
  816. }
  817. | ROM '(' emargno ',' NUMBER ')'
  818. { if ($5<1 || $5>3)
  819. yyerror("Second argument of rom must be >=1 and <=3");
  820. $$.expr_index = lookup(0,EX_ROM,$3-1,$5-1);
  821. $$.expr_typ = TYPINT;
  822. }
  823. | LOWW '(' emargno ')'
  824. {
  825. $$.expr_index = lookup(0,EX_LOWW,$3-1,0);
  826. $$.expr_typ = TYPINT;
  827. }
  828. | HIGHW '(' emargno ')'
  829. {
  830. $$.expr_index = lookup(0,EX_HIGHW,$3-1,0);
  831. $$.expr_typ = TYPINT;
  832. }
  833. | '(' expr ')'
  834. { $$ = $2; }
  835. | expr CMPEQ expr
  836. { switch(commontype($1,$3)) {
  837. case TYPINT:
  838. $$.expr_index = lookup(1,EX_NCPEQ,$1.expr_index,$3.expr_index);
  839. break;
  840. case TYPSTR:
  841. $$.expr_index = lookup(1,EX_SCPEQ,$1.expr_index,$3.expr_index);
  842. break;
  843. case TYPREG:
  844. $$.expr_index = lookup(1,EX_RCPEQ,$1.expr_index,$3.expr_index);
  845. break;
  846. }
  847. $$.expr_typ = TYPBOOL;
  848. }
  849. | expr CMPNE expr
  850. { switch(commontype($1,$3)) {
  851. case TYPINT:
  852. $$.expr_index = lookup(1,EX_NCPNE,$1.expr_index,$3.expr_index);
  853. break;
  854. case TYPSTR:
  855. $$.expr_index = lookup(1,EX_SCPNE,$1.expr_index,$3.expr_index);
  856. break;
  857. case TYPREG:
  858. $$.expr_index = lookup(1,EX_RCPNE,$1.expr_index,$3.expr_index);
  859. break;
  860. }
  861. $$.expr_typ = TYPBOOL;
  862. }
  863. | expr CMPGT expr
  864. { MUST2BEINT($1,$3);
  865. $$.expr_index = lookup(0,EX_NCPGT,exp1,exp2);
  866. $$.expr_typ = TYPBOOL;
  867. }
  868. | expr CMPGE expr
  869. { MUST2BEINT($1,$3);
  870. $$.expr_index = lookup(0,EX_NCPGE,exp1,exp2);
  871. $$.expr_typ = TYPBOOL;
  872. }
  873. | expr CMPLT expr
  874. { MUST2BEINT($1,$3);
  875. $$.expr_index = lookup(0,EX_NCPLT,exp1,exp2);
  876. $$.expr_typ = TYPBOOL;
  877. }
  878. | expr CMPLE expr
  879. { MUST2BEINT($1,$3);
  880. $$.expr_index = lookup(0,EX_NCPLE,exp1,exp2);
  881. $$.expr_typ = TYPBOOL;
  882. }
  883. | expr OR2 expr
  884. { MUST2BEBOOL($1,$3);
  885. $$.expr_index = lookup(0,EX_OR2,exp1,exp2);
  886. $$.expr_typ = TYPBOOL;
  887. }
  888. | expr AND2 expr
  889. { MUST2BEBOOL($1,$3);
  890. $$.expr_index = lookup(0,EX_AND2,exp1,exp2);
  891. $$.expr_typ = TYPBOOL;
  892. }
  893. | expr '+' expr
  894. { switch(commontype($1,$3)) {
  895. case TYPINT:
  896. $$.expr_index = lookup(1,EX_PLUS,$1.expr_index,$3.expr_index);
  897. break;
  898. case TYPSTR:
  899. $$.expr_index = lookup(0,EX_CAT,$1.expr_index,$3.expr_index);
  900. break;
  901. default:
  902. yyerror("Bad types");
  903. }
  904. $$.expr_typ = $1.expr_typ;
  905. }
  906. | expr '-' expr
  907. { MUST2BEINT($1,$3);
  908. $$.expr_index = lookup(0,EX_MINUS,exp1,exp2);
  909. $$.expr_typ = TYPINT;
  910. }
  911. | expr '*' expr
  912. { MUST2BEINT($1,$3);
  913. $$.expr_index = lookup(1,EX_TIMES,exp1,exp2);
  914. $$.expr_typ = TYPINT;
  915. }
  916. | expr '/' expr
  917. { MUST2BEINT($1,$3);
  918. $$.expr_index = lookup(0,EX_DIVIDE,exp1,exp2);
  919. $$.expr_typ = TYPINT;
  920. }
  921. | expr '%' expr
  922. { MUST2BEINT($1,$3);
  923. $$.expr_index = lookup(0,EX_MOD,exp1,exp2);
  924. $$.expr_typ = TYPINT;
  925. }
  926. | expr LSHIFT expr
  927. { MUST2BEINT($1,$3);
  928. $$.expr_index = lookup(0,EX_LSHIFT,exp1,exp2);
  929. $$.expr_typ = TYPINT;
  930. }
  931. | expr RSHIFT expr
  932. { MUST2BEINT($1,$3);
  933. $$.expr_index = lookup(0,EX_RSHIFT,exp1,exp2);
  934. $$.expr_typ = TYPINT;
  935. }
  936. | NOT expr
  937. { MUST1BEBOOL($2);
  938. $$.expr_index = lookup(0,EX_NOT,exp1,0);
  939. $$.expr_typ = TYPBOOL;
  940. }
  941. | COMP expr
  942. { MUST1BEINT($2);
  943. $$.expr_index = lookup(0,EX_COMP,exp1,0);
  944. $$.expr_typ = TYPINT;
  945. }
  946. | INREG '(' expr ')'
  947. { MUST1BEINT($3);
  948. $$.expr_index = lookup(0,EX_INREG,exp1,0);
  949. $$.expr_typ = TYPINT;
  950. }
  951. | REGVAR '(' expr ')'
  952. { MUST1BEINT($3);
  953. $$.expr_index = lookup(0,EX_REGVAR,exp1,0);
  954. $$.expr_typ = TYPREG;
  955. }
  956. /*
  957. | '-' expr %prec UMINUS
  958. { MUST1BEINT($2);
  959. $$.expr_index = lookup(0,EX_UMINUS,exp1,0);
  960. $$.expr_typ = TYPINT;
  961. }
  962. */
  963. ;
  964. subreg : /* empty */
  965. { $$=0; }
  966. | '.' NUMBER
  967. { $$=$2; }
  968. ;
  969. optboolexpr
  970. : /* empty */
  971. { $$ = 0; }
  972. | expr
  973. { MUST1BEBOOL($1);
  974. $$=exp1;
  975. }
  976. ;
  977. optexpr
  978. : /* empty */
  979. { $$.expr_typ=0;
  980. $$.expr_index=0;
  981. }
  982. | expr
  983. ;
  984. tokeninstanceno
  985. : tokeninstance
  986. { $$ = instno($1); }
  987. ;
  988. tokeninstance
  989. : '%' '[' tokargno subreg ']'
  990. { int i;
  991. if ($4!=0)
  992. chkregexp(pattokexp[$3]);
  993. $$.in_which = IN_COPY;
  994. $$.in_info[0] = $3;
  995. $$.in_info[1] = $4;
  996. for (i=2;i<TOKENSIZE;i++)
  997. $$.in_info[i] = 0;
  998. }
  999. | '%' '[' tokargno '.' IDENT ']'
  1000. { int typ;
  1001. int i;
  1002. $$.in_which = IN_COPY;
  1003. $$.in_info[0] = $3;
  1004. $$.in_info[1] = findstructel(pattokexp[$3],$5,&typ);
  1005. if (typ != TYPREG)
  1006. yyerror("Must be register");
  1007. for (i=2;i<TOKENSIZE;i++)
  1008. $$.in_info[i] = 0;
  1009. }
  1010. | RIDENT
  1011. { int i;
  1012. $$.in_which = IN_RIDENT;
  1013. $$.in_info[0] = $1->i_i.i_regno;
  1014. for (i=1;i<TOKENSIZE;i++)
  1015. $$.in_info[i] = 0;
  1016. }
  1017. | REGVAR '(' expr ')'
  1018. { int i;
  1019. MUST1BEINT($3);
  1020. $$.in_which = IN_REGVAR;
  1021. $$.in_info[0] = exp1;
  1022. for (i=1;i<TOKENSIZE;i++)
  1023. $$.in_info[i] = 0;
  1024. }
  1025. | '%' '[' LCASELETTER subreg ']'
  1026. { int i;
  1027. if ($3 >= 'a'+nallreg)
  1028. yyerror("Bad letter in %[x] construct");
  1029. $$.in_which = IN_ALLOC;
  1030. $$.in_info[0] = $3-'a';
  1031. $$.in_info[1] = $4;
  1032. for (i=2;i<TOKENSIZE;i++)
  1033. $$.in_info[i] = 0;
  1034. }
  1035. | '{' TIDENT attlist '}'
  1036. { int i;
  1037. $$.in_which = IN_DESCR;
  1038. $$.in_info[0] = $2->i_i.i_tokno;
  1039. for(i=0;i<narexp;i++) {
  1040. if (arexp[i].expr_typ !=
  1041. machtokens[$2->i_i.i_tokno].t_fields[i].t_type)
  1042. yyerror("Attribute %d has wrong type",i+1);
  1043. $$.in_info[i+1] = arexp[i].expr_index;
  1044. }
  1045. for (i=narexp+1;i<TOKENSIZE;i++) {
  1046. if (machtokens[$2->i_i.i_tokno].t_fields[i-1].t_type!=0)
  1047. yyerror("Too few attributes");
  1048. $$.in_info[i] = 0;
  1049. }
  1050. }
  1051. ;
  1052. attlist
  1053. : /* empty */
  1054. { narexp = 0; }
  1055. | attlist ',' expr
  1056. { arexp[narexp++] = $3; }
  1057. ;
  1058. %%