|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)op.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: #include "as.h"
10:
11: /* move_op - uses two effective addresses */
12:
13: move_op( ip )
14: struct ins_bkt *ip;
15: {
16: register struct oper *op1, *op2;
17: int r1, r2;
18: /*
19: * opval_i[0] -- movX eaddr,eaddr
20: * opval_i[1] -- movl Areg,USP
21: * opval_i[2] -- movw eaddr,cc
22: * opval_i[3] -- movw cc,eaddr
23: */
24:
25: op1 = operands;
26: op2 = &operands[1];
27: r1 = (int)op1->value_o;
28: r2 = (int)op2->value_o;
29:
30: if (sr_addr(op1)){
31: wcode[0] = ip->opval_i[3];
32: if (r1 != CCREG) wcode[0] ^= 1<<9;
33: eaddr(op2, SUBOP_W, 0);
34: } else if (sr_addr(op2)){
35: wcode[0] = ip->opval_i[2];
36: if (r2 != CCREG) wcode[0] ^= 1<<9;
37: eaddr(op1, SUBOP_W, 1);
38: } else if (usp_addr(op1)) {
39: wcode[0] = ip->opval_i[1] | 0x8 | (r2 & 07);
40: } else if (usp_addr(op2)) {
41: wcode[0] = ip->opval_i[1] | (r1 & 07);
42: } else {
43: unsigned reg, mode, source;
44: wcode[0] = 0;
45: /* get source address */
46: eaddr(op1, ip->subop_i, 0);
47: source = wcode[0]; /* save it */
48: wcode[0] = 0;
49: /* get destination address */
50: eaddr(op2, ip->subop_i, 1);
51: /* flip around destination address */
52: reg = wcode[0] & 07;
53: mode = (wcode[0] >> 3) & 07;
54: /* assemble instruction */
55: wcode[0] = ip->opval_i[0] | (reg << 9) | (mode << 6) | source;
56: }
57: }
58: /* two_ops - these are of the forms:
59: xxx Dn,<eaddr>
60: xxx <eaddr>,Dn
61: xxx #yyy,<eaddr>
62: xxx <eaddr>,An
63: */
64:
65: two_op( ip )
66: register struct ins_bkt *ip;
67: {
68: register struct oper *op1, *op2;
69: int r1, r2;
70: int wrtflg = ip->touchop_i&TOUCH2((BW|WW|LW)); /* 2nd operand write-to unless compare */
71: subop_t size = ip->subop_i;
72: op1 = &operands[0];
73: op2 = &operands[1];
74: r1 = (int)op1->value_o & 07;
75: r2 = (int)op2->value_o & 07;
76:
77: /*
78: * opval_i[0] -- op eaddr,dreg
79: * opval_i[1] -- op eaddr,areg
80: * opval_i[2] -- op #imm,eaddr OR 0xffff
81: * opval_i[3] -- op #imm,cc
82: */
83:
84: if (areg_addr(op2)){
85: /* addl xxx,a0 */
86: wcode[0] = ip->opval_i[1] |(r2<<9);
87: eaddr(op1, size, 0);
88: } else if (op1->type_o == T_IMMED && ip->opval_i[2] != 0xffff ) {
89: if (sr_addr(op2)){
90: /* andb #imm,cc */
91: wcode[0] = ip->opval_i[3];
92: /* byte-size to cc only, word-size to sr only */
93: if (!((op2->value_o == SRREG) ^ (size == SUBOP_B)))
94: PROG_ERROR( E_OPERAND );
95: rel_val(op1, (size==SUBOP_L)?SUBOP_L:SUBOP_W, 0);
96: } else {
97: /* andw #imm,eaddr */
98: wcode[0] = ip->opval_i[2];
99: rel_val(op1, (size==SUBOP_L)?SUBOP_L:SUBOP_W, 0);
100: eaddr(op2, size, wrtflg);
101: }
102: } else {
103: wcode[0] = ip->opval_i[0];
104: /* notice closely:
105: * op d0,d1
106: * appears ambiguous. Actually, it is not.
107: * eor takes register only as source. other ops only
108: * as destination.
109: */
110: if (!dreg_addr(op2) || ip->op_i == OP_EOR) {
111: /* op dreg,eaddr & eorl dreg,dreg */
112: wcode[0] |= 0400|(r1<<9);
113: eaddr(op2, size, wrtflg);
114: } else {
115: /* op eaddr,dreg and op dreg,dreg */
116: /* note that mulu #imm,dreg ends up here, too */
117: wcode[0] |= (r2 << 9);
118: eaddr(op1, size, 0);
119: }
120: }
121: }
122: /* one_ops - install opr, check for exactly one operand and compute eaddr */
123:
124: one_op( ip )
125: struct ins_bkt *ip;
126: {
127: register struct oper *op = operands;
128: wcode[0] = ip->opval_i[0];
129: switch (ip->op_i){
130: case OP_CALL:
131: case OP_BRANCH:
132: if (jsrflag && op->type_o == T_NORMAL && op->sym_o != 0){
133: /* make this a pc-relative */
134: /*
135: op->value_o -= dot+2;
136: */
137: op->type_o = T_PCPLUS; /* MAGIC!! */
138: op->reg_o = PCREG;
139: }
140: }
141: eaddr(op, ip->subop_i, ip->touchop_i&TOUCH1(LW|WW|BW));
142: }
143:
144:
145: /* no_op(opr) -- places opr in wcode[0]. */
146:
147: no_op(ip)
148: struct ins_bkt *ip;
149: {
150: wcode[0] = ip->opval_i[0];
151: };
152:
153: /* branch_op - process branch offsets */
154: /* also handle DBcc instructions */
155: branch_op(ip)
156: struct ins_bkt *ip;
157: {
158: long offs = 0;
159: register struct oper *opp = operands;
160:
161: wcode[0] = ip->opval_i[0];
162: if (ip->noper_i == 2){
163: wcode[0] |= opp->value_o;
164: opp += 1;
165: }
166: if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){
167: /* external branch -- good luck */
168: ;
169: } else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){
170: PROG_ERROR(E_RELOCATE);
171: } else {
172: opp->sym_o = 0; /* mark as non relocateable expression */
173: }
174: offs = opp->value_o - (dot + 2);
175: if (offs > 32767L || offs < -32768L)
176: PROG_ERROR(E_OFFSET);
177: opp->value_o = (int)offs;
178: rel_val(opp, SUBOP_W, opp->sym_o != 0);
179: }
180:
181:
182: brnchs_op(ip)
183: struct ins_bkt *ip;
184: {
185: long offs = 0;
186: register struct oper *opp = operands;
187:
188: wcode[0] = ip->opval_i[0];
189: if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){
190: /* external branch -- out of luck */
191: PROG_ERROR(E_RELOCATE);
192: } else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){
193: PROG_ERROR(E_RELOCATE);
194: }
195: offs = opp->value_o - (dot + 2);
196: if (offs > 127 || offs < -128)
197: PROG_ERROR(E_OFFSET);
198: if (offs != 0){
199: wcode[0] |= offs & 0377;
200: } else if ( ip->op_i != OP_CALL ){
201: /*
202: * this is not a bsr, and we have a PC-relative address of zero
203: * if we just spit this out as usual, it would look just like
204: * the beginning of a longer form of jump. So instead,
205: * we emit a "nop" instruction right here.
206: */
207: wcode[0] = 0x4e71;
208: } else {
209: PROG_ERROR(E_OFFSET);
210: }
211: }
212:
213: /* it is not clear that we can get there from here.
214: * If this is a 68020 instruction generation, then we can use
215: * the long form of the branch. Otherwise, if this is an
216: * unconditional, then we can use a long jump. Otherwise,
217: * we must generate a branch-around-a-jump.
218: */
219: brnchl_op(ip)
220: struct ins_bkt *ip;
221: {
222: register struct oper *opp = &operands[0];
223: int offs;
224: if (ext_instruction_set){
225: wcode[0] = ip->opval_i[0] | 0377;
226: if (opp->sym_o && ((opp->sym_o->attr_s & S_DEF) == 0)){
227: /* external branch -- good luck */
228: ;
229: } else if ((opp->sym_o==0) || (opp->sym_o->csect_s!=cur_csect_name)){
230: /* PROG_ERROR(E_RELOCATE); */
231: } else {
232: opp->sym_o = 0; /* mark as non relocateable expression */
233: }
234: offs = opp->value_o - (dot + 2);
235: opp->value_o = (int)offs;
236: rel_val(opp, SUBOP_L, opp->sym_o != 0);
237: } else {
238: /* this is not an extended-instruction set assembly */
239: hard_branch( ip, opp );
240: }
241: }
242:
243: static
244: hard_branch( ip, opp )
245: register struct ins_bkt *ip;
246: register struct oper *opp;
247: {
248: /* choose alternate opcode -- either long form or complement */
249: wcode[0] = ip->opval_i[1];
250: /*
251: * if we are unconditional, just use the long mode.
252: * otherwise, do the jump-around-jump
253: */
254: if (ip->subop_i == JALL){
255: if (jsrflag && opp->type_o == T_NORMAL && opp->sym_o != 0){
256: /* make this a pc-relative */
257: /*
258: opp->value_o -= dot+2;
259: */
260: opp->type_o = T_PCPLUS; /* MAGIC!! */
261: opp->reg_o = PCREG;
262: }
263: eaddr(opp, SUBOP_L, 0);
264: return;
265: } else if (d2flag && (opp->type_o == T_NORMAL) ){
266: /* we're really doing short displacements, anyway */
267: branch_op( ip );
268: return;
269: } else {
270: /* use complementary branch over jump */
271: /* we'll fool eaddr() by building the jump instruction in wcode[0], then moving it */
272: /* its address word, though, must be built in the right place */
273: wcode[0] = 0x4EC0; /* jmp xxxxxx */
274: code_length = 4; /* so far */
275: eaddr(opp, SUBOP_L, 0); /* the address */
276: wcode[1] = wcode[0];
277: wcode[0] = ip->opval_i[1] + code_length - 2;
278: }
279: }
280: /*
281: * generate a short or a long branch instruction as appropriate
282: * note that:
283: * jra foo
284: * foo:
285: * is translated (by brnchs_op) to a nop. If we attempt to
286: * optimize this to generate no code, then after resolving
287: * the span-dependent instructions, the value of
288: * foo is the same as the address of the jra instruction.
289: * Therefore, on pass 2, the jra looks like a jra .
290: * Presumably, this could be fixed by keeping more information
291: * after the sdi's are resolved
292: */
293: jbrnch_op( ip )
294: struct ins_bkt *ip;
295: {
296: long offs = 0;
297: register struct oper *opp = operands;
298: int longsize, longsdi, useshort;
299:
300: if (opp->type_o != T_NORMAL || opp->sym_o == NULL) {
301: /* not a relocatable operand */
302: hard_branch( ip, opp );
303: } else {
304: offs = opp->value_o - (dot + 2);
305: if (hflag && ip->op_i != OP_CALL)
306: useshort = 1;
307: else
308: useshort = d2flag||jsrflag;
309: if ((ip->subop_i == JALL) || ext_instruction_set){
310: longsize = 6;
311: longsdi = SDI6;
312: } else {
313: longsize = 8;
314: longsdi = SDI8;
315: }
316: if (opp->flags_o & O_COMPLEX) /* not a simple address */
317: hard_branch( ip, opp );
318: else if (pass == 1){
319: if (cansdi) {
320: if (ip->op_i == OP_CALL && !Oflag &&
321: operands->sym_o->value_s == 0 )
322: /* jbsr w/ forward reference */
323: goto no_sdi;
324: code_length = makesdi(opp, dot + 2,
325: useshort ? SDI4 : longsdi);
326: }
327: else
328: no_sdi:
329: code_length = useshort? 4 : longsize;
330: put_rel( opp, SUBOP_L, dot+2, 0); /* may be to external */
331: } else {
332: /* pass 2 */
333: if (opp->sym_o == 0
334: || opp->sym_o->csect_s != cur_csect_name
335: || offs < -32768L || offs > 32767L
336: || !cansdi ){
337: #ifdef EBUG
338: if (debflag>1)
339: printf("jbrnch(2): external branch line %d offset 0x%X\n",
340: line_no, dot);
341: #endif
342: if (useshort) branch_op(ip);
343: else brnchl_op( ip );
344: }else if (ip->op_i == OP_CALL && !Oflag &&
345: (operands->sym_o->value_s == 0 ||
346: operands->sym_o->value_s > dot ) ){
347: cansdi = 0; /* fake temperarily */
348: hard_branch(ip, opp);
349: cansdi = 1;
350: }else if (offs > 127 || offs < -128){
351: #ifdef EBUG
352: if (debflag>1)
353: printf("jbrnch(2): 4 byte branch line %d offset 0x%X\n",
354: line_no, dot);
355: #endif
356: branch_op(ip);
357: }else{
358: #ifdef EBUG
359: if (debflag>1)
360: printf("jbrnch(2): 2 byte branch line %d offset 0x%X\n",
361: line_no, dot);
362: #endif
363: brnchs_op(ip);
364: }
365: }
366: }
367: return;
368: }
369:
370: /*
371: * instructions of the form xxx Ax@+,Ay@+
372: * and those of the forms xxx Dx,Dy
373: * or xxx Ax@-,Ay@-
374: */
375:
376: regmem_op(ip)
377: struct ins_bkt *ip;
378: {
379: wcode[0] = ip->opval_i[0]
380: | (operands[0].value_o&07) | ((operands[1].value_o&07)<<9);
381: if (operands[0].type_o == T_PREDEC ) {
382: wcode[0] |= 010;
383: }
384: }
385:
386: /*
387: * quick_op -- instructions such as "addqw #7,d0"
388: */
389:
390: quick_op( ip )
391: struct ins_bkt *ip;
392: {
393: register int val = operands[0].value_o;
394: if ( val <= 0 || val > 8 )
395: PROG_ERROR( E_CONSTANT);
396: if (val == 8 )
397: val = 8;
398: wcode[0] = ip->opval_i[0] | (val<<9);
399: eaddr( &operands[1], ip->subop_i, 0);
400: }
401:
402: /* shift op - shift either a register or an effective address */
403:
404: shift_op( ip )
405: struct ins_bkt *ip;
406: {
407: register struct oper *op1, *op2;
408: op1 = &operands[0];
409: op2 = &operands[1];
410: /*
411: * opval_i[0] -- register-shift opcode
412: * opval_i[1] -- memory-shift opcode
413: */
414:
415: if (numops == 1) {
416: wcode[0] = ip->opval_i[1];
417: eaddr(op1, SUBOP_W, 1);
418: } else {
419: int val1, val2;
420: wcode[0] = ip->opval_i[0];
421: val1 = (int)op1->value_o;
422: val2 = (int)op2->value_o;
423: if (op1->type_o==T_IMMED) {
424: if (val1 == 8) val1 = 0;
425: } else {
426: wcode[0] |= 040;
427: }
428: wcode[0] |= ((val1 & 07) << 9) | (val2 & 07);
429: }
430: }
431: /* bit_op - of the form xxx Dn,<eaddr> or xxx #nnn,<eaddr> */
432:
433: bit_op( ip )
434: struct ins_bkt *ip;
435: {
436: register struct oper *op1 ;
437: /*
438: * opval_i[0] -- bit number dynamic
439: * opval_i[1] -- bit number static
440: */
441: op1 = operands;
442:
443: wcode[0] = ip->opval_i[0];
444: if (op1->type_o == T_REG ) {
445: /* <eaddr> is destination */
446: wcode[0] = ip->opval_i[0] | ((int)op1->value_o << 9);
447: eaddr(&operands[1], SUBOP_W, 1);
448: } else {
449: wcode[0] = ip->opval_i[1];
450: rel_val(op1, SUBOP_W, 0);
451: eaddr(&operands[1], SUBOP_W, 1);
452: }
453: }
454:
455: /*
456: * bitf_op -- single-operand bit-field instructions
457: */
458: bitf_op( ip )
459: struct ins_bkt *ip;
460: {
461: register struct oper *o = &operands[0];
462: register flags = o->flags_o;
463: wcode[0] = ip->opval_i[0];
464: if (!(flags&O_BFLD))
465: PROG_ERROR(E_OPERAND);
466: wcode[1] = 0;
467: if (flags&O_BFOREG)
468: wcode[1] |= 1<<11;
469: wcode[1] |= o->bfoffset_o << 6;
470: if (flags&O_BFWREG)
471: wcode[1] |= 1<<5;
472: wcode[1] |= o->bfwidth_o;
473: code_length += 2;
474: o->flags_o &= ~O_BFLD;
475: eaddr( o, SUBOP_W, 1);
476: }
477:
478: /*
479: * bitfr_op -- bit-field + register instructions.
480: */
481: bitfr_op( ip )
482: struct ins_bkt *ip;
483: {
484: struct oper * r ;
485: int reg;
486: r = &operands[0];
487: if (!(r->flags_o&O_BFLD)){
488: /* first operand register */
489: /* extract value, slide on down */
490: reg = r->value_o;
491: *r = operands[1];
492: } else {
493: /* second operand register */
494: /* just extract value */
495: reg = operands[1].value_o;
496: }
497: bitf_op( ip ); /* do most of the work; */
498: wcode[1] |= reg << 12; /* finish off */
499: }
500:
501: /* exg_op - instructions like exg rx,ry */
502:
503: exg_op( ip )
504: struct ins_bkt *ip;
505: {
506: int r1, r2;
507: register struct oper *op1, *op2;
508: op1 = operands;
509: op2 = &operands[1];
510: r1 = (int)op1->value_o;
511: r2 = (int)op2->value_o;
512:
513: wcode[0] = ip->opval_i[0];
514: if (dreg(r1) && dreg(r2))
515: wcode[0] |= 0100 | (r1 << 9) | r2;
516: else if (areg(r1) && areg(r2))
517: wcode[0] |= 0110 | ((r1 & 07) << 9) | (r2 & 07);
518: else if (areg(r1) && dreg(r2))
519: wcode[0] |= 0210 | (r2 << 9) | (r1 & 07);
520: else if (dreg(r1) && areg(r2))
521: wcode[0] |= 0210 | (r1 << 9) | (r2 & 07);
522: else
523: PROG_ERROR( E_OPERAND );
524: }
525: /* reg_op - instructions that take one register operand */
526:
527: reg_op( ip )
528: struct ins_bkt *ip;
529: {
530: wcode[0] = ip->opval_i[0] | (operands[0].value_o & 07);
531: }
532:
533:
534: /* link_op - form: link An,#<disp> */
535:
536: link_op( ip )
537: struct ins_bkt *ip;
538: {
539: register int v = operands[1].value_o;
540: /*
541: * opval_i[0] -- normal short form
542: * opval_i[1] -- extended long form
543: */
544: if ( (ip->opval_i[0] == 0) || /* If linkl requested specifically, */
545: v < -32768 || v > 32767 || /* or displacement too big for linkw, */
546: !( operands[1].sym_o == NULL || operands[1].sym_o->attr_s & S_DEF))
547: /* or displacement is relocatable !!, */
548: { /* try long form. */
549: if (ext_instruction_set /* If generating 68020 code, */
550: && (ip->opval_i[1] != 0)) /* and linkw not requested specifically, */
551: { /* try long form. */
552: if (!(operands[1].sym_o==NULL || operands[1].sym_o->attr_s&S_DEF)
553: && pass==1 && cansdi){
554: (void)makeddi( &operands[1], dot+code_length, SDIL, 0);
555: }
556: wcode[0] = ip->opval_i[1] | (operands[0].value_o & 07);
557: rel_val(&operands[1], SUBOP_L, 0);
558: return;
559: } else if ( v < -32768 || v > 32767)
560: PROG_ERROR(E_CONSTANT);
561: /* else is external -- take pot luck */
562: }
563: wcode[0] = ip->opval_i[0] | (operands[0].value_o & 07);
564: rel_val(&operands[1], SUBOP_W, 0);
565: }
566:
567:
568: /* movec_op - for the very weird movc instruction: movec rn,rc */
569: /* where rc is in { usp, sfc, dfc, vbr } */
570:
571: movec_op( ip )
572: struct ins_bkt *ip;
573: {
574: register struct oper *op1, *op2;
575: register reg;
576: register creg;
577: static ctrl_reg_values[] =
578: /* USP SFC DFC VBR CACR CAAR MSP ISP */
579: { 0x800, 0, 1, 0x801, 2, 0x802, 0x803, 0x804 };
580: op1 = operands;
581: op2 = &operands[1];
582: wcode[0] = ip->opval_i[0];
583: code_length = 4;
584: if (ctrl_reg(op1->value_o)){
585: /* from control reg to user reg */
586: creg = op1->value_o;
587: reg = op2->value_o;
588: }else {
589: /* from user reg to control reg */
590: wcode[0] |= 1;
591: creg = op2->value_o;
592: reg = op1->value_o;
593: }
594: creg = ctrl_reg_values[ creg - USPREG ];
595: wcode[1] = ((reg&07)<<12) | creg;
596: if(areg(reg)){
597: wcode[1] |= 0x8000;
598: }
599: }
600:
601: /* moves_op - for the very weird movs instruction: */
602: /* moves rn,eaddr or moves eaddr,rn */
603:
604: moves_op( ip )
605: struct ins_bkt *ip;
606: {
607: register struct oper *op1, *op2;
608: register reg;
609: op1 = operands;
610: op2 = &operands[1];
611: wcode[0] = ip->opval_i[0];
612: code_length = 4;
613: if ( op1->type_o == T_REG ){
614: /* from register to other space */
615: reg = op1->value_o;
616: wcode[1] = 1<<11;
617: eaddr( op2, ip->subop_i, 1);
618: } else {
619: /* from outer space to register */
620: reg = op2->value_o;
621: wcode[1] = 0;
622: eaddr( op1, ip->subop_i, 0);
623: }
624: wcode[1] |= (reg&07)<<12;
625: if(areg(reg)){
626: wcode[1] |= 0x8000;
627: }
628: }
629:
630:
631: int reverse_bits( forward )
632: int forward ;
633:
634: /*
635: result = forward with with 16 low order bits in reverse order.
636: */
637:
638: {
639: int bit, new ;
640: long i ;
641:
642: new = 0 ;
643: bit = 0x8000 ;
644:
645: for (i=0 ; i<16 ; i++ )
646: {
647: if (forward & 1) new |= bit ;
648: forward = forward >> 1 ;
649: bit = bit >> 1 ;
650: }
651: return(new) ;
652: }
653:
654: /* movem_op - of the form: movem #xxx,<eaddr> or movem <eaddr>,#xxx */
655:
656: movem_op( ip )
657: struct ins_bkt *ip;
658: {
659: register struct oper *op1, *op2;
660: op1 = operands;
661: op2 = &operands[1];
662: switch (op1->type_o)
663: {
664: case T_REGLIST: /* movem <reglist>,<ea> */
665: if (op2->type_o == T_PREDEC) /* reverse mask for an@- */
666: op1->value_o = reverse_bits(op1->value_o) ;
667: case T_IMMED: /* movem #xxx,<ea> */
668: {
669: wcode[0] = ip->opval_i[0];
670: rel_val(op1, SUBOP_W, 0);
671: eaddr(op2, SUBOP_W, 1);
672: break ;
673: }
674: default:
675: {
676: /* movem <ea>,#xxx */
677: /* movem <ea>,<reglist> */
678: wcode[0] = ip->opval_i[1];
679: rel_val(op2, SUBOP_W, 0);
680: eaddr(op1, SUBOP_W, 0);
681: }
682: }
683: }
684:
685: /* movep_op - of the form: movep Dx,Ay@(d) or movep Ay@(d),Dx */
686:
687: movep_op(ip)
688: struct ins_bkt *ip;
689: {
690: register struct oper *op1, *op2;
691: int r1, r2;
692: /*
693: * opval_i[0] -- memory-to-register
694: * opval_i[1] -- register-to-memory
695: */
696: op1 = operands;
697: op2 = &operands[1];
698: r1 = (int)op1->value_o;
699: r2 = (int)op2->value_o;
700: if (op1->type_o == T_REG ) {
701: /* register-to-memory */
702: wcode[0] = ip->opval_i[1] | (r1 << 9) | (op2->reg_o & 07);
703: rel_val(op2, SUBOP_W, 0);
704: } else {
705: /* memory-to-register */
706: wcode[0] = ip->opval_i[0] | (r2 << 9) | (op1->reg_o & 07);
707: rel_val(op1, SUBOP_W, 0);
708: }
709: }
710:
711:
712: /* moveq - form: moveq #<data>,Dn */
713:
714: moveq_op( ip )
715: struct ins_bkt *ip;
716: {
717: register struct oper *op1, *op2;
718: int r2;
719: op1 = operands;
720: op2 = &operands[1];
721: r2 = (int)op2->value_o;
722: if (op1->value_o > 0177 || op1->value_o < -0200)
723: PROG_ERROR(E_CONSTANT);
724: wcode[0] = ip->opval_i[0] | (r2 << 9) | ((short)op1->value_o & 0377);
725: }
726:
727:
728: /* trap - form: trap #xxx */
729:
730: trap( ip )
731: struct ins_bkt *ip;
732: {
733: wcode[0] = ip->opval_i[0] | (((char)operands[0].value_o) & 017);
734: }
735:
736: /* stop instruction -- form is stop #xxxx */
737: stop( ip )
738: struct ins_bkt *ip;
739: {
740: wcode[0] = ip->opval_i[0];
741: rel_val( &operands[0], ip->subop_i, 0 );
742: }
743:
744: /* rts instruction -- may or may not take an operand */
745: rts_op( ip )
746: struct ins_bkt *ip;
747: {
748: register struct oper *opp = operands;
749: /*
750: * opval_i[0] -- no operand
751: * opval_i[1] -- one operand
752: */
753: if (numops == 1){
754: /* new form -- with operand */
755: wcode[0] = ip->opval_i[1];
756: wcode[1] = 0xffff & opp->value_o;
757: code_length = 4;
758: } else {
759: wcode[0] = ip->opval_i[0];
760: }
761: }
762:
763: /*
764: * chk2_op -- instructions of chk2X and cmp2X families:
765: * take register number (plus one bit) in an extension word
766: */
767: chk2_op( ip )
768: struct ins_bkt *ip;
769: {
770: /*
771: * opval_i[0] -- opcode
772: * opval_i[1] -- extension word
773: */
774: wcode[0] = ip->opval_i[0];
775: wcode[1] = ip->opval_i[1] | ( operands[1].value_o<<12 );
776: code_length += 2;
777: eaddr( &operands[0], ip->subop_i, 0 );
778: }
779:
780: /*
781: * div_op -- long-form divide and multiply instructions that take
782: * a register or register pair as operands
783: */
784: div_op( ip )
785: struct ins_bkt *ip;
786: {
787: /*
788: * opval_i[0] -- opcode
789: * opval_i[1] -- extension word
790: * opval_i[2] -- alternate extension word to be used if regpair 2nd operand
791: */
792: wcode[0] = ip->opval_i[0];
793: if (operands[1].type_o == T_REGPAIR){
794: wcode[1] = ip->opval_i[2] | (operands[1].reg_o<<12) | operands[1].value_o;
795: } else {
796: wcode[1] = ip->opval_i[1] | (operands[1].value_o<<12) | operands[1].value_o;
797: }
798: code_length += 2;
799: eaddr( &operands[0], SUBOP_L, 0 );
800: }
801:
802: /* callm_op -- process the callm instruction */
803: callm_op( ip )
804: struct ins_bkt *ip;
805: {
806: wcode[0] = ip->opval_i[0];
807: wcode[1] = operands[0].value_o;
808: code_length += 2;
809: eaddr( &operands[1], SUBOP_L, 0 );
810: }
811:
812: /*
813: * cas1_op -- stupid comapare & set.
814: */
815: cas1_op( ip )
816: struct ins_bkt *ip;
817: {
818: wcode[0] = ip->opval_i[0];
819: wcode[1] = (operands[1].value_o<<6) + (operands[0].value_o);
820: code_length += 2;
821: eaddr( &operands[2], ip->subop_i, 1);
822: }
823:
824: /*
825: * cas2_op -- stupid comapare & set.
826: */
827: cas2_op( ip )
828: struct ins_bkt *ip;
829: {
830: register struct oper * op = &operands[0];
831: wcode[0] = ip->opval_i[0];
832: wcode[1] = (op[2].value_o<<12) + (op[1].value_o<<6) + (op[0].value_o);
833: wcode[2] = (op[2].reg_o<<12) + (op[1].reg_o<<6) + (op[0].reg_o);
834: code_length += 4;
835: }
836:
837: /*
838: * pack_op -- the ridiculous bcd pack instruction.
839: */
840: pack_op( ip )
841: struct ins_bkt *ip;
842: {
843: wcode[0] = ip->opval_i[0] | ((operands[0].type_o==T_REG)?0 : (1<<3));
844: wcode[0] |= operands[0].value_o&07 | ((operands[1].value_o&07)<<9);
845: rel_val( &operands[2], SUBOP_W, 0);
846: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.