|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)coprocessor.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: cp_general( ip )
12: struct ins_bkt *ip ;
13:
14: {
15: struct oper *op1, *op2 ;
16: unsigned r1, r2 ;
17:
18: /*
19: opval_i[0] -- fop ea,fpn
20: opval_i[1] -- fop fpm,fpn
21: */
22:
23: op1 = &operands[0] ;
24: op2 = &operands[1] ;
25: r2 = (int) op2 -> value_o - FP0REG ;
26: code_length = 4 ;
27: wcode[0] = 0xf000 + current_cpid * 01000 ;
28:
29: if (freg_addr(op1))
30: {
31: r1 = (int) op1 -> value_o - FP0REG ;
32: wcode[1] = ip->opval_i[1] + r2 * 0200 + r1 * 02000 ;
33: }
34: else
35: {
36: wcode[1] = ip->opval_i[0] + r2 * 0200 ;
37: eaddr( op1, ip->subop_i, 0) ;
38: }
39: }
40:
41: cp_oneop( ip )
42: struct ins_bkt *ip ;
43:
44: {
45: struct oper *op1;
46: unsigned r1;
47:
48: /*
49: opval_i[0] -- fop ea
50: opval_i[1] -- fop fpm
51: */
52:
53: op1 = &operands[0] ;
54: code_length = 4 ;
55: wcode[0] = 0xf000 + current_cpid * 01000 ;
56:
57: if (freg_addr(op1))
58: {
59: r1 = (int) op1 -> value_o - FP0REG ;
60: wcode[1] = ip->opval_i[1] + r1 * 02000 ;
61: }
62: else
63: {
64: wcode[1] = ip->opval_i[0] ;
65: eaddr( op1, ip->subop_i, 0) ;
66: }
67: }
68:
69: cp_move( ip )
70: struct ins_bkt *ip ;
71:
72: {
73: struct oper *op1, *op2 ;
74: unsigned r1, r2 ;
75:
76: /*
77: opval_i[0] -- fmov? ea,fpn
78: opval_i[1] -- fmov? fpm,ea
79: opval_i[2] -- fmovx fpm,fpn
80: -- fmovl ea,fpctrl
81: opval_i[3] -- fmovl fpctrl,ea
82:
83: */
84:
85: op1 = &operands[0] ;
86: op2 = &operands[1] ;
87: r1 = (int) op1 -> value_o - FP0REG ;
88: r2 = (int) op2 -> value_o - FP0REG ;
89: code_length = 4 ;
90: wcode[0] = 0xf000 + current_cpid * 01000 ;
91:
92: if (freg_addr(op1))
93: {
94: if (freg_addr(op2))
95: { /* fmovx fpm,fpn */
96: wcode[1] = ip->opval_i[2] + r1 * 02000 + r2 * 0200 ;
97: }
98: else
99: { /* fmov? fpm,ea */
100: wcode[1] = ip->opval_i[1] + r1 * 0200 ;
101: eaddr( op2, ip->subop_i, 1) ;
102: }
103: }
104: else
105: if (freg_addr(op2))
106: { /* fmov? ea,fpn */
107: wcode[1] = ip->opval_i[0] + r2 * 0200 ;
108: eaddr( op1, ip->subop_i, 0) ;
109: }
110: else
111: {
112: if (fctrlreg_addr(op2))
113: { /* fmovl ea,fpctrl */
114: switch((int) op2->value_o)
115: {
116: case FPCREG: { r2 = 4 ; break ; }
117: case FPSREG: { r2 = 2 ; break ; }
118: case FPIREG: { r2 = 1 ; break ; }
119: }
120: wcode[1] = ip->opval_i[2] + r2 * 02000 ;
121: eaddr( op1, ip->subop_i, 0) ;
122: }
123: else
124: { /* fmovl fpctrl,ea */
125: switch((int) op1->value_o)
126: {
127: case FPCREG: { r2 = 4 ; break ; }
128: case FPSREG: { r2 = 2 ; break ; }
129: case FPIREG: { r2 = 1 ; break ; }
130: }
131: wcode[1] = ip->opval_i[3] + r2 * 02000 ;
132: eaddr( op2, ip->subop_i, 0) ;
133: }
134: }
135: }
136:
137: cp_regpair( ip )
138: struct ins_bkt *ip ;
139:
140: /* Works like cp_general except the result is put in a PAIR
141: * of fp registers.
142: */
143:
144: {
145: struct oper *op1, *op2 ;
146: unsigned r1, r2, r3 ;
147:
148: /*
149: opval_i[0] -- fop ea,fpn:fpq
150: opval_i[1] -- fop fpm,fpn:fpq
151: */
152:
153: op1 = &operands[0] ;
154: op2 = &operands[1] ;
155: r2 = (int) op2 -> reg_o - FP0REG ;
156: r3 = (int) op2 -> value_o - FP0REG ;
157: code_length = 4 ;
158: wcode[0] = 0xf000 + current_cpid * 01000 ;
159:
160: if (freg_addr(op1))
161: {
162: r1 = (int) op1 -> value_o - FP0REG ;
163: wcode[1] = ip->opval_i[1] + r2 * 0200 + r1 * 02000 + r3 ;
164: }
165: else
166: {
167: wcode[1] = ip->opval_i[0] + r2 * 0200 + r3 ;
168: eaddr( op1, ip->subop_i, 0) ;
169: }
170: }
171:
172: cp_movecr( ip )
173: struct ins_bkt *ip ;
174:
175: /*
176:
177: For general format coprocessor instructions that put an immediate
178: operand in the op code extension field.
179:
180: */
181:
182: {
183: struct oper *op1, *op2 ;
184: unsigned r1, r2 ;
185:
186: /*
187: opval_i[0] -- fop #ccc,fpn
188: */
189:
190: op1 = &operands[0] ;
191: op2 = &operands[1] ;
192: r2 = (int) op2 -> value_o - FP0REG ;
193: code_length = 4 ;
194: wcode[0] = 0xf000 + current_cpid * 01000 ;
195: wcode[1] = ip->opval_i[0] + r2 * 0200 + op1->value_o ;
196: }
197:
198:
199: int reverse_8bits( forward )
200: int forward ;
201:
202: /*
203: result = forward with with 8 low order bits in reverse order.
204: */
205:
206: {
207: int bit, new ;
208: long i ;
209:
210: new = 0 ;
211: bit = 0x80 ;
212:
213: for (i=0 ; i<8 ; i++ )
214: {
215: if (forward & 1) new |= bit ;
216: forward = forward >> 1 ;
217: bit = bit >> 1 ;
218: }
219: return(new) ;
220: }
221:
222: cp_movem( ip )
223: struct ins_bkt *ip ;
224:
225: /*
226:
227: Floating move multiples come in too many varieties:
228:
229: fmovem ea,#imm
230: fmovem ea,freglist
231: fmovem ea,dn
232: fmovem ea,fcreglist
233: fmovem #imm,ea
234: fmovem #imm,sp@-
235: fmovem freglist,ea
236: fmovem freglist,sp@-
237: fmovem dn,ea
238: fmovem dn,sp@-
239: fmovem fcreglist,ea
240:
241: */
242:
243: {
244: struct oper *op1, *op2 ;
245:
246: /*
247: opval_i[0] -- fmovem ea,#imm or freglist or dn
248: opval_i[1] -- fmovem ...,ea
249: opval-i[2] -- fmovem ea,fcreglist
250: opval-i[3] -- fop fcreglist,ea
251: */
252:
253: op1 = &operands[0] ;
254: op2 = &operands[1] ;
255: code_length = 4 ;
256: wcode[0] = 0xf000 + current_cpid * 01000 ;
257: switch (op2->type_o)
258: {
259: case T_FCREGLIST:/* fmovem ea,fcreglist */
260: {
261: wcode[1] = ip->opval_i[2] + op2->value_o * 0x400 ;
262: eaddr( op1, ip->subop_i, 0) ;
263: break ;
264: }
265: case T_IMMED: /* fmovem ea,#imm */
266: {
267: wcode[1] = ip->opval_i[0] + op2->value_o ;
268: eaddr( op1, ip->subop_i, 0) ;
269: break ;
270: }
271: case T_FREGLIST:/* fmovem ea,freglist */
272: {
273: wcode[1] = ip->opval_i[0] + reverse_8bits(op2->value_o) ;
274: eaddr( op1, ip->subop_i, 0) ;
275: break ;
276: }
277: case T_REG: /* fmovem ea,dn */
278: {
279: wcode[1] = ip->opval_i[0] + 0x800 + (op2->value_o-D0REG)*0x10;
280: eaddr( op1, ip->subop_i, 0) ;
281: break ;
282: }
283: default:
284: {
285: switch(op1->type_o)
286: {
287: case T_FCREGLIST:/* fmovem fcreglist,ea */
288: {
289: wcode[1] = ip->opval_i[3] + op1->value_o * 0x400 ;
290: break ;
291: }
292: case T_IMMED: /* fmovem #imm,ea */
293: {
294: wcode[1] = ip->opval_i[1] + op1->value_o ;
295: if (op2->type_o != T_PREDEC) wcode[1] |= 0x1000 ;
296: break ;
297: }
298: case T_FREGLIST:/* fmovem freglist,ea */
299: {
300: wcode[1] = ip->opval_i[1] ;
301: if (op2->type_o == T_PREDEC)
302: wcode[1] |= op1->value_o ;
303: else
304: wcode[1] |= 0x1000 | reverse_8bits(op1->value_o);
305: break ;
306: }
307: case T_REG: /* fmovem dn,ea */
308: {
309: wcode[1] = ip->opval_i[1] + 0x800 + (op1->value_o-D0REG)*0x10;
310: if (op2->type_o != T_PREDEC) wcode[1] |= 0x1000 ;
311: break ;
312: }
313: }
314: eaddr( op2, ip->subop_i, 1) ;
315: }
316: }
317: }
318:
319: cp_oneword( ip )
320: struct ins_bkt *ip ;
321:
322: /* For one word coprocessor instructions like FSAVE and FRESTORE. */
323:
324: {
325: struct oper *op1 ;
326:
327: /*
328: opval_i[0] -- fop ea
329: */
330:
331: op1 = &operands[0] ;
332: wcode[0] = ip->opval_i[0] + current_cpid * 01000 ;
333: eaddr( op1, ip->subop_i, 0) ;
334:
335: }
336:
337: cp_branch( ip )
338: struct ins_bkt *ip ;
339:
340: /* For coprocessor 16, 32, and indeterminate branches. */
341:
342: {
343: long offs = 0;
344: register struct oper *opp = operands;
345: int offlong, instlong ;
346: int useshort;
347:
348: wcode[0] = ip->opval_i[0] + current_cpid * 01000 ;
349: if (ip->noper_i == 0)
350: { /* fnop */
351: code_length = 4 ;
352: wcode[1] = 0 ;
353: return ;
354: }
355: offs = opp->value_o - (dot + 2);
356: if (hflag )
357: useshort = 1;
358: else
359: useshort = d2flag||jsrflag;
360: if (opp->flags_o & O_COMPLEX) {
361: /* not a simple address */
362: opp->value_o = (int) offs;
363: rel_val(opp, SUBOP_W, opp->sym_o != 0);
364: return;
365: }
366: if (pass == 1 ) {
367: if (cansdi)
368: code_length += useshort? 2 : makesdi(opp, dot+2, SDIP);
369: else
370: code_length += (useshort)?2:4;
371: put_rel(opp, SUBOP_L, dot+2, 0);
372: }
373: else {
374: /* pass 2 */
375: if ( opp->sym_o && (opp->sym_o->attr_s & S_DEF) == 0){
376: /* external branch -- good luck */
377: ;
378: } else if (opp->sym_o == 0 || opp->sym_o->csect_s != cur_csect_name){
379: PROG_ERROR(E_RELOCATE);
380: } else {
381: opp->sym_o = 0; /* mark as non relocateable expression */
382: }
383: offlong = (offs > 32767L || offs < -32768L) ;
384: if (ip->opval_i[0] & 0100) instlong = 1 ; /* fbccl*/
385: else if (ip->opval_i[0] & 0200) instlong = 0 ; /* fbcc */
386: else
387: { /* fjcc */
388: instlong = offlong ;
389: if (instlong && !useshort )
390: wcode[0] |= 0300 ; /* Op code for fbccl. */
391: else
392: wcode[0] |= 0200 ; /* Op code for fbcc . */
393: }
394: if (offlong &~ instlong) PROG_ERROR(E_OFFSET);
395: opp->value_o = (int)offs;
396: if (instlong && !useshort)
397: rel_val(opp, SUBOP_L, opp->sym_o != 0);
398: else
399: rel_val(opp, SUBOP_W, opp->sym_o != 0);
400: }
401: }
402:
403: cp_conditional ( ip )
404: struct ins_bkt *ip ;
405: /*
406:
407: Coprocessor conditional instructions:
408: fscc ea
409: fdbcc dn,label
410: ftcc
411: ftccw #imm
412: ftccl #imm
413:
414: */
415:
416: {
417: struct oper *op1, *op2 ;
418: long offs = 0;
419:
420: /*
421: opval_i[0] -- fop ea,fpn
422: opval_i[1] -- fop fpm,fpn
423: */
424:
425: code_length = 4 ;
426: wcode[0] = ip->opval_i[0] + current_cpid * 01000 ;
427: wcode[1] = ip->opval_i[1] ; /* condition code */
428: switch(ip->noper_i)
429: {
430: /* case 0: ftcc - nothing more to do */
431: case 1: {
432: op1 = &operands[0] ;
433: if (op1->type_o == T_IMMED)
434: { /* ftccw or ftccl */
435: rel_val(op1, ip->subop_i, 0) ;
436: }
437: else
438: { /* fscc */
439: eaddr( op1, ip->subop_i, 0) ;
440: }
441: break ;
442: }
443: case 2: { /* fdbcc */
444: op1 = &operands[0] ;
445: op2 = &operands[1] ;
446: wcode[0] |= op1->value_o;
447: if ( op2->sym_o && (op2->sym_o->attr_s & S_DEF) == 0){
448: /* external branch -- good luck */
449: ;
450: } else if (op2->sym_o == 0 || op2->sym_o->csect_s != cur_csect_name){
451: PROG_ERROR(E_RELOCATE);
452: } else {
453: op2->sym_o = 0; /* mark as non relocateable expression */
454: }
455: offs = op2->value_o - (dot + 4);
456: if (offs > 32767L || offs < -32768L)
457: PROG_ERROR(E_OFFSET);
458: op2->value_o = (int)offs;
459: rel_val(op2, SUBOP_W, op2->sym_o != 0);
460: break ;
461: }
462: }
463: }
464:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.