|
|
1.1 root 1: static char *ID_gencode="@(#) gencode.c: 1.22 5/8/84";
2: #include <stdio.h>
3: #include "systems.h"
4: #include "symbols.h"
5: #include "instab.h"
6: #include "parse.h"
7: #include "gendefs.h"
8: #include "expand.h"
9: #include "expand2.h"
10:
11: long
12: swap_b2(),
13: swap_b4();
14: extern upsymins
15: *lookup();
16: extern short
17: opt; /* no optimize flag */
18: extern unsigned short
19: line; /* current line number */
20:
21: addrgen(insptr,addr,expand,opnum)
22: register instr
23: *insptr;
24: register addrmode
25: *addr;
26: short expand, opnum;
27: {
28: long val;
29: register short reg;
30:
31: /* check if USER specified an expand byte */
32: /* check if USER specified an operand specifier */
33: if (insptr->tag & IS25) {
34: if (addr->newtype != NOTYPE)
35: yyerror("Expand byte invalid in IS25 instruction");
36: if (addr->expspec != NULLSPEC)
37: yyerror("Operand specifier invalid in IS25 instruction");
38: } else
39: expand = addr->newtype;
40: if (expand != NOTYPE)
41: generate(8,NOACTION,(long)((CEXPAND<<4)|expand),NULLSYM);
42:
43: switch(addr->admode) {
44:
45: case REGDFMD: /* register deferred mode */
46: reg = addr->adreg;
47: if (reg != PCREG) {
48: generate(8,NOACTION,(long)((CREGDFMD<<4)|reg),NULLSYM);
49: } else {
50: yyerror("Register deferred mode illegal with register 15 (%pc).");
51: }
52: return;
53:
54: case DSPMD: /* displacement mode */
55: val = addr->adexpr.expval;
56: reg = addr->adreg;
57: if ((addr->adexpr.symptr == NULLSYM)
58: && (addr->expspec == NULLSPEC)
59: && opt) {
60: /* No operand specifier, and optimization allowed, and
61: symbol ptr is null */
62: if ((val == 0) && (reg != PCREG)) {
63: /* register deferred mode */
64: /* not legal for register 15 or PC */
65: generate(8,NOACTION,(long)((CREGDFMD<<4)|reg),
66: NULLSYM);
67: return;
68: } /* register deferred mode */
69:
70: if ((reg == APREG) && (0 <= val && val <= 14)) {
71: /* AP displacement mode */
72: generate(8,NOACTION,(CAPDSPMD<<4)|val,NULLSYM);
73: return;
74: } /* AP displacement mode */
75:
76: if ((reg == FPREG) && (0 <= val && val <= 14)) {
77: /* FP displacement mode */
78: generate(8,NOACTION,(CFPDSPMD<<4)|val,NULLSYM);
79: return;
80: } /* FP displacement mode */
81:
82: if (-(1<<7) <= val && val < 1<<7) {
83: /* byte displacement mode */
84: generate(8,NOACTION,(long)((CBDSPMD<<4)|reg),
85: NULLSYM);
86: generate(8,NOACTION,val,NULLSYM);
87: return;
88: } /* byte displacement mode */
89: if (-(1L<<15) <= val && val < 1L<<15) {
90: /* halfword displacement mode */
91: generate(8,NOACTION,(long)((CHDSPMD<<4)|reg),
92: NULLSYM);
93: generate(16,NOACTION,swap_b2(val),NULLSYM);
94: return;
95: } /* halfword displacement mode */
96: /* Otherwise use word displacement mode */
97: generate(8,NOACTION,(long)((CDSPMD<<4)|reg),NULLSYM);
98: generate(32,NOACTION,swap_b4(val),NULLSYM);
99: return;
100: } /* addr->adexpr.symptr == NULLSYM */
101:
102: if ( (addr->adexpr.symptr != NULLSYM)
103: || ((!opt) && (addr->expspec == NULLSPEC))) {
104: /* don't know displacement;
105: must use word displacement mode */
106: generate(8,NOACTION,(long)((CDSPMD<<4)|reg),NULLSYM);
107: generate(32,RELDIR32,val,addr->adexpr.symptr);
108: return;
109: }
110:
111: /* At this point the user must be specifying the operand
112: expression size through the use of an operand specifier.
113: Generate the correct operand. */
114:
115: switch ( addr->expspec ) {
116:
117: case BYTESPEC:
118: if ( (unsigned) val >= (1<<8)) {
119: yyerror("Expression larger than byte.");
120: } else {
121: /* byte displacement mode */
122: generate(8,NOACTION,(long)((CBDSPMD<<4)|reg),
123: NULLSYM);
124: generate(8,NOACTION,val,NULLSYM);
125: }
126: return;
127:
128: case HALFSPEC:
129: if ( (unsigned) val >= (1<<16)) {
130: yyerror("Expression larger than halfword.");
131: } else {
132: /* halfword displacement mode */
133: generate(8,NOACTION,(long)((CHDSPMD<<4)|reg),
134: NULLSYM);
135: generate(16,NOACTION,swap_b2(val),NULLSYM);
136: }
137: return;
138:
139: case WORDSPEC:
140: generate(8,NOACTION,(long)((CDSPMD<<4)|reg),NULLSYM);
141: generate(32,NOACTION,swap_b4(val),NULLSYM);
142: return;
143:
144: case SHORTSPEC:
145: if (0 > val || val > 14) {
146: yyerror("Expression outside short offset range.");
147: return;
148: }
149: if (reg == APREG) {
150: /* AP displacement mode */
151: generate(8,NOACTION,(CAPDSPMD<<4)|val,NULLSYM);
152: return;
153: } /* AP short offset */
154:
155: if (reg == FPREG) {
156: /* FP displacement mode */
157: generate(8,NOACTION,(CFPDSPMD<<4)|val,NULLSYM);
158: return;
159: } /* FP displacement mode */
160:
161: yyerror("Illegal register for short offset address mode.");
162: return;
163:
164: default:
165: yyerror("Illegal operand specifier for displacement address mode.");
166: return;
167:
168: } /* switch */
169:
170: case DSPDFMD: /* displacement deferred mode */
171: val = addr->adexpr.expval;
172: reg = addr->adreg;
173: if ( (addr->adexpr.symptr == NULLSYM)
174: && (addr->expspec == NULLSPEC)
175: && opt) {
176: if (-(1<<7) <= val && val < 1<<7) {
177: /* byte displacement deferred mode */
178: generate(8,NOACTION,(long)((CBDSPDFMD<<4)|reg),
179: NULLSYM);
180: generate(8,NOACTION,val,NULLSYM);
181: return;
182: } /* byte displacement deferred mode */
183: if (-(1L<<15) <= val && val < 1L<<15) {
184: /* halfword displacement deferred mode */
185: generate(8,NOACTION,(long)((CHDSPDFMD<<4)|reg),
186: NULLSYM);
187: generate(16,NOACTION,swap_b2(val),NULLSYM);
188: return;
189: } /* halfword displacement deferred mode */
190: /* Otherwise use word displacement deferred mode */
191: generate(8,NOACTION,(long)((CDSPDFMD<<4)|reg),NULLSYM);
192: generate(32,NOACTION,swap_b4(val),NULLSYM);
193: return;
194: } /* addr->adexpr.symptr == NULLSYM */
195:
196: if ( (addr->adexpr.symptr != NULLSYM)
197: || ((!opt) && (addr->expspec == NULLSPEC))) {
198:
199: /* don't know displacement;
200: must use word displacement deferred mode */
201: generate(8,NOACTION,(long)((CDSPDFMD<<4)|reg),NULLSYM);
202: generate(32,RELDIR32,val,addr->adexpr.symptr);
203: return;
204: }
205:
206: /* At this point the user must be specifying the operand
207: expression size through the use of an operand specifier.
208: Generate the correct operand. */
209:
210: switch ( addr->expspec ) {
211:
212: case BYTESPEC:
213: if ( (unsigned) val >= (1<<8)) {
214: yyerror("Expression larger than byte.");
215: } else {
216: /* byte displacement deferred mode */
217: generate(8,NOACTION,(long)((CBDSPDFMD<<4)|reg),
218: NULLSYM);
219: generate(8,NOACTION,val,NULLSYM);
220: }
221: return;
222:
223: case HALFSPEC:
224: if ( (unsigned) val >= (1<<16)) {
225: yyerror("Expression larger than halfword.");
226: } else {
227: /* halfword displacement deferred mode */
228: generate(8,NOACTION,(long)((CHDSPDFMD<<4)|reg),
229: NULLSYM);
230: generate(16,NOACTION,swap_b2(val),NULLSYM);
231: }
232: return;
233:
234: case WORDSPEC:
235: generate(8,NOACTION,(long)((CDSPDFMD<<4)|reg),NULLSYM);
236: generate(32,NOACTION,swap_b4(val),NULLSYM);
237: return;
238:
239: default:
240: yyerror("Illegal operand specifier for displacement deferred address mode.");
241: return;
242:
243: } /* switch */
244:
245: case EXADMD: /* external address mode */
246: case ABSMD: /* absolute address mode */
247: generate(8,NOACTION,(long)(CABSMD),NULLSYM);
248: generate(32,RELDIR32,addr->adexpr.expval,addr->adexpr.symptr);
249: return;
250:
251: case EXADDFMD: /* external address deferred mode (PC relative deferred) */
252: case ABSDFMD: /* absolute address deferred mode */
253: generate(8,NOACTION,(long)(CABSDFMD),NULLSYM);
254: generate(32,RELDIR32,addr->adexpr.expval,addr->adexpr.symptr);
255: return;
256:
257: case IMMD: /* immediate mode */
258: val = addr->adexpr.expval;
259: if ( (addr->adexpr.symptr == NULLSYM)
260: && (addr->expspec == NULLSPEC)
261: && opt) {
262: if ( val < 0 ) {
263: if ( (insptr->tag & IS25) &&
264: (insptr->name[0] == 'u') )
265: {
266: generate(8,NOACTION,(long)CIMMD,NULLSYM);
267: generate(32,NOACTION,swap_b4(val),NULLSYM);
268: return;
269: }
270: }
271:
272: if (-(1<<4) <= val && val < 1<<6) {
273: generate(8,NOACTION,val,NULLSYM);
274: return;
275: }
276:
277: if (-(1<<7) <= val && val < 1<<7) {
278: /* byte immediate mode */
279: generate(8,NOACTION,(long)CBIMMD,NULLSYM);
280: generate(8,NOACTION,val,NULLSYM);
281: return;
282: } /* byte immediate mode */
283: if (-(1L<<15) <= val && val < 1L<<15) {
284: /* halfword immediate mode */
285: generate(8,NOACTION,(long)CHIMMD,NULLSYM);
286: generate(16,NOACTION,swap_b2(val),NULLSYM);
287: return;
288: } /* halfword immediate mode */
289: /* Otherwise use fullword immediate mode */
290: generate(8,NOACTION,(long)CIMMD,NULLSYM);
291: generate(32,NOACTION,swap_b4(val),NULLSYM);
292: return;
293: } /* addr->adexpr.symptr == NULLSYM */
294:
295: if ( (addr->adexpr.symptr != NULLSYM)
296: || ((!opt) && (addr->expspec == NULLSPEC))) {
297:
298: /* don't know value;
299: must use fullword immediate mode */
300: generate(8,NOACTION,(long)CIMMD,NULLSYM);
301: generate(32,RELDIR32,val,addr->adexpr.symptr);
302: return;
303: }
304:
305: /* At this point the user must be specifying the operand
306: expression size through the use of an operand specifier.
307: Generate the correct operand. */
308:
309: switch ( addr->expspec ) {
310:
311: case BYTESPEC:
312: if ( (unsigned) val >= (1<<8)) {
313: yyerror("Expression larger than byte.");
314: } else {
315: /* byte immediate mode */
316: generate(8,NOACTION,(long)CBIMMD,NULLSYM);
317: generate(8,NOACTION,val,NULLSYM);
318: }
319: return;
320:
321: case HALFSPEC:
322: if ( (unsigned) val >= (1<<16)) {
323: yyerror("Expression larger than halfword.");
324: } else {
325: /* halfword immediate mode */
326: generate(8,NOACTION,(long)CHIMMD,NULLSYM);
327: generate(16,NOACTION,swap_b2(val),NULLSYM);
328: }
329: return;
330:
331: case WORDSPEC:
332: /* fullword immediate mode */
333: generate(8,NOACTION,(long)CIMMD,NULLSYM);
334: generate(32,NOACTION,swap_b4(val),NULLSYM);
335: return;
336:
337: case LITERALSPEC:
338: if (-(1<<4) <= val && val < 1<<6) {
339: generate(8,NOACTION,val,NULLSYM);
340: } else {
341: yyerror("Expression larger than literal.");
342: }
343: return;
344:
345: default:
346: yyerror("Illegal operand specifier for immediate address mode.");
347: return;
348:
349: } /* switch */
350:
351: #if FLOAT
352: case FPIMMD: /* fp immediate, same as IMMD but w/o optimization */
353: if ((val=optype(insptr->tag,opnum)) == 3) /* 64 bit (double) */
354: generate(8,NOACTION,(long)CDIMMD,NULLSYM);
355: else /* 32 bit (single) */
356: generate(8,NOACTION,(long)CIMMD,NULLSYM);
357: generate(32,NOACTION,swap_b4(addr->adexpr.expval),addr->adexpr.symptr);
358: if (val == 3) /* generate second 32 bits */
359: generate(32,NOACTION,swap_b4(addr->adexpr.fdexpval2),addr->adexpr.symptr);
360: break;
361: #endif
362:
363: case REGMD: /* register mode */
364: reg = addr->adreg;
365: if ( reg == PCREG ) {
366: yyerror("Register mode illegal with register 15 (%pc).");
367: } else {
368: generate(8,NOACTION,(long)((CREGMD<<4)|reg),NULLSYM);
369: }
370: return;
371:
372: default:
373: yyerror("Assembler error: invalid addressing mode");
374: return;
375: } /* switch */
376: } /* addrgen */
377:
378: long
379: swap_b2(val)
380: long val;
381: {
382: long b1, b2;
383:
384: b1 = (val >> 8) & 0x00FFL; /* 2nd low goes to low */
385: b2 = (val << 8) & 0xFF00L; /* low goes to high */
386: return (b2|b1);
387: } /* swap_b2 */
388:
389: long
390: swap_b4(val)
391: long val;
392: {
393: long b1, b2, b3, b4;
394:
395: b1 = (val >> 24) & 0x000000FFL; /* high goes to low */
396: b2 = (val >> 8) & 0x0000FF00L; /* 2nd high goes to 2nd low */
397: b3 = (val << 8) & 0x00FF0000L; /* 2nd low goes to 2nd high */
398: b4 = (val << 24) & 0xFF000000L; /* low goes to high */
399: return (b1|b2|b3|b4);
400: } /* swap_b4 */
401:
402: optype(instype,opnum)
403: BYTE instype;
404: short opnum;
405: {
406: /*
407: * figure out operand type according to instruction type and operand number
408: * return: 0=byte 1=half 2=word 3=double
409: */
410:
411: switch (instype & (~IS25)) {
412:
413: case INSTRB:
414: return 0;
415:
416: case INSTRH:
417: return 1;
418:
419: case INSTRW:
420: return 2;
421:
422: #if FLOAT
423: case INSTRD:
424: return 3;
425: #endif
426:
427: case INSTRBH:
428: return (opnum==1) ? 0 : 1;
429:
430: case INSTRBW:
431: return (opnum==1) ? 0 : 2;
432:
433: case INSTRHW:
434: return (opnum==1) ? 1 : 2;
435:
436: case INSTRWH:
437: return (opnum==1) ? 2 : 1;
438:
439: case INSTRWB:
440: return (opnum==1) ? 2 : 0;
441:
442: case INSTRHB:
443: return (opnum==1) ? 1 : 0;
444:
445: default: /* should not happen, but just in case */
446: return 2; /* treat as word operand */
447: }
448: } /* optype */
449:
450: convgen(insptr,addr1,addr2)
451: instr *insptr;
452: register addrmode
453: *addr1,
454: *addr2;
455: {
456: /*
457: *
458: * movb[bh|bw|hw] and movt[wb|hb|wh] instructions;
459: *
460: * All are encoded as expand mode mappings except
461: * for movtXY with a register destination.
462: * These are encoded as follows:
463: *
464: * movthb X,%ry -> andh3 &0xFF,X,%ry
465: * movtwb X,%ry -> andw3 &0xFF,X,%ry
466: * movtwh X,%ry -> movw X,%ry ; movh %ry,%ry
467: *
468: */
469:
470: static addrmode maskop = {NOTYPE,IMMD,0x01,{ABS,NULLSYM,0xFFL}};
471: register short expand;
472: instr *newins; /* set up dummy operands for movtwb */
473: char *maskinst = "andw3";
474:
475: /* check for movtXY with a register dest. */
476: if (addr2->admode == REGMD)
477: switch (insptr->tag & (~IS25)) {
478: case INSTRHB:
479: /* change instruction for movthb */
480: maskinst = "andh3";
481: /* fall through to ... */
482: case INSTRWB:
483: newins = (*lookup(maskinst,N_INSTALL,MNEMON)).itp;
484: generate(8,NOACTION,newins->opcode,NULLSYM);
485: addrgen(newins,&maskop,NOTYPE,1); /* mask operand */
486: addrgen(insptr,addr1,NOTYPE,2);
487: addrgen(insptr,addr2,UBYTE,3);
488: return;
489: case INSTRWH:
490: generate(8,NOACTION,insptr->opcode,NULLSYM); /* movw */
491: addrgen(insptr,addr1,NOTYPE,1);
492: addrgen(insptr,addr2,NOTYPE,2);
493: generate(0,NEWSTMT,(long)line,NULLSYM);
494: newins = (*lookup("movh",N_INSTALL,MNEMON)).itp;
495: generate(8,NOACTION,newins->opcode,NULLSYM);
496: addrgen(insptr,addr2,NOTYPE,1);
497: addrgen(insptr,addr2,NOTYPE,2);
498: return;
499: } /* switch */
500:
501: generate(insptr->nbits,NOACTION,insptr->opcode,NULLSYM);
502: addrgen(insptr,addr1,NOTYPE,1);
503: switch (optype(insptr->tag,2)) {
504: case 0: /* byte */
505: expand = SBYTE;
506: break;
507: case 1: /* half */
508: expand = SHALF;
509: break;
510: case 2: /* word */
511: expand = SWORD;
512: break;
513: } /* switch */
514:
515: addrgen(insptr,addr2,expand,2);
516: } /* convgen */
517:
518: testgen(insptr, addr1)
519: register instr *insptr;
520: register addrmode *addr1;
521: {
522: /*
523: * NOP2 NOP3
524: *
525: * This routine will generate the filler bytes
526: * for the above two nops.
527: */
528:
529: int val;
530:
531: if ( addr1->newtype != NOTYPE ) {
532: yyerror("Expand byte illegal with NOP2 or NOP3 instructions.");
533: return;
534: }
535:
536: if ( addr1->expspec != NULLSPEC ) {
537: yyerror("Operand specifier illegal with NOP2 or NOP3 instructions.");
538: return;
539: }
540:
541: generate( insptr->nbits, NOACTION, insptr->opcode, NULLSYM);
542: val = addr1->adexpr.expval;
543:
544: if ( insptr->tag == INSTRB ) {
545: if ((unsigned) val >= (1L << 8)) {
546: yyerror("Optional immediate for NOP2 larger than byte.");
547: } else {
548: generate( 8, NOACTION, val, NULLSYM);
549: }
550: } else {
551: if ((unsigned) val >= (1L << 16)) {
552: yyerror("Optional immediate for NOP3 larger than halfword.");
553: } else {
554: generate(16, NOACTION, val, NULLSYM);
555: }
556: }
557: } /* testgen */
558:
559: opt21gen(insptr,addr1,addr2,constant)
560: instr *insptr;
561: register addrmode
562: *addr1,
563: *addr2;
564: short constant;
565: {
566: /*
567: * This function attempts to optimize certain dyadic instructions
568: * into monadics when the first operand is a particular
569: * immediate constant.
570: *
571: * The possible optimizations are:
572: *
573: * Dyadic Constant Monadic
574: *
575: * mov[bhw] 0 CLR[BHW]
576: * add[bhw]2 1 INC[BHW]
577: * sub[bhw]2 1 DEC[BHW]
578: * cmp[bhw] 0 TST[BHW]
579: *
580: *
581: * In all cases the dyadic opcode is stored in the low byte
582: * of the opcode field of the instruction table (pointed to by insptr)
583: * and the monadic opcode is stored in the 2nd low byte
584: *
585: */
586:
587: if (addr1->admode==IMMD && addr1->adexpr.exptype==ABS &&
588: addr1->adexpr.expval==(long)constant &&
589: (insptr->tag & IS25) && opt)
590: {
591: /* generate monadic opcode */
592: generate(8,NOACTION,(insptr->opcode >> 8),NULLSYM);
593: addrgen(insptr,addr2,NOTYPE,2);
594: }
595: else {
596: /* just do normal dyadic instruction */
597: /* mask off 2nd low byte, but don't really have to */
598: generate(8,NOACTION,insptr->opcode & 0xFFL,NULLSYM);
599: addrgen(insptr,addr1,NOTYPE,1);
600: addrgen(insptr,addr2,NOTYPE,2);
601: } /* else */
602: } /* opt21gen */
603:
604: jmpopgen(insptr,opnd1)
605: instr *insptr;
606: addrmode *opnd1;
607: {
608: instr *newins;
609: long opcd, newopcd;
610: BYTE nbits;
611: unsigned short action;
612: short jmptype;
613:
614: opcd = insptr->opcode;
615:
616: switch (insptr->tag) {
617: case INSTRB: /* byte displacement */
618: nbits = 8;
619: if (opnd1->admode != EXADMD)
620: yyerror("Invalid operand");
621: action = RELPC8;
622: break;
623: case INSTRH: /* halfword displacement */
624: if (opnd1->admode != EXADMD)
625: yyerror("Invalid operand");
626: nbits = 16;
627: action = RELPC16;
628: break;
629: case IS25|INSTRW: /* IS25, word displacement */
630: if (opnd1->admode != EXADMD) {
631: /* can't generate PC relative */
632: if ((newopcd = opcd >> 8) != 0) {
633: /* generate complementary branch */
634: generate(8,NOACTION,newopcd,NULLSYM);
635: generate(8,FNDBRLEN,0L,NULLSYM);
636: } /* (newopcd = opcd >> 8) != 0 */
637: newins = (*lookup("JMP",N_INSTALL,MNEMON)).itp;
638: generate(8,NOACTION,newins->opcode,NULLSYM);
639: addrgen(insptr,opnd1,NOTYPE,1);
640: return;
641: } /* opnd1->admode != EXADMD */
642: jmptype = (opcd >> 8) != 0;
643: /* 1 means conditional; 0 unconditional */
644: if (opt) switch(shortsdi(opnd1->adexpr.symptr,
645: opnd1->adexpr.expval,
646: jmptype ? CBRB : UBRB))
647: {
648: case S_SDI: /* definitely 8-bit short */
649: generate(8,NOACTION,opcd & 0xFFL,NULLSYM);
650: generate(8,RELPC8,opnd1->adexpr.expval,
651: opnd1->adexpr.symptr);
652: return;
653: case U_SDI: /* don't know; generate short and flag */
654: generate(8,BRNOPT,opcd,NULLSYM);
655: generate(8,RELPC8,opnd1->adexpr.expval,
656: opnd1->adexpr.symptr);
657: return;
658: /* case L_SDI: fall through */
659: } /* if (opt) switch (...) */
660:
661: /* try 16-bit branch offset */
662: switch(shortsdi(opnd1->adexpr.symptr,
663: opnd1->adexpr.expval,
664: jmptype ? CBRH : UBRH))
665: {
666: case S_SDI: /* definitely 16-bit short */
667: generate(8,NOACTION,(opcd & 0xFFL) - 1L,
668: NULLSYM);
669: generate(16,RELPC16,opnd1->adexpr.expval,
670: opnd1->adexpr.symptr);
671: return;
672: case U_SDI: /* unknown; generate 16-bit short (interm.) and flag */
673: /* convert opcode(s) from short to intermed. */
674: if ((opcd >> 8) != 0)
675: /* subtract 1 from both opcodes */
676: opcd -= 0x0101L;
677: else
678: /* subtract 1 from opcode */
679: --opcd;
680: generate(8,BRNOPT,opcd,NULLSYM);
681: generate(16,RELPC16,opnd1->adexpr.expval,
682: opnd1->adexpr.symptr);
683: return;
684: case L_SDI:
685: /* test for unconditional jump */
686: if ((newopcd = opcd >> 8) != 0) {
687: /* generate complementary branch */
688: generate(8,NOACTION,newopcd,NULLSYM);
689: generate(8,FNDBRLEN,0L,NULLSYM);
690: generate(0,NEWSTMT,(long)line,NULLSYM);
691: }
692: newins = (*lookup("JMP",N_INSTALL,MNEMON)).itp;
693: generate(8,NOACTION,newins->opcode,NULLSYM);
694: addrgen(insptr,opnd1,NOTYPE,1);
695: return;
696: } /* switch */
697: case INSTRW: /* word displacement */
698: generate(8,NOACTION,opcd,NULLSYM);
699: addrgen(insptr,opnd1,NOTYPE,1);
700: return;
701: default:
702: aerror("assembler error; invalid operator type");
703: } /* switch */
704:
705: generate(8,NOACTION,opcd & 0xFFL,NULLSYM); /* not necessary to mask */
706: generate(nbits,action,opnd1->adexpr.expval,opnd1->adexpr.symptr);
707: } /* jmpopgen */
708:
709: jsbopgen(insptr,opnd1)
710: instr *insptr;
711: addrmode *opnd1;
712: {
713: long opcd;
714:
715: opcd = insptr->opcode;
716:
717: if (opnd1->admode != EXADMD) {
718: /* can't generate PC relative */
719: generate(8,NOACTION,opcd >> 8,NULLSYM);
720: addrgen(insptr,opnd1,NOTYPE,1);
721: }
722: else {
723: if (opt) switch(shortsdi(opnd1->adexpr.symptr,
724: opnd1->adexpr.expval,BSBB))
725: {
726: case S_SDI: /* definitely 8-bit short */
727: generate(8,NOACTION,opcd & 0xFFL,NULLSYM);
728: generate(8,RELPC8,opnd1->adexpr.expval,
729: opnd1->adexpr.symptr);
730: return;
731: case U_SDI: /* don't know; generate short and flag */
732: generate(8,BSBNOPT,opcd,NULLSYM);
733: generate(8,RELPC8,opnd1->adexpr.expval,
734: opnd1->adexpr.symptr);
735: return;
736: /* case L_SDI: fall through */
737: } /* if (opt) switch (...) */
738:
739: /* try 16-bit branch offset */
740: switch(shortsdi(opnd1->adexpr.symptr,
741: opnd1->adexpr.expval,BSBH))
742: {
743: case S_SDI: /* definitely 16-bit short */
744: generate(8,NOACTION,(opcd & 0xFFL) - 1L,NULLSYM);
745: generate(16,RELPC16,opnd1->adexpr.expval,
746: opnd1->adexpr.symptr);
747: return;
748: case U_SDI: /* don't know; generate 16-bit short and flag */
749: /* convert opcode from short to intermed. */
750: --opcd;
751: generate(8,BSBNOPT,opcd,NULLSYM);
752: generate(16,RELPC16,opnd1->adexpr.expval,
753: opnd1->adexpr.symptr);
754: generate(8,NOACTION,opcd >> 8,NULLSYM);
755: addrgen(insptr,opnd1,NOTYPE,1);
756: return;
757: case L_SDI:
758: generate(8,NOACTION,opcd,NULLSYM);
759: addrgen(insptr,opnd1,NOTYPE,2);
760: return;
761: } /* switch */
762: } /* else */
763: } /* jsbopgen */
764:
765: callgen(insptr,imm,dest)
766: instr *insptr;
767: addrmode *imm, *dest;
768: {
769: /*
770: *
771: * call imm,dest
772: *
773: * is encoded as
774: *
775: * CALL -(4*imm)(%sp),dest
776: *
777: */
778:
779: static addrmode dispsp = {NOTYPE,DSPMD,SPREG,{ABS,NULLSYM,1L}};
780: int span;
781:
782: dispsp.adexpr.expval = - (4L * imm->adexpr.expval );
783: generate(8,NOACTION,insptr->opcode,NULLSYM); /* CALL opcode */
784: addrgen(insptr,&dispsp,NOTYPE,1);
785:
786: #ifndef CALLPCREL
787: addrgen(insptr,dest,NOTYPE,2);
788: #else
789: if (dest->admode != EXADMD) {
790: /* can't generate PC relative */
791: addrgen(insptr,dest,NOTYPE,2);
792: } else {
793: if (opt) {
794: if (sdi(dest->adexpr.symptr, dest->adexpr.expval,
795: PCBRELCALL) == S_SDI) {
796: span = shortsdi(dest->adexpr.symptr,
797: dest->adexpr.expval,PCBRELCALL);
798: if ( span == S_SDI) {
799: /* byte displacement from PC */
800: generate(8,NOACTION,0xCFL,NULLSYM);
801: generate(8,RELPC8,dest->adexpr.expval,
802: dest->adexpr.symptr);
803: } else {
804: yyerror("Assembler error with short span dependent procedure call.");
805: }
806: return;
807: }
808: }
809:
810: /* if (opt) switch(shortsdi(dest->adexpr.symptr,
811: /* dest->adexpr.expval,PCBRELCALL))
812: /* {
813: /* case S_SDI: /* definitely 8-bit short */
814: /* /* byte displacement from PC */
815: /* generate(8,NOACTION,0xCFL,NULLSYM);
816: /* generate(8,RELPC8,dest->adexpr.expval,
817: /* dest->adexpr.symptr);
818: /* return;
819: /* case U_SDI: /* don't know; generate short and flag */
820: /* /* byte displacement from PC */
821: /* generate(8,CALLNOPT,0xCFL,NULLSYM);
822: /* generate(8,RELPC8,dest->adexpr.expval,
823: /* dest->adexpr.symptr);
824: /* return;
825: /* /* case L_SDI: fall through */
826: /* } /* if (opt) switch (...) */
827:
828: /* try 16-bit branch offset */
829: switch(shortsdi(dest->adexpr.symptr,
830: dest->adexpr.expval,PCHRELCALL))
831: {
832: case S_SDI: /* definitely 16-bit short */
833: /* halfword relative from PC */
834: generate(8,NOACTION,0xAFL,NULLSYM);
835: generate(16,RELPC16,dest->adexpr.expval,
836: dest->adexpr.symptr);
837: return;
838: case U_SDI: /* don't know; generate 16-bit short and flag */
839: /* halfword relative from PC */
840: generate(8,CALLNOPT,0xAFL,NULLSYM);
841: generate(16,RELPC16,dest->adexpr.expval,
842: dest->adexpr.symptr);
843: return;
844: case L_SDI:
845: /* CALL opcode */
846: addrgen(insptr,dest,NOTYPE,2);
847: return;
848: } /* switch */
849: } /* else */
850: #endif
851: } /* callgen */
852:
853: loop1gen(insptr,index,incr,limit,dest)
854: instr *insptr;
855: addrmode *index, *incr, *limit, *dest;
856: {
857: /*
858: *
859: * acX index,incr,limit,dest
860: * where X can be [jl|jlu|jle|jleu]
861: *
862: * is encoded as
863: *
864: * addw2 incr,index
865: * cmpw index,limit
866: * X dest
867: *
868: */
869:
870: instr *newins;
871:
872: /* addw2 */
873: newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
874: opt21gen(newins,incr,index,1); /* optimized "add" */
875: pcintcheck(newins,index);
876:
877: /* cmpw */
878: generate(0,NEWSTMT,(long)line,NULLSYM);
879: newins = (*lookup("cmpw",N_INSTALL,MNEMON)).itp;
880: #if 0
881: /* generate optimized "cmpw" and interchange operands */
882: opt21gen(newins,limit,index,0);
883: #endif
884: /* DONT generate optimized "cmpw" because of Interrupt
885: * After TSTW Chip Bug.
886: */
887: generate(8,NOACTION,newins->opcode & 0xFFL,NULLSYM);
888: addrgen(newins,limit,NOTYPE,1);
889: addrgen(newins,index,NOTYPE,2);
890:
891: /* jump instr. */
892: generate(0,NEWSTMT,(long)line,NULLSYM);
893: newins = (*lookup((insptr->name)+2,N_INSTALL,MNEMON)).itp;
894: jmpopgen(newins,dest);
895: } /* loop1gen */
896:
897: loop2gen(insptr,index,incr,dest)
898: instr *insptr;
899: addrmode *index, *incr, *dest;
900: {
901: /*
902: *
903: * atjnz[bhw] index,incr,dest
904: *
905: * is encoded as
906: *
907: * addw2 incr,index
908: * TST[BHW] *index
909: * jnz dest
910: *
911: */
912:
913: instr *newins;
914:
915: /* addw2 */
916: newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
917: opt21gen(newins,incr,index,1); /* optimized "add" */
918:
919: /* TST[BHW] */
920: generate(0,NEWSTMT,(long)line,NULLSYM);
921: generate(8,NOACTION,insptr->opcode,NULLSYM); /* TST opcode */
922:
923: /*
924: * To generate TST *index,
925: * must add a level of indirection to "index"
926: *
927: */
928:
929: switch(index->admode) {
930:
931: case DSPMD:
932: case EXADMD:
933: case ABSMD:
934: ++(index->admode); /* adds a level of indirection */
935: break;
936: case REGMD:
937: index->admode = DSPMD;
938: index->adexpr.exptype = ABS;
939: index->adexpr.expval = 0L;
940: index->adexpr.symptr = NULLSYM;
941: break;
942: default:
943: yyerror("Invalid `index' operand of `atjnz'");
944: break;
945: } /* switch */
946:
947: addrgen(insptr,index,NOTYPE,1);
948:
949: /* jnz */
950: generate(0,NEWSTMT,(long)line,NULLSYM);
951: newins = (*lookup("jnz",N_INSTALL,MNEMON)).itp;
952: jmpopgen(newins,dest);
953: } /* loop2gen */
954:
955: blockgen(insptr)
956: instr *insptr;
957: {
958: /*
959: *
960: * movbl[bh]
961: * is encoded as
962: *
963: * TSTW %r2
964: * BRB +12 (for half) or +14 (for byte)
965: * mov[bh] (%r0),(%r1)
966: * NOP
967: * addw2 &2,%r0 (for half) or INCW %r0 (for byte)
968: * addw2 &2,%r1 (for half) or INCW %r1 (for byte)
969: * DECW %r2
970: * BNEB -12 (for half) or -10 (for byte)
971: *
972: */
973:
974: instr *newins;
975: short byte;
976:
977: if( (insptr->tag & SHFT_MSK) == INSTRB)
978: byte = YES;
979: else
980: byte = NO;
981:
982: /* TSTW */
983: newins = (*lookup("TSTW",N_INSTALL,MNEMON)).itp;
984: generate(8,NOACTION,newins->opcode,NULLSYM); /* TSTW opcode */
985: generate(8,NOACTION,(long)(CREGMD<<4|0x02),NULLSYM); /* %r2 */
986:
987: /* BRB */
988: generate(0,NEWSTMT,(long)line,NULLSYM);
989: newins = (*lookup("BRB",N_INSTALL,MNEMON)).itp;
990: generate(8,NOACTION,newins->opcode,NULLSYM); /* unc. branch */
991: if (byte == YES)
992: generate(8,NOACTION,12L,NULLSYM);
993: else
994: generate(8,NOACTION,14L,NULLSYM);
995:
996: /* mov[bh] */
997: generate(0,NEWSTMT,(long)line,NULLSYM);
998: generate(8,NOACTION,insptr->opcode,NULLSYM); /* mov[bh] */
999: generate(8,NOACTION,(long)(CREGDFMD<<4|0x00),NULLSYM); /* (%r0) */
1000: generate(8,NOACTION,(long)(CREGDFMD<<4|0x01),NULLSYM); /* (%r1) */
1001:
1002: /*
1003: * A NOP must ne inserted here because a write to memory
1004: * was just generated.
1005: */
1006: generate(0,NEWSTMT,(long)line,NULLSYM);
1007: newins = (*lookup("NOP",N_INSTALL,MNEMON)).itp;
1008: generate(newins->nbits, NOACTION, newins->opcode, NULLSYM);
1009:
1010: generate(0,NEWSTMT,(long)line,NULLSYM);
1011: if (byte == YES) {
1012: /* INCW - increment register 0 */
1013: /* INCW - increment register 1 */
1014:
1015: newins = (*lookup("INCW",N_INSTALL,MNEMON)).itp;
1016: generate(8,NOACTION,newins->opcode,NULLSYM); /* INCW */
1017: generate(8,NOACTION,(long)(CREGMD<<4|0x00),NULLSYM); /* %r0 */
1018: generate(0,NEWSTMT,(long)line,NULLSYM);
1019: generate(8,NOACTION,newins->opcode,NULLSYM); /* INCW */
1020: generate(8,NOACTION,(long)(CREGMD<<4|0x01),NULLSYM); /* %r1 */
1021: }
1022: else {
1023:
1024: /* addw2 - increment register 0 */
1025: /* addw2 - increment register 1 */
1026: newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
1027: generate(8,NOACTION,newins->opcode,NULLSYM); /* addw2 */
1028: generate(8,NOACTION,2L,NULLSYM);
1029: generate(8,NOACTION,(long)(CREGMD<<4|0x00),NULLSYM); /* %r0 */
1030: generate(0,NEWSTMT,(long)line,NULLSYM);
1031: generate(8,NOACTION,newins->opcode,NULLSYM); /* addw2 */
1032: generate(8,NOACTION,2L,NULLSYM);
1033: generate(8,NOACTION,(long)(CREGMD<<4|0x01),NULLSYM); /* %r1 */
1034: }
1035:
1036: /* DECW */
1037: generate(0,NEWSTMT,(long)line,NULLSYM);
1038: newins = (*lookup("DECW",N_INSTALL,MNEMON)).itp;
1039: generate(8,NOACTION,newins->opcode,NULLSYM); /* DECW */
1040: generate(8,NOACTION,(long)(CREGMD<<4|0x02),NULLSYM); /* %r2 */
1041:
1042: /* BNEB */
1043: generate(0,NEWSTMT,(long)line,NULLSYM);
1044: newins = (*lookup("BNEB",N_INSTALL,MNEMON)).itp;
1045: generate(8,NOACTION,newins->opcode,NULLSYM); /* BNEB opcode */
1046: if (byte == YES)
1047: generate(8,NOACTION,-10L,NULLSYM);
1048: else
1049: generate(8,NOACTION,-12L,NULLSYM);
1050: } /* blockgen */
1051:
1052: pushopgen(insptr,opnd1)
1053: instr *insptr;
1054: addrmode *opnd1;
1055: {
1056: /*
1057: *
1058: * push[zb][bh] opnd1
1059: *
1060: * is encoded as
1061: *
1062: * addw2 &4,%sp
1063: * followed by one of the following:
1064: *
1065: * if opnd1 does not use %sp
1066: * mov[bh] {X}opnd1,{sword}-4(%sp)
1067: *
1068: * if opnd1=%sp
1069: * subw3 &4,{X}%sp,{sword}-4(%sp)
1070: *
1071: * if opnd1=expr(%sp)
1072: * mov[bh] {X}expr-4(%sp),{sword}-4(%sp)
1073: *
1074: * if opnd1=*expr(%sp)
1075: * mov[bh] {X}*expr-4(%sp),{sword}-4(%sp)
1076: *
1077: * where X = signed for push.b
1078: * unsigned for push.h
1079: */
1080:
1081: static addrmode dispsp = {NOTYPE,DSPMD,SPREG,{ABS,NULLSYM,-4L}};
1082: static addrmode immdop = {NOTYPE,IMMD,0x04,{ABS,NULLSYM,4L}};
1083: instr *newins;
1084: short expand;
1085:
1086: /* addw2 */
1087: newins = (*lookup("addw2",N_INSTALL,MNEMON)).itp;
1088: generate(8,NOACTION,newins->opcode,NULLSYM);
1089: addrgen(insptr,&immdop,NOTYPE,1);
1090: generate(8,NOACTION,(long)((CREGMD<<4)|SPREG),NULLSYM); /* operand %sp */
1091:
1092: /* decide on which second instruction to generate */
1093: switch (opnd1->admode) {
1094: case REGMD:
1095: if (opnd1->adreg == SPREG) { /* if opnd1 is %sp then */
1096: /* generate subw3 instr */
1097: newins = (*lookup("subw3",N_INSTALL,MNEMON)).itp;
1098: generate(8,NOACTION,newins->opcode,NULLSYM);
1099: addrgen(insptr,&immdop,NOTYPE,1);
1100: generate(8,NOACTION,(long)((CREGMD<<4)|SPREG),NULLSYM); /* oprnd %sp */
1101: addrgen(insptr,&dispsp,SWORD,3); /* oprnd {sword}-4(%sp) */
1102: pcintcheck(insptr,&dispsp);
1103: return;
1104: } else
1105: break;
1106: case REGDFMD:
1107: case DSPMD:
1108: case DSPDFMD:
1109: /* if register is %sp, subtract 4 from displacement */
1110: if (opnd1->adreg == SPREG)
1111: opnd1->adexpr.expval -= 4;
1112: break;
1113: } /* switch */
1114:
1115: /* mov[bh] opcode */
1116: generate(8,NOACTION,insptr->opcode,NULLSYM);
1117: switch (insptr->tag & (~IS25)) {
1118: case INSTRBW:
1119: expand = SBYTE;
1120: break;
1121: case INSTRHW:
1122: expand = UHALF;
1123: break;
1124: default:
1125: expand = NOTYPE;
1126: } /* switch */
1127:
1128: addrgen(insptr,opnd1,expand,1);
1129: addrgen(insptr,&dispsp,SWORD,2);
1130: pcintcheck(insptr,&dispsp);
1131: } /* pushopgen */
1132:
1133: shftopgen(insptr,opnd1,opnd2,opnd3)
1134: instr *insptr;
1135: addrmode *opnd1, *opnd2, *opnd3;
1136: {
1137: short expand1, expand2;
1138: long opcd, opcd2;
1139:
1140: opcd = insptr->opcode;
1141: if ((insptr->tag & IS25) &&
1142: (opnd1->admode != REGMD) && (opnd1->admode != IMMD))
1143: {
1144: expand2 = SWORD;
1145: /*
1146: * The opcode field contains 2 8-bit opcodes.
1147: * The lower opcode corresponds to the shift
1148: * word opcode. The higher opcode corresponds
1149: * either to a shift word or a shift byte opcode.
1150: * Since the shift length (opnd1) is a byte operand
1151: * in IS25, the shift byte opcode will be used if
1152: * there is one on the MAC32. If there is no shift
1153: * byte instruction, then the shift word will be used
1154: * with an expand byte of signed-byte specified.
1155: * Thus, test to see if the 2 opcodes are the same.
1156: * If so, then the expand byte must be used.
1157: */
1158: opcd2 = opcd & 0x000000FFL; /* lower 8 bits */
1159: if ((opcd >>= 8) == opcd2)
1160: expand1 = SBYTE;
1161: else
1162: expand1 = NOTYPE;
1163: }
1164: else
1165: expand1 = expand2 = NOTYPE;
1166:
1167: generate(8,NOACTION,opcd,NULLSYM);
1168: addrgen(insptr,opnd1,expand1,1);
1169: addrgen(insptr,opnd2,expand2,2);
1170: addrgen(insptr,opnd3,NOTYPE,3);
1171: } /* shftopgen */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.