Commit | Line | Data |
---|---|---|
80dbc321 BJ |
1 | /* INTERMEDIATE CODE GENERATION FOR S C JOHNSON C COMPILERS */ |
2 | /* NEW VERSION USING BINARY POLISH POSTFIX INTERMEDIATE */ | |
3 | #if FAMILY != SCJ | |
4 | WRONG put FULE !!!! | |
5 | #endif | |
6 | ||
7 | #include "defs" | |
8 | #include "scjdefs" | |
9 | struct Addrblock *imagpart(); | |
10 | ||
11 | #define FOUR 4 | |
12 | extern int ops2[]; | |
13 | extern int types2[]; | |
14 | ||
15 | #define P2BUFFMAX 128 | |
16 | static long int p2buff[P2BUFFMAX]; | |
17 | static long int *p2bufp = &p2buff[0]; | |
18 | static long int *p2bufend = &p2buff[P2BUFFMAX]; | |
19 | ||
20 | ||
21 | puthead(s, class) | |
22 | char *s; | |
23 | int class; | |
24 | { | |
25 | char buff[100]; | |
26 | #if TARGET == VAX | |
27 | if(s) | |
28 | p2ps("\t.globl\t_%s", s); | |
29 | #endif | |
30 | /* put out fake copy of left bracket line, to be redone later */ | |
31 | if( ! headerdone ) | |
32 | { | |
33 | #if FAMILY==SCJ && OUTPUT==BINARY | |
34 | p2flush(); | |
35 | #endif | |
36 | headoffset = ftell(textfile); | |
37 | prhead(textfile); | |
38 | headerdone = YES; | |
39 | p2triple(P2STMT, (strlen(infname)+FOUR-1)/FOUR, 0); | |
40 | p2str(infname); | |
41 | #if TARGET == PDP11 | |
42 | /* fake jump to start the optimizer */ | |
43 | if(class != CLBLOCK) | |
44 | putgoto( fudgelabel = newlabel() ); | |
45 | #endif | |
46 | } | |
47 | } | |
48 | ||
49 | ||
50 | ||
51 | ||
52 | ||
53 | /* It is necessary to precede each procedure with a "left bracket" | |
54 | * line that tells pass 2 how many register variables and how | |
55 | * much automatic space is required for the function. This compiler | |
56 | * does not know how much automatic space is needed until the | |
57 | * entire procedure has been processed. Therefore, "puthead" | |
58 | * is called at the begining to record the current location in textfile, | |
59 | * then to put out a placeholder left bracket line. This procedure | |
60 | * repositions the file and rewrites that line, then puts the | |
61 | * file pointer back to the end of the file. | |
62 | */ | |
63 | ||
64 | putbracket() | |
65 | { | |
66 | long int hereoffset; | |
67 | ||
68 | #if FAMILY==SCJ && OUTPUT==BINARY | |
69 | p2flush(); | |
70 | #endif | |
71 | hereoffset = ftell(textfile); | |
72 | if(fseek(textfile, headoffset, 0)) | |
73 | fatal("fseek failed"); | |
74 | prhead(textfile); | |
75 | if(fseek(textfile, hereoffset, 0)) | |
76 | fatal("fseek failed 2"); | |
77 | } | |
78 | ||
79 | ||
80 | ||
81 | ||
82 | putrbrack(k) | |
83 | int k; | |
84 | { | |
85 | p2op(P2RBRACKET, k); | |
86 | } | |
87 | ||
88 | ||
89 | ||
90 | putnreg() | |
91 | { | |
92 | } | |
93 | ||
94 | ||
95 | ||
96 | ||
97 | ||
98 | ||
99 | puteof() | |
100 | { | |
101 | p2op(P2EOF, 0); | |
102 | p2flush(); | |
103 | } | |
104 | ||
105 | ||
106 | ||
107 | putstmt() | |
108 | { | |
109 | p2triple(P2STMT, 0, lineno); | |
110 | } | |
111 | ||
112 | ||
113 | ||
114 | ||
115 | /* put out code for if( ! p) goto l */ | |
116 | putif(p,l) | |
117 | register expptr p; | |
118 | int l; | |
119 | { | |
120 | register int k; | |
121 | ||
122 | if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL) | |
123 | { | |
124 | if(k != TYERROR) | |
125 | err("non-logical expression in IF statement"); | |
126 | frexpr(p); | |
127 | } | |
128 | else | |
129 | { | |
130 | putex1(p); | |
131 | p2icon( (long int) l , P2INT); | |
132 | p2op(P2CBRANCH, 0); | |
133 | putstmt(); | |
134 | } | |
135 | } | |
136 | ||
137 | ||
138 | ||
139 | ||
140 | ||
141 | /* put out code for goto l */ | |
142 | putgoto(label) | |
143 | int label; | |
144 | { | |
145 | p2triple(P2GOTO, 1, label); | |
146 | putstmt(); | |
147 | } | |
148 | ||
149 | ||
150 | /* branch to address constant or integer variable */ | |
151 | putbranch(p) | |
152 | register struct Addrblock *p; | |
153 | { | |
154 | putex1(p); | |
155 | p2op(P2GOTO, P2INT); | |
156 | putstmt(); | |
157 | } | |
158 | ||
159 | ||
160 | ||
161 | /* put out label l: */ | |
162 | putlabel(label) | |
163 | int label; | |
164 | { | |
165 | p2op(P2LABEL, label); | |
166 | } | |
167 | ||
168 | ||
169 | ||
170 | ||
171 | putexpr(p) | |
172 | expptr p; | |
173 | { | |
174 | putex1(p); | |
175 | putstmt(); | |
176 | } | |
177 | ||
178 | ||
179 | ||
180 | ||
181 | putcmgo(index, nlab, labs) | |
182 | expptr index; | |
183 | int nlab; | |
184 | struct Labelblock *labs[]; | |
185 | { | |
186 | int i, labarray, skiplabel; | |
187 | ||
188 | if(! ISINT(index->headblock.vtype) ) | |
189 | { | |
190 | execerr("computed goto index must be integer", NULL); | |
191 | return; | |
192 | } | |
193 | ||
194 | #if TARGET == VAX | |
195 | /* use special case instruction */ | |
196 | vaxgoto(index, nlab, labs); | |
197 | #else | |
198 | labarray = newlabel(); | |
199 | preven(ALIADDR); | |
200 | prlabel(asmfile, labarray); | |
201 | prcona(asmfile, (ftnint) (skiplabel = newlabel()) ); | |
202 | for(i = 0 ; i < nlab ; ++i) | |
203 | if( labs[i] ) | |
204 | prcona(asmfile, (ftnint)(labs[i]->labelno) ); | |
205 | prcmgoto(index, nlab, skiplabel, labarray); | |
206 | putlabel(skiplabel); | |
207 | #endif | |
208 | } | |
209 | \f | |
210 | putx(p) | |
211 | expptr p; | |
212 | { | |
213 | struct Addrblock *putcall(), *putcx1(), *realpart(); | |
214 | char *memname(); | |
215 | int opc; | |
216 | int ncomma; | |
217 | int type, k; | |
218 | ||
219 | switch(p->headblock.tag) | |
220 | { | |
221 | case TERROR: | |
222 | free(p); | |
223 | break; | |
224 | ||
225 | case TCONST: | |
226 | switch(type = p->constblock.vtype) | |
227 | { | |
228 | case TYLOGICAL: | |
229 | type = tyint; | |
230 | case TYLONG: | |
231 | case TYSHORT: | |
232 | p2icon(p->constblock.const.ci, types2[type]); | |
233 | free(p); | |
234 | break; | |
235 | ||
236 | case TYADDR: | |
237 | p2triple(P2ICON, 1, P2INT|P2PTR); | |
238 | p2word(0L); | |
239 | p2name(memname(STGCONST, (int) p->constblock.const.ci) ); | |
240 | free(p); | |
241 | break; | |
242 | ||
243 | default: | |
244 | putx( putconst(p) ); | |
245 | break; | |
246 | } | |
247 | break; | |
248 | ||
249 | case TEXPR: | |
250 | switch(opc = p->exprblock.opcode) | |
251 | { | |
252 | case OPCALL: | |
253 | case OPCCALL: | |
254 | if( ISCOMPLEX(p->exprblock.vtype) ) | |
255 | putcxop(p); | |
256 | else putcall(p); | |
257 | break; | |
258 | ||
259 | case OPMIN: | |
260 | case OPMAX: | |
261 | putmnmx(p); | |
262 | break; | |
263 | ||
264 | ||
265 | case OPASSIGN: | |
266 | if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) || | |
267 | ISCOMPLEX(p->exprblock.rightp->headblock.vtype) ) | |
268 | frexpr( putcxeq(p) ); | |
269 | else if( ISCHAR(p) ) | |
270 | putcheq(p); | |
271 | else | |
272 | goto putopp; | |
273 | break; | |
274 | ||
275 | case OPEQ: | |
276 | case OPNE: | |
277 | if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) || | |
278 | ISCOMPLEX(p->exprblock.rightp->headblock.vtype) ) | |
279 | { | |
280 | putcxcmp(p); | |
281 | break; | |
282 | } | |
283 | case OPLT: | |
284 | case OPLE: | |
285 | case OPGT: | |
286 | case OPGE: | |
287 | if(ISCHAR(p->exprblock.leftp)) | |
288 | putchcmp(p); | |
289 | else | |
290 | goto putopp; | |
291 | break; | |
292 | ||
293 | case OPPOWER: | |
294 | putpower(p); | |
295 | break; | |
296 | ||
297 | case OPSTAR: | |
298 | #if FAMILY == SCJ | |
299 | /* m * (2**k) -> m<<k */ | |
300 | if(INT(p->exprblock.leftp->headblock.vtype) && | |
301 | ISICON(p->exprblock.rightp) && | |
302 | ( (k = log2(p->exprblock.rightp->constblock.const.ci))>0) ) | |
303 | { | |
304 | p->exprblock.opcode = OPLSHIFT; | |
305 | frexpr(p->exprblock.rightp); | |
306 | p->exprblock.rightp = ICON(k); | |
307 | goto putopp; | |
308 | } | |
309 | #endif | |
310 | ||
311 | case OPMOD: | |
312 | goto putopp; | |
313 | case OPPLUS: | |
314 | case OPMINUS: | |
315 | case OPSLASH: | |
316 | case OPNEG: | |
317 | if( ISCOMPLEX(p->exprblock.vtype) ) | |
318 | putcxop(p); | |
319 | else goto putopp; | |
320 | break; | |
321 | ||
322 | case OPCONV: | |
323 | if( ISCOMPLEX(p->exprblock.vtype) ) | |
324 | putcxop(p); | |
325 | else if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) ) | |
326 | { | |
327 | ncomma = 0; | |
328 | putx( mkconv(p->exprblock.vtype, | |
329 | realpart(putcx1(p->exprblock.leftp, &ncomma)))); | |
330 | putcomma(ncomma, p->exprblock.vtype, NO); | |
331 | free(p); | |
332 | } | |
333 | else goto putopp; | |
334 | break; | |
335 | ||
336 | case OPNOT: | |
337 | case OPOR: | |
338 | case OPAND: | |
339 | case OPEQV: | |
340 | case OPNEQV: | |
341 | case OPADDR: | |
342 | case OPPLUSEQ: | |
343 | case OPSTAREQ: | |
344 | case OPCOMMA: | |
345 | case OPQUEST: | |
346 | case OPCOLON: | |
347 | case OPBITOR: | |
348 | case OPBITAND: | |
349 | case OPBITXOR: | |
350 | case OPBITNOT: | |
351 | case OPLSHIFT: | |
352 | case OPRSHIFT: | |
353 | putopp: | |
354 | putop(p); | |
355 | break; | |
356 | ||
357 | default: | |
358 | fatali("putx: invalid opcode %d", opc); | |
359 | } | |
360 | break; | |
361 | ||
362 | case TADDR: | |
363 | putaddr(p, YES); | |
364 | break; | |
365 | ||
366 | default: | |
367 | fatali("putx: impossible tag %d", p->headblock.tag); | |
368 | } | |
369 | } | |
370 | ||
371 | ||
372 | ||
373 | LOCAL putop(p) | |
374 | expptr p; | |
375 | { | |
376 | int k; | |
377 | expptr lp, tp; | |
378 | int pt, lt; | |
379 | int comma; | |
380 | ||
381 | switch(p->exprblock.opcode) /* check for special cases and rewrite */ | |
382 | { | |
383 | case OPCONV: | |
384 | pt = p->exprblock.vtype; | |
385 | lp = p->exprblock.leftp; | |
386 | lt = lp->headblock.vtype; | |
387 | while(p->headblock.tag==TEXPR && | |
388 | p->exprblock.opcode==OPCONV && | |
389 | ( (ISREAL(pt)&&ISREAL(lt)) || | |
390 | (INT(pt)&&(ONEOF(lt,MSKINT|MSKADDR|MSKCHAR|M(TYSUBR)))) )) | |
391 | { | |
392 | #if SZINT < SZLONG | |
393 | if(lp->headblock.tag != TEXPR) | |
394 | { | |
395 | if(pt==TYINT && lt==TYLONG) | |
396 | break; | |
397 | if(lt==TYINT && pt==TYLONG) | |
398 | break; | |
399 | } | |
400 | #endif | |
401 | ||
402 | #if TARGET == VAX | |
403 | if(pt==TYDREAL && lt==TYREAL) | |
404 | break; | |
405 | #endif | |
406 | ||
407 | if(lt==TYCHAR && lp->headblock.tag==TEXPR && | |
408 | lp->exprblock.opcode==OPCALL) | |
409 | { | |
410 | p->exprblock.leftp = putcall(lp); | |
411 | putop(p); | |
412 | putcomma(1, pt, NO); | |
413 | free(p); | |
414 | return; | |
415 | } | |
416 | free(p); | |
417 | p = lp; | |
418 | pt = lt; | |
419 | lp = p->exprblock.leftp; | |
420 | lt = lp->headblock.vtype; | |
421 | } | |
422 | if(p->headblock.tag==TEXPR && p->exprblock.opcode==OPCONV) | |
423 | break; | |
424 | putx(p); | |
425 | return; | |
426 | ||
427 | case OPADDR: | |
428 | comma = NO; | |
429 | lp = p->exprblock.leftp; | |
430 | if(lp->headblock.tag != TADDR) | |
431 | { | |
432 | tp = mktemp(lp->headblock.vtype, lp->headblock.vleng); | |
433 | putx( mkexpr(OPASSIGN, cpexpr(tp), lp) ); | |
434 | lp = tp; | |
435 | comma = YES; | |
436 | } | |
437 | putaddr(lp, NO); | |
438 | if(comma) | |
439 | putcomma(1, TYINT, NO); | |
440 | free(p); | |
441 | return; | |
442 | } | |
443 | ||
444 | if( (k = ops2[p->exprblock.opcode]) <= 0) | |
445 | fatali("putop: invalid opcode %d", p->exprblock.opcode); | |
446 | putx(p->exprblock.leftp); | |
447 | if(p->exprblock.rightp) | |
448 | putx(p->exprblock.rightp); | |
449 | p2op(k, types2[p->exprblock.vtype]); | |
450 | ||
451 | if(p->exprblock.vleng) | |
452 | frexpr(p->exprblock.vleng); | |
453 | free(p); | |
454 | } | |
455 | \f | |
456 | putforce(t, p) | |
457 | int t; | |
458 | expptr p; | |
459 | { | |
460 | p = mkconv(t, fixtype(p)); | |
461 | putx(p); | |
462 | p2op(P2FORCE, | |
463 | (t==TYSHORT ? P2SHORT : (t==TYLONG ? P2LONG : P2DREAL)) ); | |
464 | putstmt(); | |
465 | } | |
466 | ||
467 | ||
468 | ||
469 | LOCAL putpower(p) | |
470 | expptr p; | |
471 | { | |
472 | expptr base; | |
473 | struct Addrblock *t1, *t2; | |
474 | ftnint k; | |
475 | int type; | |
476 | int ncomma; | |
477 | ||
478 | if(!ISICON(p->exprblock.rightp) || | |
479 | (k = p->exprblock.rightp->constblock.const.ci)<2) | |
480 | fatal("putpower: bad call"); | |
481 | base = p->exprblock.leftp; | |
482 | type = base->headblock.vtype; | |
483 | t1 = mktemp(type, NULL); | |
484 | t2 = NULL; | |
485 | ncomma = 1; | |
486 | putassign(cpexpr(t1), cpexpr(base) ); | |
487 | ||
488 | for( ; (k&1)==0 && k>2 ; k>>=1 ) | |
489 | { | |
490 | ++ncomma; | |
491 | putsteq(t1, t1); | |
492 | } | |
493 | ||
494 | if(k == 2) | |
495 | putx( mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) ); | |
496 | else | |
497 | { | |
498 | t2 = mktemp(type, NULL); | |
499 | ++ncomma; | |
500 | putassign(cpexpr(t2), cpexpr(t1)); | |
501 | ||
502 | for(k>>=1 ; k>1 ; k>>=1) | |
503 | { | |
504 | ++ncomma; | |
505 | putsteq(t1, t1); | |
506 | if(k & 1) | |
507 | { | |
508 | ++ncomma; | |
509 | putsteq(t2, t1); | |
510 | } | |
511 | } | |
512 | putx( mkexpr(OPSTAR, cpexpr(t2), | |
513 | mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) )); | |
514 | } | |
515 | putcomma(ncomma, type, NO); | |
516 | frexpr(t1); | |
517 | if(t2) | |
518 | frexpr(t2); | |
519 | frexpr(p); | |
520 | } | |
521 | ||
522 | ||
523 | ||
524 | ||
525 | LOCAL struct Addrblock *intdouble(p, ncommap) | |
526 | struct Addrblock *p; | |
527 | int *ncommap; | |
528 | { | |
529 | register struct Addrblock *t; | |
530 | ||
531 | t = mktemp(TYDREAL, NULL); | |
532 | ++*ncommap; | |
533 | putassign(cpexpr(t), p); | |
534 | return(t); | |
535 | } | |
536 | ||
537 | ||
538 | ||
539 | ||
540 | ||
541 | LOCAL putcxeq(p) | |
542 | register struct Exprblock *p; | |
543 | { | |
544 | register struct Addrblock *lp, *rp; | |
545 | int ncomma; | |
546 | ||
547 | ncomma = 0; | |
548 | lp = putcx1(p->leftp, &ncomma); | |
549 | rp = putcx1(p->rightp, &ncomma); | |
550 | putassign(realpart(lp), realpart(rp)); | |
551 | if( ISCOMPLEX(p->vtype) ) | |
552 | { | |
553 | ++ncomma; | |
554 | putassign(imagpart(lp), imagpart(rp)); | |
555 | } | |
556 | putcomma(ncomma, TYREAL, NO); | |
557 | frexpr(rp); | |
558 | free(p); | |
559 | return(lp); | |
560 | } | |
561 | ||
562 | ||
563 | ||
564 | LOCAL putcxop(p) | |
565 | expptr p; | |
566 | { | |
567 | struct Addrblock *putcx1(); | |
568 | int ncomma; | |
569 | ||
570 | ncomma = 0; | |
571 | putaddr( putcx1(p, &ncomma), NO); | |
572 | putcomma(ncomma, TYINT, NO); | |
573 | } | |
574 | ||
575 | ||
576 | ||
577 | LOCAL struct Addrblock *putcx1(p, ncommap) | |
578 | register expptr p; | |
579 | int *ncommap; | |
580 | { | |
581 | struct Addrblock *q, *lp, *rp; | |
582 | register struct Addrblock *resp; | |
583 | int opcode; | |
584 | int ltype, rtype; | |
585 | struct Constblock *mkrealcon(); | |
586 | ||
587 | if(p == NULL) | |
588 | return(NULL); | |
589 | ||
590 | switch(p->headblock.tag) | |
591 | { | |
592 | case TCONST: | |
593 | if( ISCOMPLEX(p->constblock.vtype) ) | |
594 | p = putconst(p); | |
595 | return( p ); | |
596 | ||
597 | case TADDR: | |
598 | if( ! addressable(p) ) | |
599 | { | |
600 | ++*ncommap; | |
601 | resp = mktemp(tyint, NULL); | |
602 | putassign( cpexpr(resp), p->addrblock.memoffset ); | |
603 | p->addrblock.memoffset = resp; | |
604 | } | |
605 | return( p ); | |
606 | ||
607 | case TEXPR: | |
608 | if( ISCOMPLEX(p->exprblock.vtype) ) | |
609 | break; | |
610 | ++*ncommap; | |
611 | resp = mktemp(TYDREAL, NO); | |
612 | putassign( cpexpr(resp), p); | |
613 | return(resp); | |
614 | ||
615 | default: | |
616 | fatali("putcx1: bad tag %d", p->headblock.tag); | |
617 | } | |
618 | ||
619 | opcode = p->exprblock.opcode; | |
620 | if(opcode==OPCALL || opcode==OPCCALL) | |
621 | { | |
622 | ++*ncommap; | |
623 | return( putcall(p) ); | |
624 | } | |
625 | else if(opcode == OPASSIGN) | |
626 | { | |
627 | ++*ncommap; | |
628 | return( putcxeq(p) ); | |
629 | } | |
630 | resp = mktemp(p->exprblock.vtype, NULL); | |
631 | if(lp = putcx1(p->exprblock.leftp, ncommap) ) | |
632 | ltype = lp->headblock.vtype; | |
633 | if(rp = putcx1(p->headblock.rightp, ncommap) ) | |
634 | rtype = rp->headblock.vtype; | |
635 | ||
636 | switch(opcode) | |
637 | { | |
638 | case OPCOMMA: | |
639 | frexpr(resp); | |
640 | resp = rp; | |
641 | rp = NULL; | |
642 | break; | |
643 | ||
644 | case OPNEG: | |
645 | putassign( realpart(resp), mkexpr(OPNEG, realpart(lp), NULL) ); | |
646 | putassign( imagpart(resp), mkexpr(OPNEG, imagpart(lp), NULL) ); | |
647 | *ncommap += 2; | |
648 | break; | |
649 | ||
650 | case OPPLUS: | |
651 | case OPMINUS: | |
652 | putassign( realpart(resp), mkexpr(opcode, realpart(lp), realpart(rp) )); | |
653 | if(rtype < TYCOMPLEX) | |
654 | putassign( imagpart(resp), imagpart(lp) ); | |
655 | else if(ltype < TYCOMPLEX) | |
656 | { | |
657 | if(opcode == OPPLUS) | |
658 | putassign( imagpart(resp), imagpart(rp) ); | |
659 | else putassign( imagpart(resp), mkexpr(OPNEG, imagpart(rp), NULL) ); | |
660 | } | |
661 | else | |
662 | putassign( imagpart(resp), mkexpr(opcode, imagpart(lp), imagpart(rp) )); | |
663 | ||
664 | *ncommap += 2; | |
665 | break; | |
666 | ||
667 | case OPSTAR: | |
668 | if(ltype < TYCOMPLEX) | |
669 | { | |
670 | if( ISINT(ltype) ) | |
671 | lp = intdouble(lp, ncommap); | |
672 | putassign( realpart(resp), mkexpr(OPSTAR, cpexpr(lp), realpart(rp) )); | |
673 | putassign( imagpart(resp), mkexpr(OPSTAR, cpexpr(lp), imagpart(rp) )); | |
674 | } | |
675 | else if(rtype < TYCOMPLEX) | |
676 | { | |
677 | if( ISINT(rtype) ) | |
678 | rp = intdouble(rp, ncommap); | |
679 | putassign( realpart(resp), mkexpr(OPSTAR, cpexpr(rp), realpart(lp) )); | |
680 | putassign( imagpart(resp), mkexpr(OPSTAR, cpexpr(rp), imagpart(lp) )); | |
681 | } | |
682 | else { | |
683 | putassign( realpart(resp), mkexpr(OPMINUS, | |
684 | mkexpr(OPSTAR, realpart(lp), realpart(rp)), | |
685 | mkexpr(OPSTAR, imagpart(lp), imagpart(rp)) )); | |
686 | putassign( imagpart(resp), mkexpr(OPPLUS, | |
687 | mkexpr(OPSTAR, realpart(lp), imagpart(rp)), | |
688 | mkexpr(OPSTAR, imagpart(lp), realpart(rp)) )); | |
689 | } | |
690 | *ncommap += 2; | |
691 | break; | |
692 | ||
693 | case OPSLASH: | |
694 | /* fixexpr has already replaced all divisions | |
695 | * by a complex by a function call | |
696 | */ | |
697 | if( ISINT(rtype) ) | |
698 | rp = intdouble(rp, ncommap); | |
699 | putassign( realpart(resp), mkexpr(OPSLASH, realpart(lp), cpexpr(rp)) ); | |
700 | putassign( imagpart(resp), mkexpr(OPSLASH, imagpart(lp), cpexpr(rp)) ); | |
701 | *ncommap += 2; | |
702 | break; | |
703 | ||
704 | case OPCONV: | |
705 | putassign( realpart(resp), realpart(lp) ); | |
706 | if( ISCOMPLEX(lp->vtype) ) | |
707 | q = imagpart(lp); | |
708 | else if(rp != NULL) | |
709 | q = realpart(rp); | |
710 | else | |
711 | q = mkrealcon(TYDREAL, 0.0); | |
712 | putassign( imagpart(resp), q); | |
713 | *ncommap += 2; | |
714 | break; | |
715 | ||
716 | default: | |
717 | fatali("putcx1 of invalid opcode %d", opcode); | |
718 | } | |
719 | ||
720 | frexpr(lp); | |
721 | frexpr(rp); | |
722 | free(p); | |
723 | return(resp); | |
724 | } | |
725 | ||
726 | ||
727 | ||
728 | ||
729 | LOCAL putcxcmp(p) | |
730 | register struct Exprblock *p; | |
731 | { | |
732 | int opcode; | |
733 | int ncomma; | |
734 | register struct Addrblock *lp, *rp; | |
735 | struct Exprblock *q; | |
736 | ||
737 | ncomma = 0; | |
738 | opcode = p->opcode; | |
739 | lp = putcx1(p->leftp, &ncomma); | |
740 | rp = putcx1(p->rightp, &ncomma); | |
741 | ||
742 | q = mkexpr( opcode==OPEQ ? OPAND : OPOR , | |
743 | mkexpr(opcode, realpart(lp), realpart(rp)), | |
744 | mkexpr(opcode, imagpart(lp), imagpart(rp)) ); | |
745 | putx( fixexpr(q) ); | |
746 | putcomma(ncomma, TYINT, NO); | |
747 | ||
748 | free(lp); | |
749 | free(rp); | |
750 | free(p); | |
751 | } | |
752 | \f | |
753 | LOCAL struct Addrblock *putch1(p, ncommap) | |
754 | register expptr p; | |
755 | int * ncommap; | |
756 | { | |
757 | register struct Addrblock *t; | |
758 | struct Addrblock *mktemp(), *putconst(); | |
759 | ||
760 | switch(p->headblock.tag) | |
761 | { | |
762 | case TCONST: | |
763 | return( putconst(p) ); | |
764 | ||
765 | case TADDR: | |
766 | return(p); | |
767 | ||
768 | case TEXPR: | |
769 | ++*ncommap; | |
770 | ||
771 | switch(p->exprblock.opcode) | |
772 | { | |
773 | case OPCALL: | |
774 | case OPCCALL: | |
775 | t = putcall(p); | |
776 | break; | |
777 | ||
778 | case OPCONCAT: | |
779 | t = mktemp(TYCHAR, cpexpr(p->exprblock.vleng) ); | |
780 | putcat( cpexpr(t), p ); | |
781 | break; | |
782 | ||
783 | case OPCONV: | |
784 | if(!ISICON(p->exprblock.vleng) | |
785 | || p->exprblock.vleng->constblock.const.ci!=1 | |
786 | || ! INT(p->exprblock.leftp->headblock.vtype) ) | |
787 | fatal("putch1: bad character conversion"); | |
788 | t = mktemp(TYCHAR, ICON(1) ); | |
789 | putop( mkexpr(OPASSIGN, cpexpr(t), p) ); | |
790 | break; | |
791 | default: | |
792 | fatali("putch1: invalid opcode %d", | |
793 | p->exprblock.opcode); | |
794 | } | |
795 | return(t); | |
796 | ||
797 | default: | |
798 | fatali("putch1: bad tag %d", p->tag); | |
799 | } | |
800 | /* NOTREACHED */ | |
801 | } | |
802 | \f | |
803 | ||
804 | ||
805 | ||
806 | LOCAL putchop(p) | |
807 | expptr p; | |
808 | { | |
809 | int ncomma; | |
810 | ||
811 | ncomma = 0; | |
812 | putaddr( putch1(p, &ncomma) , NO ); | |
813 | putcomma(ncomma, TYCHAR, YES); | |
814 | } | |
815 | ||
816 | ||
817 | ||
818 | ||
819 | LOCAL putcheq(p) | |
820 | register struct Exprblock *p; | |
821 | { | |
822 | int ncomma; | |
823 | ||
824 | ncomma = 0; | |
825 | if( p->rightp->headblock.tag==TEXPR && p->rightp->exprblock.opcode==OPCONCAT ) | |
826 | putcat(p->leftp, p->rightp); | |
827 | else if( ISONE(p->leftp->headblock.vleng) && ISONE(p->rightp->headblock.vleng) ) | |
828 | { | |
829 | putaddr( putch1(p->leftp, &ncomma) , YES ); | |
830 | putaddr( putch1(p->rightp, &ncomma) , YES ); | |
831 | putcomma(ncomma, TYINT, NO); | |
832 | p2op(P2ASSIGN, P2CHAR); | |
833 | } | |
834 | else | |
835 | { | |
836 | putx( call2(TYINT, "s_copy", p->leftp, p->rightp) ); | |
837 | putcomma(ncomma, TYINT, NO); | |
838 | } | |
839 | ||
840 | frexpr(p->vleng); | |
841 | free(p); | |
842 | } | |
843 | ||
844 | ||
845 | ||
846 | ||
847 | LOCAL putchcmp(p) | |
848 | register struct Exprblock *p; | |
849 | { | |
850 | int ncomma; | |
851 | ||
852 | ncomma = 0; | |
853 | if(ISONE(p->leftp->headblock.vleng) && ISONE(p->rightp->headblock.vleng) ) | |
854 | { | |
855 | putaddr( putch1(p->leftp, &ncomma) , YES ); | |
856 | putaddr( putch1(p->rightp, &ncomma) , YES ); | |
857 | p2op(ops2[p->opcode], P2CHAR); | |
858 | free(p); | |
859 | putcomma(ncomma, TYINT, NO); | |
860 | } | |
861 | else | |
862 | { | |
863 | p->leftp = call2(TYINT,"s_cmp", p->leftp, p->rightp); | |
864 | p->rightp = ICON(0); | |
865 | putop(p); | |
866 | } | |
867 | } | |
868 | ||
869 | ||
870 | ||
871 | ||
872 | ||
873 | LOCAL putcat(lhs, rhs) | |
874 | register struct Addrblock *lhs; | |
875 | register expptr rhs; | |
876 | { | |
877 | int n, ncomma; | |
878 | struct Addrblock *lp, *cp; | |
879 | ||
880 | ncomma = 0; | |
881 | n = ncat(rhs); | |
882 | lp = mktmpn(n, TYLENG, NULL); | |
883 | cp = mktmpn(n, TYADDR, NULL); | |
884 | ||
885 | n = 0; | |
886 | putct1(rhs, lp, cp, &n, &ncomma); | |
887 | ||
888 | putx( call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n)) ) ); | |
889 | putcomma(ncomma, TYINT, NO); | |
890 | } | |
891 | ||
892 | ||
893 | ||
894 | ||
895 | ||
896 | LOCAL ncat(p) | |
897 | register expptr p; | |
898 | { | |
899 | if(p->headblock.tag==TEXPR && p->exprblock.opcode==OPCONCAT) | |
900 | return( ncat(p->exprblock.leftp) + ncat(p->exprblock.rightp) ); | |
901 | else return(1); | |
902 | } | |
903 | ||
904 | ||
905 | ||
906 | ||
907 | LOCAL putct1(q, lp, cp, ip, ncommap) | |
908 | register expptr q; | |
909 | register struct Addrblock *lp, *cp; | |
910 | int *ip, *ncommap; | |
911 | { | |
912 | int i; | |
913 | struct Addrblock *lp1, *cp1; | |
914 | ||
915 | if(q->headblock.tag==TEXPR && q->exprblock.opcode==OPCONCAT) | |
916 | { | |
917 | putct1(q->exprblock.leftp, lp, cp, ip, ncommap); | |
918 | putct1(q->exprblock.rightp, lp, cp , ip, ncommap); | |
919 | frexpr(q->exprblock.vleng); | |
920 | free(q); | |
921 | } | |
922 | else | |
923 | { | |
924 | i = (*ip)++; | |
925 | lp1 = cpexpr(lp); | |
926 | lp1->memoffset = mkexpr(OPPLUS, lp1->memoffset, ICON(i*SZLENG)); | |
927 | cp1 = cpexpr(cp); | |
928 | cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR)); | |
929 | putassign( lp1, cpexpr(q->headblock.vleng) ); | |
930 | putassign( cp1, addrof(putch1(q,ncommap)) ); | |
931 | *ncommap += 2; | |
932 | } | |
933 | } | |
934 | \f | |
935 | LOCAL putaddr(p, indir) | |
936 | register struct Addrblock *p; | |
937 | int indir; | |
938 | { | |
939 | int type, type2, funct; | |
940 | ftnint offset, simoffset(); | |
941 | expptr offp, shorten(); | |
942 | ||
943 | if( ISERROR(p) || ISERROR(p->memoffset) ) | |
944 | { | |
945 | frexpr(p); | |
946 | return; | |
947 | } | |
948 | ||
949 | type = p->vtype; | |
950 | type2 = types2[type]; | |
951 | funct = (p->vclass==CLPROC ? P2FUNCT<<2 : 0); | |
952 | ||
953 | offp = (p->memoffset ? cpexpr(p->memoffset) : NULL); | |
954 | ||
955 | ||
956 | #if (FUDGEOFFSET != 1) | |
957 | if(offp) | |
958 | offp = mkexpr(OPSTAR, ICON(FUDGEOFFSET), offp); | |
959 | #endif | |
960 | ||
961 | offset = simoffset( &offp ); | |
962 | #if SZINT < SZLONG | |
963 | if(offp) | |
964 | if(shortsubs) | |
965 | offp = shorten(offp); | |
966 | else | |
967 | offp = mkconv(TYINT, offp); | |
968 | #else | |
969 | if(offp) | |
970 | offp = mkconv(TYINT, offp); | |
971 | #endif | |
972 | ||
973 | switch(p->vstg) | |
974 | { | |
975 | case STGAUTO: | |
976 | if(indir && !offp) | |
977 | { | |
978 | p2oreg(offset, AUTOREG, type2); | |
979 | break; | |
980 | } | |
981 | ||
982 | if(!indir && !offp && !offset) | |
983 | { | |
984 | p2reg(AUTOREG, type2 | P2PTR); | |
985 | break; | |
986 | } | |
987 | ||
988 | p2reg(AUTOREG, type2 | P2PTR); | |
989 | if(offp) | |
990 | { | |
991 | putx(offp); | |
992 | if(offset) | |
993 | p2icon(offset, P2INT); | |
994 | } | |
995 | else | |
996 | p2icon(offset, P2INT); | |
997 | if(offp && offset) | |
998 | p2op(P2PLUS, type2 | P2PTR); | |
999 | p2op(P2PLUS, type2 | P2PTR); | |
1000 | if(indir) | |
1001 | p2op(P2INDIRECT, type2); | |
1002 | break; | |
1003 | ||
1004 | case STGARG: | |
1005 | p2oreg( | |
1006 | #ifdef ARGOFFSET | |
1007 | ARGOFFSET + | |
1008 | #endif | |
1009 | (ftnint) (FUDGEOFFSET*p->memno), | |
1010 | ARGREG, type2 | P2PTR | funct ); | |
1011 | ||
1012 | if(offp) | |
1013 | putx(offp); | |
1014 | if(offset) | |
1015 | p2icon(offset, P2INT); | |
1016 | if(offp && offset) | |
1017 | p2op(P2PLUS, type2 | P2PTR); | |
1018 | if(offp || offset) | |
1019 | p2op(P2PLUS, type2 | P2PTR); | |
1020 | if(indir) | |
1021 | p2op(P2INDIRECT, type2); | |
1022 | break; | |
1023 | ||
1024 | case STGLENG: | |
1025 | if(indir) | |
1026 | { | |
1027 | p2oreg( | |
1028 | #ifdef ARGOFFSET | |
1029 | ARGOFFSET + | |
1030 | #endif | |
1031 | (ftnint) (FUDGEOFFSET*p->memno), | |
1032 | ARGREG, type2 ); | |
1033 | } | |
1034 | else { | |
1035 | p2reg(ARGREG, type2 | P2PTR ); | |
1036 | p2icon( | |
1037 | #ifdef ARGOFFSET | |
1038 | ARGOFFSET + | |
1039 | #endif | |
1040 | (ftnint) (FUDGEOFFSET*p->memno), P2INT); | |
1041 | p2op(P2PLUS, type2 | P2PTR ); | |
1042 | } | |
1043 | break; | |
1044 | ||
1045 | ||
1046 | case STGBSS: | |
1047 | case STGINIT: | |
1048 | case STGEXT: | |
1049 | case STGCOMMON: | |
1050 | case STGEQUIV: | |
1051 | case STGCONST: | |
1052 | if(offp) | |
1053 | { | |
1054 | putx(offp); | |
1055 | putmem(p, P2ICON, offset); | |
1056 | p2op(P2PLUS, type2 | P2PTR); | |
1057 | if(indir) | |
1058 | p2op(P2INDIRECT, type2); | |
1059 | } | |
1060 | else | |
1061 | putmem(p, (indir ? P2NAME : P2ICON), offset); | |
1062 | ||
1063 | break; | |
1064 | ||
1065 | case STGREG: | |
1066 | if(indir) | |
1067 | p2reg(p->memno, type2); | |
1068 | else | |
1069 | fatal("attempt to take address of a register"); | |
1070 | break; | |
1071 | ||
1072 | default: | |
1073 | fatali("putaddr: invalid vstg %d", p->vstg); | |
1074 | } | |
1075 | frexpr(p); | |
1076 | } | |
1077 | ||
1078 | ||
1079 | ||
1080 | ||
1081 | LOCAL putmem(p, class, offset) | |
1082 | expptr p; | |
1083 | int class; | |
1084 | ftnint offset; | |
1085 | { | |
1086 | int type2; | |
1087 | int funct; | |
1088 | char *name, *memname(); | |
1089 | ||
1090 | funct = (p->headblock.vclass==CLPROC ? P2FUNCT<<2 : 0); | |
1091 | type2 = types2[p->headblock.vtype]; | |
1092 | if(p->headblock.vclass == CLPROC) | |
1093 | type2 |= (P2FUNCT<<2); | |
1094 | name = memname(p->addrblock.vstg, p->addrblock.memno); | |
1095 | if(class == P2ICON) | |
1096 | { | |
1097 | p2triple(P2ICON, name[0]!='\0', type2|P2PTR); | |
1098 | p2word(offset); | |
1099 | if(name[0]) | |
1100 | p2name(name); | |
1101 | } | |
1102 | else | |
1103 | { | |
1104 | p2triple(P2NAME, offset!=0, type2); | |
1105 | if(offset != 0) | |
1106 | p2word(offset); | |
1107 | p2name(name); | |
1108 | } | |
1109 | } | |
1110 | ||
1111 | ||
1112 | \f | |
1113 | LOCAL struct Addrblock *putcall(p) | |
1114 | struct Exprblock *p; | |
1115 | { | |
1116 | chainp arglist, charsp, cp; | |
1117 | int n, first; | |
1118 | struct Addrblock *t; | |
1119 | struct Exprblock *q; | |
1120 | struct Exprblock *fval; | |
1121 | int type, type2, ctype, indir; | |
1122 | ||
1123 | type2 = types2[type = p->vtype]; | |
1124 | charsp = NULL; | |
1125 | indir = (p->opcode == OPCCALL); | |
1126 | n = 0; | |
1127 | first = YES; | |
1128 | ||
1129 | if(p->rightp) | |
1130 | { | |
1131 | arglist = p->rightp->listblock.listp; | |
1132 | free(p->rightp); | |
1133 | } | |
1134 | else | |
1135 | arglist = NULL; | |
1136 | ||
1137 | for(cp = arglist ; cp ; cp = cp->nextp) | |
1138 | if(indir) | |
1139 | ++n; | |
1140 | else { | |
1141 | q = cp->datap; | |
1142 | if(q->tag == TCONST) | |
1143 | cp->datap = q = putconst(q); | |
1144 | if( ISCHAR(q) ) | |
1145 | { | |
1146 | charsp = hookup(charsp, mkchain(cpexpr(q->vleng), 0) ); | |
1147 | n += 2; | |
1148 | } | |
1149 | else if(q->vclass == CLPROC) | |
1150 | { | |
1151 | charsp = hookup(charsp, mkchain( ICON(0) , 0)); | |
1152 | n += 2; | |
1153 | } | |
1154 | else | |
1155 | n += 1; | |
1156 | } | |
1157 | ||
1158 | if(type == TYCHAR) | |
1159 | { | |
1160 | if( ISICON(p->vleng) ) | |
1161 | { | |
1162 | fval = mktemp(TYCHAR, p->vleng); | |
1163 | n += 2; | |
1164 | } | |
1165 | else { | |
1166 | err("adjustable character function"); | |
1167 | return; | |
1168 | } | |
1169 | } | |
1170 | else if( ISCOMPLEX(type) ) | |
1171 | { | |
1172 | fval = mktemp(type, NULL); | |
1173 | n += 1; | |
1174 | } | |
1175 | else | |
1176 | fval = NULL; | |
1177 | ||
1178 | ctype = (fval ? P2INT : type2); | |
1179 | putaddr(p->leftp, NO); | |
1180 | ||
1181 | if(fval) | |
1182 | { | |
1183 | first = NO; | |
1184 | putaddr( cpexpr(fval), NO); | |
1185 | if(type==TYCHAR) | |
1186 | { | |
1187 | putx( mkconv(TYLENG,p->vleng) ); | |
1188 | p2op(P2LISTOP, type2); | |
1189 | } | |
1190 | } | |
1191 | ||
1192 | for(cp = arglist ; cp ; cp = cp->nextp) | |
1193 | { | |
1194 | q = cp->datap; | |
1195 | if(q->tag==TADDR && (indir || q->vstg!=STGREG) ) | |
1196 | putaddr(q, indir && q->vtype!=TYCHAR); | |
1197 | else if( ISCOMPLEX(q->vtype) ) | |
1198 | putcxop(q); | |
1199 | else if (ISCHAR(q) ) | |
1200 | putchop(q); | |
1201 | else if( ! ISERROR(q) ) | |
1202 | { | |
1203 | if(indir) | |
1204 | putx(q); | |
1205 | else { | |
1206 | t = mktemp(q->vtype, q->vleng); | |
1207 | putassign( cpexpr(t), q ); | |
1208 | putaddr(t, NO); | |
1209 | putcomma(1, q->vtype, YES); | |
1210 | } | |
1211 | } | |
1212 | if(first) | |
1213 | first = NO; | |
1214 | else | |
1215 | p2op(P2LISTOP, type2); | |
1216 | } | |
1217 | ||
1218 | if(arglist) | |
1219 | frchain(&arglist); | |
1220 | for(cp = charsp ; cp ; cp = cp->nextp) | |
1221 | { | |
1222 | putx( mkconv(TYLENG,cp->datap) ); | |
1223 | p2op(P2LISTOP, type2); | |
1224 | } | |
1225 | frchain(&charsp); | |
1226 | p2op(n>0 ? P2CALL : P2CALL0 , ctype); | |
1227 | free(p); | |
1228 | return(fval); | |
1229 | } | |
1230 | ||
1231 | ||
1232 | ||
1233 | LOCAL putmnmx(p) | |
1234 | register struct Exprblock *p; | |
1235 | { | |
1236 | int op, type; | |
1237 | int ncomma; | |
1238 | struct Exprblock *qp; | |
1239 | chainp p0, p1; | |
1240 | struct Addrblock *sp, *tp; | |
1241 | ||
1242 | type = p->vtype; | |
1243 | op = (p->opcode==OPMIN ? OPLT : OPGT ); | |
1244 | p0 = p->leftp->listblock.listp; | |
1245 | free(p->leftp); | |
1246 | free(p); | |
1247 | ||
1248 | sp = mktemp(type, NULL); | |
1249 | tp = mktemp(type, NULL); | |
1250 | qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp)); | |
1251 | qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp); | |
1252 | qp = fixexpr(qp); | |
1253 | ||
1254 | ncomma = 1; | |
1255 | putassign( cpexpr(sp), p0->datap ); | |
1256 | ||
1257 | for(p1 = p0->nextp ; p1 ; p1 = p1->nextp) | |
1258 | { | |
1259 | ++ncomma; | |
1260 | putassign( cpexpr(tp), p1->datap ); | |
1261 | if(p1->nextp) | |
1262 | { | |
1263 | ++ncomma; | |
1264 | putassign( cpexpr(sp), cpexpr(qp) ); | |
1265 | } | |
1266 | else | |
1267 | putx(qp); | |
1268 | } | |
1269 | ||
1270 | putcomma(ncomma, type, NO); | |
1271 | frtemp(sp); | |
1272 | frtemp(tp); | |
1273 | frchain( &p0 ); | |
1274 | } | |
1275 | ||
1276 | ||
1277 | ||
1278 | ||
1279 | LOCAL putcomma(n, type, indir) | |
1280 | int n, type, indir; | |
1281 | { | |
1282 | type = types2[type]; | |
1283 | if(indir) | |
1284 | type |= P2PTR; | |
1285 | while(--n >= 0) | |
1286 | p2op(P2COMOP, type); | |
1287 | } | |
1288 | ||
1289 | ||
1290 | ||
1291 | ||
1292 | ftnint simoffset(p0) | |
1293 | expptr *p0; | |
1294 | { | |
1295 | ftnint offset, prod; | |
1296 | register expptr p, lp, rp; | |
1297 | ||
1298 | offset = 0; | |
1299 | p = *p0; | |
1300 | if(p == NULL) | |
1301 | return(0); | |
1302 | ||
1303 | if( ! ISINT(p->headblock.vtype) ) | |
1304 | return(0); | |
1305 | ||
1306 | if(p->headblock.tag==TEXPR && p->exprblock.opcode==OPSTAR) | |
1307 | { | |
1308 | lp = p->exprblock.leftp; | |
1309 | rp = p->exprblock.rightp; | |
1310 | if(ISICON(rp) && lp->headblock.tag==TEXPR && | |
1311 | lp->exprblock.opcode==OPPLUS && ISICON(lp->exprblock.rightp)) | |
1312 | { | |
1313 | p->exprblock.opcode = OPPLUS; | |
1314 | lp->opcode = OPSTAR; | |
1315 | prod = rp->constblock.const.ci * | |
1316 | lp->exprblock.rightp->constblock.const.ci; | |
1317 | lp->exprblock.rightp->constblock.const.ci = rp->constblock.const.ci; | |
1318 | rp->constblock.const.ci = prod; | |
1319 | } | |
1320 | } | |
1321 | ||
1322 | if(p->headblock.tag==TEXPR && p->exprblock.opcode==OPPLUS && | |
1323 | ISICON(p->exprblock.rightp)) | |
1324 | { | |
1325 | rp = p->exprblock.rightp; | |
1326 | lp = p->exprblock.leftp; | |
1327 | offset += rp->constblock.const.ci; | |
1328 | frexpr(rp); | |
1329 | free(p); | |
1330 | *p0 = lp; | |
1331 | } | |
1332 | ||
1333 | if(p->headblock.tag == TCONST) | |
1334 | { | |
1335 | offset += p->constblock.const.ci; | |
1336 | frexpr(p); | |
1337 | *p0 = NULL; | |
1338 | } | |
1339 | ||
1340 | return(offset); | |
1341 | } | |
1342 | \f | |
1343 | ||
1344 | ||
1345 | ||
1346 | ||
1347 | p2op(op, type) | |
1348 | int op, type; | |
1349 | { | |
1350 | p2triple(op, 0, type); | |
1351 | } | |
1352 | ||
1353 | p2icon(offset, type) | |
1354 | ftnint offset; | |
1355 | int type; | |
1356 | { | |
1357 | p2triple(P2ICON, 0, type); | |
1358 | p2word(offset); | |
1359 | } | |
1360 | ||
1361 | ||
1362 | ||
1363 | ||
1364 | p2oreg(offset, reg, type) | |
1365 | ftnint offset; | |
1366 | int reg, type; | |
1367 | { | |
1368 | p2triple(P2OREG, reg, type); | |
1369 | p2word(offset); | |
1370 | p2name(""); | |
1371 | } | |
1372 | ||
1373 | ||
1374 | ||
1375 | ||
1376 | p2reg(reg, type) | |
1377 | int reg, type; | |
1378 | { | |
1379 | p2triple(P2REG, reg, type); | |
1380 | } | |
1381 | ||
1382 | ||
1383 | ||
1384 | p2pi(s, i) | |
1385 | char *s; | |
1386 | int i; | |
1387 | { | |
1388 | char buff[100]; | |
1389 | sprintf(buff, s, i); | |
1390 | p2pass(buff); | |
1391 | } | |
1392 | ||
1393 | ||
1394 | ||
1395 | p2pij(s, i, j) | |
1396 | char *s; | |
1397 | int i, j; | |
1398 | { | |
1399 | char buff[100]; | |
1400 | sprintf(buff, s, i, j); | |
1401 | p2pass(buff); | |
1402 | } | |
1403 | ||
1404 | ||
1405 | ||
1406 | ||
1407 | p2ps(s, t) | |
1408 | char *s, *t; | |
1409 | { | |
1410 | char buff[100]; | |
1411 | sprintf(buff, s, t); | |
1412 | p2pass(buff); | |
1413 | } | |
1414 | ||
1415 | ||
1416 | ||
1417 | ||
1418 | p2pass(s) | |
1419 | char *s; | |
1420 | { | |
1421 | p2triple(P2PASS, (strlen(s) + FOUR-1)/FOUR, 0); | |
1422 | p2str(s); | |
1423 | } | |
1424 | ||
1425 | ||
1426 | ||
1427 | ||
1428 | p2str(s) | |
1429 | register char *s; | |
1430 | { | |
1431 | union { long int word; char str[FOUR]; } u; | |
1432 | register int i; | |
1433 | ||
1434 | i = 0; | |
1435 | u.word = 0; | |
1436 | while(*s) | |
1437 | { | |
1438 | u.str[i++] = *s++; | |
1439 | if(i == FOUR) | |
1440 | { | |
1441 | p2word(u.word); | |
1442 | u.word = 0; | |
1443 | i = 0; | |
1444 | } | |
1445 | } | |
1446 | if(i > 0) | |
1447 | p2word(u.word); | |
1448 | } | |
1449 | ||
1450 | ||
1451 | ||
1452 | ||
1453 | p2triple(op, var, type) | |
1454 | int op, var, type; | |
1455 | { | |
1456 | register long word; | |
1457 | word = op | (var<<8); | |
1458 | word |= ( (long int) type) <<16; | |
1459 | p2word(word); | |
1460 | } | |
1461 | ||
1462 | ||
1463 | ||
1464 | ||
1465 | p2name(s) | |
1466 | char *s; | |
1467 | { | |
1468 | int i; | |
1469 | union { long int word[2]; char str[8]; } u; | |
1470 | ||
1471 | u.word[0] = u.word[1] = 0; | |
1472 | for(i = 0 ; i<8 && *s ; ++i) | |
1473 | u.str[i] = *s++; | |
1474 | p2word(u.word[0]); | |
1475 | p2word(u.word[1]); | |
1476 | } | |
1477 | ||
1478 | ||
1479 | ||
1480 | ||
1481 | p2word(w) | |
1482 | long int w; | |
1483 | { | |
1484 | *p2bufp++ = w; | |
1485 | if(p2bufp >= p2bufend) | |
1486 | p2flush(); | |
1487 | } | |
1488 | ||
1489 | ||
1490 | ||
1491 | p2flush() | |
1492 | { | |
1493 | if(p2bufp > p2buff) | |
1494 | write(fileno(textfile), p2buff, (p2bufp-p2buff)*sizeof(long int)); | |
1495 | p2bufp = p2buff; | |
1496 | } |