bootgram.y 23 KB

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