maktab.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. *
  5. */
  6. #include "ip_spec.h"
  7. #include <stdio.h>
  8. #include <em_spec.h>
  9. #include <em_flag.h>
  10. #ifndef NORCSID
  11. static char rcs_id[] = "$Id$" ;
  12. #endif
  13. /* This program reads the human readable interpreter specification
  14. and produces a efficient machine representation that can be
  15. translated by a C-compiler.
  16. */
  17. #define NOTAB 600 /* The max no of interpreter specs */
  18. #define ESCAP 256
  19. struct opform intable[NOTAB] ;
  20. struct opform *lastform = intable-1 ;
  21. int nerror = 0 ;
  22. int atend = 0 ;
  23. int line = 1 ;
  24. int maxinsl= 0 ;
  25. extern char em_mnem[][4] ;
  26. char esca[] = "escape" ;
  27. #define ename(no) ((no)==ESCAP?esca:em_mnem[(no)])
  28. extern char em_flag[] ;
  29. main(argc,argv) char **argv ; {
  30. if ( argc>1 ) {
  31. if ( freopen(argv[1],"r",stdin)==NULL) {
  32. fatal("Cannot open %s",argv[1]) ;
  33. }
  34. }
  35. if ( argc>2 ) {
  36. if ( freopen(argv[2],"w",stdout)==NULL) {
  37. fatal("Cannot create %s",argv[2]) ;
  38. }
  39. }
  40. if ( argc>3 ) {
  41. fatal("%s [ file [ file ] ]",argv[0]) ;
  42. }
  43. atend=0 ;
  44. readin();
  45. atend=1 ;
  46. checkall();
  47. if ( nerror==0 ) {
  48. writeout();
  49. }
  50. exit(nerror);
  51. }
  52. readin() {
  53. register struct opform *nextform ;
  54. char *ident();
  55. char *firstid ;
  56. register maxl ;
  57. maxl = 0 ;
  58. for ( nextform=intable ;
  59. !feof(stdin) && nextform<&intable[NOTAB] ; ) {
  60. firstid=ident() ;
  61. if ( *firstid=='\n' || feof(stdin) ) continue ;
  62. lastform=nextform ;
  63. nextform->i_opcode = getmnem(firstid) ;
  64. nextform->i_flag = decflag(ident()) ;
  65. switch ( nextform->i_flag&OPTYPE ) {
  66. case OPMINI:
  67. case OPSHORT:
  68. nextform->i_num = atoi(ident()) ;
  69. break ;
  70. }
  71. nextform->i_low = atoi(ident()) ;
  72. if ( *ident()!='\n' ) {
  73. int c ;
  74. error("End of line expected");
  75. while ( (c=readchar())!='\n' && c!=EOF ) ;
  76. }
  77. if ( oplength(nextform)>maxl ) maxl=oplength(nextform) ;
  78. nextform++ ;
  79. }
  80. if ( !feof(stdin) ) fatal("Internal table too small") ;
  81. maxinsl = maxl ;
  82. }
  83. char *ident() {
  84. /* skip spaces and tabs, anything up to space,tab or eof is
  85. a identifier.
  86. Anything from # to end-of-line is an end-of-line.
  87. End-of-line is an identifier all by itself.
  88. */
  89. static char array[200] ;
  90. register int c ;
  91. register char *cc ;
  92. do {
  93. c=readchar() ;
  94. } while ( c==' ' || c=='\t' ) ;
  95. for ( cc=array ; cc<&array[(sizeof array) - 1] ; cc++ ) {
  96. if ( c=='#' ) {
  97. do {
  98. c=readchar();
  99. } while ( c!='\n' && c!=EOF ) ;
  100. }
  101. *cc = c ;
  102. if ( c=='\n' && cc==array ) break ;
  103. c=readchar() ;
  104. if ( c=='\n' ) {
  105. pushback(c) ;
  106. break ;
  107. }
  108. if ( c==' ' || c=='\t' || c==EOF ) break ;
  109. }
  110. *++cc=0 ;
  111. return array ;
  112. }
  113. int getmnem(str) char *str ; {
  114. char (*ptr)[4] ;
  115. for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem-sp_fmnem][0] ; ptr++ ) {
  116. if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ;
  117. }
  118. error("Illegal mnemonic") ;
  119. return 0 ;
  120. }
  121. error(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
  122. if ( !atend ) fprintf(stderr,"line %d: ",line) ;
  123. fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
  124. fprintf(stderr,"\n");
  125. nerror++ ;
  126. }
  127. mess(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
  128. if ( !atend ) fprintf(stderr,"line %d: ",line) ;
  129. fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
  130. fprintf(stderr,"\n");
  131. }
  132. fatal(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
  133. error(str,a1,a2,a3,a4,a5,a6) ;
  134. exit(1) ;
  135. }
  136. #define ILLGL -1
  137. check(val) int val ; {
  138. if ( val!=ILLGL ) error("Illegal flag combination") ;
  139. }
  140. int decflag(str) char *str ; {
  141. int type ;
  142. int escape ;
  143. int range ;
  144. int wordm ;
  145. int notzero ;
  146. type=escape=range=wordm=notzero= ILLGL ;
  147. while ( *str ) switch ( *str++ ) {
  148. case 'm' :
  149. check(type) ; type=OPMINI ; break ;
  150. case 's' :
  151. check(type) ; type=OPSHORT ; break ;
  152. case '-' :
  153. check(type) ; type=OPNO ; break ;
  154. case '1' :
  155. check(type) ; type=OP8 ; break ;
  156. case '2' :
  157. check(type) ; type=OP16 ; break ;
  158. case '4' :
  159. check(type) ; type=OP32 ; break ;
  160. case '8' :
  161. check(type) ; type=OP64 ; break ;
  162. case 'u':
  163. check(type) ; type=OP16U ; break ;
  164. case 'e' :
  165. check(escape) ; escape=0 ; break ;
  166. case 'N' :
  167. check(range) ; range= 2 ; break ;
  168. case 'P' :
  169. check(range) ; range= 1 ; break ;
  170. case 'w' :
  171. check(wordm) ; wordm=0 ; break ;
  172. case 'o' :
  173. check(notzero) ; notzero=0 ; break ;
  174. default :
  175. error("Unknown flag") ;
  176. }
  177. if ( type==ILLGL ) error("Type must be specified") ;
  178. switch ( type ) {
  179. case OP64 :
  180. case OP32 :
  181. if ( escape!=ILLGL ) error("Conflicting escapes") ;
  182. escape=ILLGL ;
  183. case OP16 :
  184. case OP16U :
  185. case OP8 :
  186. case OPSHORT :
  187. case OPNO :
  188. if ( notzero!=ILLGL ) mess("Improbable OPNZ") ;
  189. if ( type==OPNO && range!=ILLGL ) {
  190. mess("No operand in range") ;
  191. }
  192. }
  193. if ( escape!=ILLGL ) type|=OPESC ;
  194. if ( wordm!=ILLGL ) type|=OPWORD ;
  195. switch ( range) {
  196. case ILLGL : type|=OP_BOTH ;
  197. if ( type==OPMINI || type==OPSHORT )
  198. error("Minies and shorties must have P or N") ;
  199. break ;
  200. case 1 : type|=OP_POS ; break ;
  201. case 2 : type|=OP_NEG ; break ;
  202. }
  203. if ( notzero!=ILLGL ) type|=OPNZ ;
  204. return type ;
  205. }
  206. writeout() {
  207. register struct opform *next ;
  208. int elem[sp_lmnem-sp_fmnem+1+1] ;
  209. /* for each op points to first of descr. */
  210. register int i,currop ;
  211. int nch ;
  212. int compare() ;
  213. qsort(intable,(lastform-intable)+1,sizeof intable[0],compare) ;
  214. printf("int\tmaxinsl\t= %d ;\n",maxinsl) ;
  215. currop= -1 ; nch=0 ;
  216. printf("char opchoice[] = {\n") ;
  217. for (next=intable ; next<=lastform ; next++ ) {
  218. if ( (next->i_opcode&0377)!=currop ) {
  219. for ( currop++ ;
  220. currop<(next->i_opcode&0377) ; currop++ ) {
  221. elem[currop]= nch ;
  222. error("Missing opcode %s",em_mnem[currop]) ;
  223. }
  224. elem[currop]= nch ;
  225. }
  226. printf("%d, %d,",next->i_flag&0377,next->i_low&0377) ;
  227. nch+=2 ;
  228. switch ( next->i_flag&OPTYPE ) {
  229. case OPMINI :
  230. case OPSHORT :
  231. printf("%d,",next->i_num&0377) ; nch++ ;
  232. }
  233. printf("\n") ;
  234. }
  235. for ( currop++ ; currop<=sp_lmnem-sp_fmnem ; currop++ ) {
  236. elem[currop]= nch ;
  237. error("Missing opcode %s",em_mnem[currop]) ;
  238. }
  239. elem[sp_lmnem-sp_fmnem+1]=nch ;
  240. printf("0 } ;\n\nchar *opindex[] = {\n");
  241. for ( i=0 ; i<=sp_lmnem-sp_fmnem+1 ; i++ ) {
  242. printf(" &opchoice[%d],\n",elem[i]) ;
  243. }
  244. printf("} ;\n") ;
  245. }
  246. int compare(a,b) struct opform *a,*b ; {
  247. if ( a->i_opcode!=b->i_opcode ) {
  248. return (a->i_opcode&0377)-(b->i_opcode&0377) ;
  249. }
  250. return oplength(a)-oplength(b) ;
  251. }
  252. int oplength(a) struct opform *a ; {
  253. int cnt ;
  254. cnt=1 ;
  255. if ( a->i_flag&OPESC ) cnt++ ;
  256. switch( a->i_flag&OPTYPE ) {
  257. case OPNO :
  258. case OPMINI : break ;
  259. case OP8 :
  260. case OPSHORT : cnt++ ; break ;
  261. case OP16U :
  262. case OP16 : cnt+=2 ; break ;
  263. case OP32 : cnt+=5 ; break ;
  264. case OP64 : cnt+=9 ; break ;
  265. }
  266. return cnt ;
  267. }
  268. /* ----------- checking --------------*/
  269. int ecodes[256],codes[256],lcodes[256] ;
  270. #define NMNEM (sp_lmnem-sp_fmnem+1)
  271. #define MUST 1
  272. #define MAY 2
  273. #define FORB 3
  274. char negc[NMNEM], zc[NMNEM], posc[NMNEM] ;
  275. checkall() {
  276. register i,flag ;
  277. register struct opform *next ;
  278. int opc,low ;
  279. for ( i=0 ; i<NMNEM ; i++ ) negc[i]=zc[i]=posc[i]=0 ;
  280. for ( i=0 ; i<256 ; i++ ) lcodes[i]= codes[i]= ecodes[i]= -1 ;
  281. codes[254]=codes[255]=ESCAP;
  282. atend=0 ; line=0 ;
  283. for ( next=intable ; next<=lastform ; next++ ) {
  284. line++ ;
  285. flag = next->i_flag&0377 ;
  286. opc = next->i_opcode&0377 ;
  287. low = next->i_low&0377 ;
  288. chkc(flag,low,opc) ;
  289. switch(flag&OPTYPE) {
  290. case OPNO : zc[opc]++ ; break ;
  291. case OPMINI :
  292. case OPSHORT :
  293. for ( i=1 ; i<((next->i_num)&0377) ; i++ ) {
  294. chkc(flag,low+i,opc) ;
  295. }
  296. if ( !(em_flag[opc]&PAR_G) &&
  297. (flag&OPRANGE)==OP_BOTH) {
  298. mess("Mini's and shorties should have P or N");
  299. }
  300. break ;
  301. case OP8 :
  302. error("OP8 is removed") ;
  303. break ;
  304. case OP16 :
  305. if ( flag&OP_NEG )
  306. negc[opc]++ ;
  307. else if ( flag&OP_POS )
  308. posc[opc]++ ;
  309. break ;
  310. case OP16U :
  311. case OP32 :
  312. case OP64 :
  313. break ;
  314. default :
  315. error("Illegal type") ;
  316. break ;
  317. }
  318. }
  319. atend=1 ;
  320. for ( i=0 ; i<256 ; i++ ) if ( codes[i]== -1 ) {
  321. mess("interpreter opcode %d not used",i) ;
  322. }
  323. for ( opc=0 ; opc<NMNEM ; opc++ ) {
  324. switch(em_flag[opc]&EM_PAR) {
  325. case PAR_NO :
  326. ckop(opc,MUST,FORB,FORB) ;
  327. break ;
  328. case PAR_C:
  329. case PAR_D:
  330. case PAR_F:
  331. case PAR_B:
  332. ckop(opc,FORB,MAY,MAY) ;
  333. break ;
  334. case PAR_N:
  335. case PAR_G:
  336. case PAR_S:
  337. case PAR_Z:
  338. case PAR_O:
  339. case PAR_P:
  340. ckop(opc,FORB,MAY,FORB) ;
  341. break ;
  342. case PAR_R:
  343. ckop(opc,FORB,MAY,FORB) ;
  344. break ;
  345. case PAR_L:
  346. ckop(opc,FORB,MUST,MUST) ;
  347. break ;
  348. case PAR_W:
  349. ckop(opc,MUST,MAY,FORB) ;
  350. break ;
  351. default :
  352. error("Unknown instruction type of %s",ename(opc)) ;
  353. break ;
  354. }
  355. }
  356. }
  357. chkc(flag,icode,emc) {
  358. if ( flag&OPESC ) {
  359. if ( ecodes[icode]!=-1 ) {
  360. mess("Escaped opcode %d used by %s and %s",
  361. icode,ename(emc),ename(ecodes[icode])) ;
  362. }
  363. ecodes[icode]=emc;
  364. } else switch ( flag&OPTYPE ) {
  365. default:
  366. if ( codes[icode]!=-1 ) {
  367. mess("Opcode %d used by %s and %s",
  368. icode,ename(emc),ename(codes[icode])) ;
  369. }
  370. codes[icode]=emc;
  371. break ;
  372. case OP32:
  373. case OP64:
  374. if ( lcodes[icode]!=-1 ) {
  375. mess("Long opcode %d used by %s and %s",
  376. icode,ename(emc),ename(codes[icode])) ;
  377. }
  378. lcodes[icode]=emc;
  379. break ;
  380. }
  381. }
  382. ckop(emc,zf,pf,nf) {
  383. if ( zc[emc]>1 ) mess("More then one OPNO for %s",ename(emc)) ;
  384. if ( posc[emc]>1 ) mess("More then one OP16(pos) for %s",ename(emc)) ;
  385. if ( negc[emc]>1 ) mess("More then one OP16(neg) for %s",ename(emc)) ;
  386. switch(zf) {
  387. case MUST:
  388. if ( zc[emc]==0 ) mess("No OPNO for %s",ename(emc)) ;
  389. break ;
  390. case FORB:
  391. if ( zc[emc]==1 ) mess("Forbidden OPNO for %s",ename(emc)) ;
  392. break ;
  393. }
  394. switch(pf) {
  395. case MUST:
  396. if ( posc[emc]==0 ) mess("No OP16(pos) for %s",ename(emc)) ;
  397. break ;
  398. case FORB:
  399. if ( posc[emc]==1 )
  400. mess("Forbidden OP16(pos) for %s",ename(emc)) ;
  401. break ;
  402. }
  403. switch(nf) {
  404. case MUST:
  405. if ( negc[emc]==0 ) mess("No OP16(neg) for %s",ename(emc)) ;
  406. break ;
  407. case FORB:
  408. if ( negc[emc]==1 )
  409. mess("Forbidden OP16(neg) for %s",ename(emc)) ;
  410. break ;
  411. }
  412. }
  413. static int pushchar ;
  414. static int pushf ;
  415. int readchar() {
  416. int c ;
  417. if ( pushf ) {
  418. pushf=0 ;
  419. c = pushchar ;
  420. } else {
  421. if ( feof(stdin) ) return EOF ;
  422. c=getc(stdin) ;
  423. }
  424. if ( c=='\n' ) line++ ;
  425. return c ;
  426. }
  427. pushback(c) {
  428. if ( pushf ) {
  429. fatal("Double pushback") ;
  430. }
  431. pushf++ ;
  432. pushchar=c ;
  433. if ( c=='\n' ) line-- ;
  434. }