bootgram.y 23 KB

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