Subversion Repositories tendra.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
 
32
 
33
/*
34
			    VERSION INFORMATION
35
			    ===================
36
 
37
--------------------------------------------------------------------------
38
$Header: /u/g/release/CVSROOT/Source/src/installers/sparc/common/inst_fmt.c,v 1.1.1.1 1998/01/17 15:55:54 release Exp $
39
--------------------------------------------------------------------------
40
$Log: inst_fmt.c,v $
41
 * Revision 1.1.1.1  1998/01/17  15:55:54  release
42
 * First version to be checked into rolling release.
43
 *
44
 * Revision 1.12  1997/11/06  09:28:50  pwe
45
 * ANDF-DE V1.8
46
 *
47
 * Revision 1.11  1997/10/10  18:32:25  pwe
48
 * prep ANDF-DE revision
49
 *
50
 * Revision 1.10  1997/08/23  13:53:49  pwe
51
 * initial ANDF-DE
52
 *
53
 * Revision 1.9  1997/04/17  11:59:39  pwe
54
 * dwarf2 support
55
 *
56
 * Revision 1.8  1996/09/18  12:03:38  pwe
57
 * fixed PIC_code
58
 *
59
 * Revision 1.7  1995/12/15  10:12:47  john
60
 * Minor change
61
 *
62
 * Revision 1.6  1995/08/31  15:55:06  john
63
 * Added function for calculation of floating_max
64
 *
65
 * Revision 1.5  1995/07/18  09:38:37  john
66
 * New functions for return_to_label
67
 *
68
 * Revision 1.4  1995/07/14  16:30:59  john
69
 * Minor fix
70
 *
71
 * Revision 1.3  1995/06/14  15:33:09  john
72
 * Reformatting
73
 *
74
 * Revision 1.2  1995/05/26  12:58:38  john
75
 * Reformatting
76
 *
77
 * Revision 1.1.1.1  1995/03/13  10:18:39  john
78
 * Entered into CVS
79
 *
80
 * Revision 1.7  1995/01/24  16:56:34  john
81
 * Added special regs to the register set
82
 *
83
 * Revision 1.6  1994/12/21  12:11:38  djch
84
 * Added maxmin functions for int max/min. Uses the delay slot...
85
 *
86
 * Revision 1.5  1994/12/01  13:16:01  djch
87
 * Added lr_ins to load a label address to a register
88
 * Added lngjmp to code the long jump construct
89
 * Added br_abs to get efficient jump in abs (except with SunOS as)
90
 *
91
 * Revision 1.4  1994/07/07  16:11:33  djch
92
 * Jul94 tape
93
 *
94
 * Revision 1.3  1994/07/04  08:20:45  djch
95
 * added asserts to spot uninitialized labels
96
 *
97
 * Revision 1.2  1994/05/13  12:31:14  djch
98
 * Incorporates improvements from expt version
99
 * Fixed printf strings to remove long, added CONST to extj_special_ins
100
 *
101
 * Revision 1.1  1994/05/03  14:49:38  djch
102
 * Initial revision
103
 *
104
 * Revision 1.7  93/09/27  14:45:39  14:45:39  ra (Robert Andrews)
105
 * The label prefix is now given by lab_prefix rather than by being
106
 * hardwired in.
107
 * 
108
 * Revision 1.6  93/08/27  11:27:19  11:27:19  ra (Robert Andrews)
109
 * Added a couple of explicit integer casts, ext_name now takes a long.
110
 * 
111
 * Revision 1.5  93/07/12  15:14:20  15:14:20  ra (Robert Andrews)
112
 * A couple of things should have been CONST.
113
 * 
114
 * Revision 1.4  93/07/08  18:21:11  18:21:11  ra (Robert Andrews)
115
 * Reformatted.
116
 * 
117
 * Revision 1.3  93/07/05  18:19:49  18:19:49  ra (Robert Andrews)
118
 * Reformatted a couple of routines.  Added support for Position Independent
119
 * Code (PIC) in set_ins.
120
 * 
121
 * Revision 1.2  93/06/29  14:26:39  14:26:39  ra (Robert Andrews)
122
 * Included a couple of explicit casts.
123
 * 
124
 * Revision 1.1  93/06/24  14:58:28  14:58:28  ra (Robert Andrews)
125
 * Initial revision
126
 * 
127
--------------------------------------------------------------------------
128
*/
129
 
130
 
131
#define SPARCTRANS_CODE
132
 
133
/*
134
    This file contains procedures for outputting various SPARC instruction
135
    formats to the external file - as_file.  Each procedure produces
136
    assembler instructions for a family of SPARC operations, the actual
137
    instruction being passed as the string understood by the assembler.
138
*/
139
 
140
#include "config.h"
141
#include "common_types.h"
142
#include "myassert.h"
143
#include "xalloc.h"
144
#include "addrtypes.h"
145
#include "regexps.h"
146
#include "regmacs.h"
147
#include "sparcins.h"
148
#include "maxminmacs.h"
149
#include "comment.h"
150
#include "translat.h"
151
#include "inst_fmt.h"
152
#include "out.h"
153
#include "flags.h"
154
#include "labels.h"
155
#ifdef NEWDWARF
156
#include "dw2_config.h"
157
#endif
158
 
159
 
160
/*
161
     IS c A POWER OF 2?
162
*/
163
 
164
#define IS_POW2( c )	( ( c ) != 0 && ( ( c ) & ( ( c ) - 1 ) ) == 0 )
165
 
166
 
167
/*
168
    ARRAY OF REGISTER NAMES
169
*/
170
 
171
static CONST char reg_name_tab [66][5] = {
172
    "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
173
    "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
174
    "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
175
    "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",
176
    "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
177
    "%f8", "%f9", "%f10","%f11","%f12","%f13","%f14","%f15",
178
    "%f16","%f17","%f18","%f19","%f20","%f21","%f22","%f23",
179
    "%f24","%f25","%f26","%f27","%f28","%f29","%f30","%f31",
180
    "%fsr","%y"
181
} ;
182
 
183
 
184
/*
185
    MACRO FOR ACCESSING REGISTER NAMES
186
 
187
    This converts a register number into the corresponding register
188
    name.
189
*/
190
 
191
#define RN( reg )	reg_name_tab [ reg ]
192
#define FRN( reg )	reg_name_tab [ reg + 32 ]
193
 
194
/*
195
    FIND AN EXTERNAL NAME
196
*/
197
 
198
char *ext_name 
199
    PROTO_N ( ( id ) )
200
    PROTO_T ( int id )
201
{
202
    if ( id < 0 ) {
203
	/* Negative numbers refer to globals */
204
	char *ext = main_globals [ -id - 1 ]->dec_u.dec_val.dec_id ;
205
	return ( ext ) ;
206
    } else {
207
	/* Positive numbers refer to labels */
208
	static char space [64] ;
209
	sprintf ( space, "%sD%d", lab_prefix, id ) ;
210
	return ( space ) ;
211
    }
212
}
213
 
214
 
215
/*
216
    OUTPUT A LOAD REGISTER-OFFSET INSTRUCTION
217
*/
218
 
219
void ld_ro_ins 
220
    PROTO_N ( ( ins, a, dest ) )
221
    PROTO_T ( ins_p ins X baseoff a X int dest )
222
{
223
    long off = a.offset ;
224
    assert ( IS_FIXREG ( a.base ) ) ;
225
    clear_reg ( dest ) ;
226
    if ( SIMM13_SIZE ( off ) ) {
227
	/* Small offset */
228
	CONST char *ra = RN ( a.base ) ;
229
	CONST char *rd = RN ( dest ) ;
230
	if ( off == 0 ) {
231
	    fprintf ( as_file, "\t%s\t[%s],%s\n", ins, ra, rd ) ;
232
	} else if ( off > 0 ) {
233
	    fprintf ( as_file, "\t%s\t[%s+%ld],%s\n", ins, ra, off, rd ) ;
234
	} else /* if ( off < 0 ) */ {
235
	    fprintf ( as_file, "\t%s\t[%s-%ld],%s\n", ins, ra, -off, rd ) ;
236
	}
237
#ifdef NEWDWARF
238
	count_ins(1);
239
#endif
240
    } else {
241
	/* Large offset */
242
	if ( a.base != dest ) {
243
	    /* Is this really a saving? */
244
	    ir_ins ( i_set, off, dest ) ;
245
	    ld_rr_ins ( ins, a.base, dest, dest ) ;
246
	} else {
247
	    assert ( a.base != R_TMP ) ;
248
	    ir_ins ( i_set, off, R_TMP ) ;
249
	    ld_rr_ins ( ins, a.base, R_TMP, dest ) ;
250
	}
251
#ifdef NEWDWARF
252
	lost_count_ins();
253
#endif
254
    }
255
    return ;
256
}
257
 
258
 
259
/*
260
    OUTPUT A LOAD REGISTER-REGISTER INSTRUCTION
261
*/
262
 
263
void ld_rr_ins 
264
    PROTO_N ( ( ins, reg1, reg2, dest ) )
265
    PROTO_T ( ins_p ins X int reg1 X int reg2 X int dest )
266
{
267
    clear_reg ( dest ) ;
268
    fprintf ( as_file, "\t%s\t[%s+%s],%s\n", ins,
269
	      RN ( reg1 ), RN ( reg2 ), RN ( dest ) ) ;
270
#ifdef NEWDWARF
271
    count_ins(1);
272
#endif
273
    return ;
274
}
275
 
276
 
277
/*
278
    OUTPUT A SET INSTRUCTION
279
*/
280
 
281
void set_ins 
282
    PROTO_N ( ( a, dest ) )
283
    PROTO_T ( baseoff a X int dest )
284
{
285
    char *extname = ext_name ( a.base ) ;
286
    long d = a.offset ;
287
    clear_reg ( dest ) ;
288
 
289
    if ( d == 0 || PIC_code ) {
290
	fprintf ( as_file, "\tset\t%s,%s\n", extname, RN ( dest ) ) ;
291
    } else if ( d > 0 ) {
292
	fprintf ( as_file, "\tset\t%s+%ld,%s\n", extname, d, RN ( dest ) ) ;
293
    } else {
294
	fprintf ( as_file, "\tset\t%s-%ld,%s\n", extname, -d, RN ( dest ) ) ;
295
    }
296
#ifdef NEWDWARF
297
    lost_count_ins();
298
#endif
299
 
300
    if ( PIC_code ) {
301
	ld_rr_ins ( i_ld, R_L7, dest, dest ) ;
302
	if ( d ) rir_ins ( i_add, dest, d, dest ) ;
303
    }
304
    return ;
305
}
306
 
307
 
308
/*
309
    OUTPUT A LOAD INSTRUCTION
310
 
311
    If baseoff is a global this may be two instructions and involve
312
    a temporary register.
313
*/
314
 
315
 
316
void ld_ins 
317
    PROTO_N ( ( ins, a, dest ) )
318
    PROTO_T ( ins_p ins X baseoff a X int dest )
319
{
320
    if ( !IS_FIXREG ( a.base ) ) {
321
	/* global */
322
	baseoff tmp_off ;
323
	tmp_off.base = R_TMP ;
324
	tmp_off.offset = 0 ;
325
	set_ins ( a, R_TMP ) ;
326
	ld_ro_ins ( ins, tmp_off, dest ) ;
327
    } else {
328
	ld_ro_ins ( ins, a, dest ) ;
329
    }
330
    return ;
331
}
332
 
333
 
334
/*
335
    OUTPUT A STORE REGISTER-OFFSET INSTRUCTION
336
*/
337
 
338
void st_ro_ins 
339
    PROTO_N ( ( ins, src, a ) )
340
    PROTO_T ( ins_p ins X int src X baseoff a )
341
{
342
    long off = a.offset ;
343
    assert ( IS_FIXREG ( a.base ) ) ;
344
 
345
    /* in general we cannot cope with store using temp reg, catch it always */
346
    if ( ( src == R_TMP || a.base == R_TMP )
347
	 && ABS_OF ( off ) > ( 16 + 1 + 6 ) * 4 /* leeway for mem_temp */ ) {
348
	fail ( "Temporary register problem in st_ro_ins" ) ;
349
    }
350
 
351
    if ( SIMM13_SIZE ( off ) ) {
352
	/* Small offset */
353
	CONST char *rs = RN ( src ) ;
354
	CONST char *ra = RN ( a.base ) ;
355
	if ( off == 0 ) {
356
	    fprintf ( as_file, "\t%s\t%s,[%s]\n", ins, rs, ra ) ;
357
	} else if ( off > 0 ) {
358
	    fprintf ( as_file, "\t%s\t%s,[%s+%ld]\n", ins, rs, ra, off ) ;
359
	} else /* if ( off < 0 ) */ {
360
	    fprintf ( as_file, "\t%s\t%s,[%s-%ld]\n", ins, rs, ra, -off ) ;
361
	}
362
#ifdef NEWDWARF
363
	count_ins(1);
364
#endif
365
    } else {
366
	/* Large offset */
367
	assert ( a.base != R_TMP ) ;
368
	ir_ins ( i_set, off, R_TMP ) ;
369
#ifdef NEWDWARF
370
	lost_count_ins();
371
#endif
372
	st_rr_ins ( ins, src, a.base, R_TMP ) ;
373
    }
374
    return ;
375
}
376
 
377
 
378
/*
379
    OUTPUT A STORE REGISTER-REGISTER INSTRUCTION
380
*/
381
 
382
void st_rr_ins 
383
    PROTO_N ( ( ins, src, reg1, reg2 ) )
384
    PROTO_T ( ins_p ins X int src X int reg1 X int reg2 )
385
{
386
    fprintf ( as_file, "\t%s\t%s,[%s+%s]\n", ins,
387
	      RN ( src ), RN ( reg1 ), RN ( reg2 ) ) ;
388
#ifdef NEWDWARF
389
    count_ins(1);
390
#endif
391
    return ;
392
}
393
 
394
 
395
/*
396
    OUTPUT A STORE INSTRUCTION
397
 
398
    If baseoff is a global this may be two instructions and involve
399
    a temporary register.
400
*/
401
 
402
void st_ins 
403
    PROTO_N ( ( ins, src, a ) )
404
    PROTO_T ( ins_p ins X int src X baseoff a )
405
{
406
    if ( !IS_FIXREG ( a.base ) ) {
407
	/* global */
408
	baseoff tmp_off ;
409
	if ( src == R_TMP ) {
410
	    fail ( "Temporary register problem in st_ins" ) ;
411
	}
412
	tmp_off.base = R_TMP ;
413
	tmp_off.offset = 0 ;
414
	set_ins ( a, R_TMP ) ;
415
	st_ro_ins ( ins, src, tmp_off ) ;
416
    } else {
417
	st_ro_ins ( ins, src, a ) ;
418
    }
419
    return ;
420
}
421
 
422
 
423
/*
424
    OUTPUT A THREE REGISTER INSTRUCTION
425
*/
426
 
427
void rrr_ins 
428
    PROTO_N ( ( ins, src1, src2, dest ) )
429
    PROTO_T ( ins_p ins X int src1 X int src2 X int dest )
430
{
431
    clear_reg ( dest ) ;
432
    fprintf ( as_file, "\t%s\t%s,%s,%s\n", ins,
433
	      RN ( src1 ), RN ( src2 ), RN ( dest ) ) ;
434
#ifdef NEWDWARF
435
    count_ins(1);
436
#endif
437
    return ;
438
}
439
 
440
 
441
/*
442
    OUTPUT A REGISTER, IMMEDIATE, REGISTER INSTRUCTION
443
*/
444
 
445
void rir_ins 
446
    PROTO_N ( ( ins, src1, imm, dest ) )
447
    PROTO_T ( ins_p ins X int src1 X long imm X int dest )
448
{
449
    clear_reg ( dest ) ;
450
 
451
    if ( SIMM13_SIZE ( imm ) ) {
452
	/* Small data */
453
	fprintf ( as_file, "\t%s\t%s,%ld,%s\n", ins,
454
		  RN ( src1 ), imm, RN ( dest ) ) ;
455
#ifdef NEWDWARF
456
	count_ins(1);
457
#endif
458
    } else if ( SIMM13_SIZE ( ~imm ) &&
459
		( ins == i_and || ins == i_or || ins == i_xor ) ) {
460
	/* Small data complemented */
461
	ins_p n_ins ;
462
	if ( ins == i_and ) {
463
	    n_ins = i_andn ;
464
	} else if ( ins == i_or ) {
465
	    n_ins = i_orn ;
466
	} else /* if ( ins == i_xor ) */ {
467
	    n_ins = i_xnor ;
468
	}
469
	fprintf ( as_file, "\t%s\t%s,%ld,%s\n", n_ins,
470
		  RN ( src1 ), ~imm, RN ( dest ) ) ;
471
#ifdef NEWDWARF
472
	count_ins(1);
473
#endif
474
    } else if ( ins == i_and && IS_POW2 ( imm + 1 ) ) {
475
	/* Can be done by shift left, shift right */
476
	int nbits = 0, shift ;
477
	unsigned long uimm = ( unsigned long ) imm ;
478
	while ( uimm != 0 ) {
479
	    nbits++ ;
480
	    uimm = uimm >> 1 ;
481
	}
482
	shift = 32 - nbits ;
483
	rir_ins ( i_sll, src1, ( long ) shift, dest ) ;
484
	rir_ins ( i_srl, dest, ( long ) shift, dest ) ;
485
    } else if ( ( ins == i_add || ins == i_sub ) &&
486
		SIMM13_SIZE ( imm / 2 ) && dest != R_SP ) {
487
	if ( imm == 4096 ) {
488
	    /* add 4096 => sub -4096 etc */
489
	    rir_ins ( ( ins == i_add ? i_sub : i_add ), src1, -imm, dest ) ;
490
	} else {
491
	    /* use two adds or subs */
492
	    long half = imm / 2;
493
	    rir_ins ( ins, src1, half, dest ) ;
494
	    rir_ins ( ins, dest, ( long ) ( imm - half ), dest ) ;
495
	}
496
    } else {
497
	/* use temporary register for large constant */
498
	if ( src1 == R_TMP ) {
499
	    fail ( "Temporary register problem in rir_ins" ) ;
500
	} else {
501
	    fprintf ( as_file, "\tset\t%ld,%s\n", imm, RN ( R_TMP ) ) ;
502
#ifdef NEWDWARF
503
	    lost_count_ins();
504
#endif
505
	    rrr_ins ( ins, src1, R_TMP, dest ) ;
506
	}
507
    }
508
    return ;
509
}
510
 
511
 
512
/*
513
    OUTPUT A REGISTER TO REGISTER PSEUDO INSTRUCTION
514
*/
515
 
516
void rr_ins 
517
    PROTO_N ( ( ins, src, dest ) )
518
    PROTO_T ( ins_p ins X int src X int dest )
519
{
520
    clear_reg ( dest ) ;
521
    fprintf ( as_file, "\t%s\t%s,%s\n", ins, RN ( src ), RN ( dest ) ) ;
522
#ifdef NEWDWARF
523
    count_ins(1);
524
#endif
525
    return ;
526
}
527
 
528
 
529
/*
530
    OUTPUT AN IMMEDIATE TO REGISTER PSEUDO INSTRUCTION
531
*/
532
 
533
void ir_ins 
534
    PROTO_N ( ( ins, imm, dest ) )
535
    PROTO_T ( ins_p ins X long imm X int dest )
536
{
537
    clear_reg ( dest ) ;
538
 
539
    if ( SIMM13_SIZE ( imm ) || ins == i_set ) {
540
	fprintf ( as_file, "\t%s\t%ld,%s\n", ins, imm, RN ( dest ) ) ;
541
#ifdef NEWDWARF
542
	count_ins(1);
543
#endif
544
    } else if ( ins == i_mov ) {
545
	/* use a set instruction for move */
546
	fprintf ( as_file, "\tset\t%ld,%s\n", imm, RN ( dest ) ) ;
547
#ifdef NEWDWARF
548
	lost_count_ins();
549
#endif
550
    } else {
551
	/* use temporary register for large constant */
552
	fprintf ( as_file, "\tset\t%ld,%s\n", imm, RN ( R_TMP ) ) ;
553
#ifdef NEWDWARF
554
	lost_count_ins();
555
#endif
556
	rr_ins ( ins, R_TMP, dest ) ;
557
    }
558
    return ;
559
}
560
 
561
/*
562
    OUTPUT A LABEL TO REGISTER PSEUDO INSTRUCTION
563
*/
564
 
565
void lr_ins 
566
    PROTO_N ( ( imm, dest ) )
567
    PROTO_T ( int imm X int dest )
568
{
569
    clear_reg ( dest ) ;
570
 
571
    /* use a set instruction to load the label */
572
    fprintf ( as_file, "\tset\t%s%d,%s\n", lab_prefix, imm, RN ( dest ) ) ;
573
#ifdef NEWDWARF
574
    lost_count_ins();
575
#endif
576
 
577
    if ( PIC_code ) {
578
	ld_rr_ins ( i_ld, R_L7, dest, dest ) ;
579
    }
580
    return ;
581
}
582
 
583
 
584
/*
585
    OUTPUT A ZEROADIC INSTRUCTION
586
*/
587
 
588
void z_ins 
589
    PROTO_N ( ( ins ) )
590
    PROTO_T ( ins_p ins )
591
{
592
    fprintf ( as_file, "\t%s\n", ins ) ;
593
#ifdef NEWDWARF
594
    count_ins(1);
595
#endif
596
    return ;
597
}
598
 
599
 
600
/*
601
    OUTPUT AN UNCONDITIONAL BRANCH
602
*/
603
 
604
void uncond_ins 
605
    PROTO_N ( ( ins, lab ) )
606
    PROTO_T ( ins_p ins X int lab )
607
{
608
    fprintf ( as_file, "\t%s\t%s%d\n", ins, lab_prefix, lab ) ;
609
    assert (lab > 100);
610
    outs ( "\tnop\n" ) ;	/* delay slot */
611
#ifdef NEWDWARF
612
    count_ins(2);
613
#endif
614
    return ;
615
}
616
 
617
 
618
/*
619
    OUTPUT A RETURN INSTRUCTION
620
*/
621
 
622
void ret_ins 
623
    PROTO_N ( ( ins ) )
624
    PROTO_T ( ins_p ins )
625
{
626
    fprintf ( as_file, "\t%s\n", ins ) ;
627
    outs ( "\tnop\n" ) ;	/* delay slot */
628
#ifdef NEWDWARF
629
    count_ins(2);
630
#endif
631
    return ;
632
}
633
 
634
 
635
/*
636
    OUTPUT A RETURN AND RESTORE INSTRUCTION
637
*/
638
 
639
void ret_restore_ins 
640
    PROTO_Z ()
641
{
642
    fprintf ( as_file, "\t%s\n", i_ret ) ;
643
    fprintf ( as_file, "\t%s\n", i_restore ) ;	/* delay slot */
644
#ifdef NEWDWARF
645
    count_ins(2);
646
#endif
647
    return ;
648
}
649
 
650
/*
651
   OUTPUT A LONGJMP (old sp, pc)
652
*/
653
				/* offset from fp to saved i6 in the 16 word
654
				 reg save area. See rw_fp in <machine/reg.h> */
655
#define FP_OFFSET_IN_FRAME (8*4 + 6*4)
656
 
657
void lngjmp 
658
    PROTO_N ( ( o_fp_reg, pc_reg, r_new_sp ) )
659
    PROTO_T ( int o_fp_reg X int pc_reg X int r_new_sp )
660
{
661
  int lab = new_label();
662
  baseoff frm;
663
 
664
  frm.offset = FP_OFFSET_IN_FRAME;
665
 
666
#ifdef NOT_SUN_BUGGY_ASM
667
  fprintf ( as_file, "\tta\t3\n" );
668
#else
669
  fprintf ( as_file, "\t.word\t0x91d02003\n" ) ; /* ta 3, but SunOS as may
670
						    get ta wrong I'm told */
671
#endif
672
#ifdef NEWDWARF
673
	lost_count_ins();
674
#endif
675
  rr_ins ( i_mov, R_SP, r_new_sp);
676
  rir_ins( i_sub, R_SP, 0x40, R_SP);
677
 
678
  frm.base = r_new_sp;
679
 
680
  set_label (lab);
681
  ld_ro_ins (i_ld, frm,   R_TMP);
682
  fprintf ( as_file, "\tcmp\t%s,%s\n", RN (R_TMP ), RN(o_fp_reg));
683
  fprintf ( as_file, "\tbne,a\t%s%d\n", lab_prefix, lab);
684
#ifdef NEWDWARF
685
  count_ins(2);
686
#endif
687
  rr_ins (i_mov, R_TMP, r_new_sp);
688
				/* now r_new_sp holds the sp to a reg
689
				 save area whose fp is the fp we want...*/
690
  rr_ins (i_mov, r_new_sp, R_FP);
691
 
692
  fprintf ( as_file, "\tjmpl\t %s + 0, %%g0\n", RN(pc_reg)) ;
693
  fprintf ( as_file, "\t%s\n", i_restore ) ;	/* delay slot */
694
#ifdef NEWDWARF
695
  count_ins(2);
696
#endif
697
}
698
 
699
/*
700
    OUTPUT A STRUCTURE RESULT RETURN AND RESTORE INSTRUCTION
701
 
702
    See section D.4 of the SPARC architecture manual.
703
*/
704
 
705
void stret_restore_ins 
706
    PROTO_Z ()
707
{
708
    fprintf ( as_file, "\tjmp\t%%i7+12\n" ) ;
709
    fprintf ( as_file, "\t%s\n", i_restore ) ;	/* delay slot */
710
#ifdef NEWDWARF
711
    count_ins(2);
712
#endif
713
    return ;
714
}
715
 
716
 
717
/*
718
    OUTPUT AN EXTERNAL JUMP OR CALL INSTRUCTION
719
*/
720
 
721
void extj_ins 
722
    PROTO_N ( ( ins, b, param_regs_used ) )
723
    PROTO_T ( ins_p ins X baseoff b X int param_regs_used )
724
{
725
  char *ext = ext_name ( b.base ) ;
726
  if ( param_regs_used >= 0 ) {
727
    /* print number of parameter registers if known */
728
    assert ( param_regs_used <= 6 ) ;	/* %o0..%o5 */
729
    if(b.offset) {
730
      fprintf(as_file,"\t%s\t%s+%ld,%d\n",ins,ext,b.offset,param_regs_used);
731
    }
732
    else {
733
      fprintf ( as_file, "\t%s\t%s,%d\n", ins, ext, param_regs_used ) ;
734
    }
735
 
736
  } 
737
  else {
738
    /* param_regs_used = -1 means it is not known */
739
    if (b.offset) {
740
      fprintf(as_file,"\t%s\t%s+%ld\n",ins,ext,b.offset);
741
    }
742
    else {
743
      fprintf ( as_file, "\t%s\t%s\n", ins, ext ) ;
744
    }
745
  }
746
  outs ( "\tnop\n" ) ;	/* delay slot */
747
#ifdef NEWDWARF
748
  count_ins(2);
749
#endif
750
  return ;
751
}	
752
 
753
/* 
754
   don't fill up the delay slot: the caller of this functions must
755
   provide its own delay slot filler 
756
*/
757
void extj_ins_without_delay 
758
    PROTO_N ( ( ins, b, param_regs_used ) )
759
    PROTO_T ( ins_p ins X baseoff b X int param_regs_used ){
760
  char *ext = ext_name ( b.base ) ;
761
  if ( param_regs_used >= 0 ) {
762
    /* print number of parameter registers if known */
763
    assert ( param_regs_used <= 6 ) ;	/* %o0..%o5 */
764
    fprintf ( as_file, "\t%s\t%s,%d\n", ins, ext, param_regs_used ) ;
765
  } 
766
  else {
767
    /* param_regs_used = -1 means it is not known */
768
    fprintf ( as_file, "\t%s\t%s\n", ins, ext ) ;
769
  }
770
#ifdef NEWDWARF
771
  count_ins(1);
772
#endif
773
  return ;
774
}
775
 
776
 
777
 
778
/*
779
  OUTPUT AN EXTERNAL JUMP OR CALL INSTRUCTION (SPECIAL CASE)
780
 
781
  This case is used to handle special calls like .muls where the
782
  name is given by a string.
783
*/
784
 
785
void extj_special_ins 
786
    PROTO_N ( ( ins, ext, param_regs_used ) )
787
    PROTO_T ( ins_p ins X CONST char * CONST ext X int param_regs_used ){
788
  if ( param_regs_used >= 0 ) {
789
    /* print number of parameter registers if known */
790
    assert ( param_regs_used <= 6 ) ;	/* %o0..%o5 */
791
    fprintf ( as_file, "\t%s\t%s,%d\n", ins, ext, param_regs_used ) ;
792
  } 
793
  else {
794
    /* param_regs_used = -1 means it is not known */
795
    fprintf ( as_file, "\t%s\t%s\n", ins, ext ) ;
796
  }
797
  outs ( "\tnop\n" ) ;	/* delay slot */
798
#ifdef NEWDWARF
799
  count_ins(2);
800
#endif
801
  return ;
802
}
803
 
804
 
805
/* as above, but with allowing the calling function to fill in the
806
   delay slot. */
807
void extj_special_ins_no_delay 
808
    PROTO_N ( ( ins, ext, param_regs_used ) )
809
    PROTO_T ( ins_p ins X CONST char * CONST ext X int param_regs_used ){
810
  if ( param_regs_used >= 0 ) {
811
    /* print number of parameter registers if known */
812
    assert ( param_regs_used <= 6 ) ;	/* %o0..%o5 */
813
    fprintf ( as_file, "\t%s\t%s,%d\n", ins, ext, param_regs_used ) ;
814
  } 
815
  else {
816
    /* param_regs_used = -1 means it is not known */
817
    fprintf ( as_file, "\t%s\t%s\n", ins, ext ) ;
818
  }
819
#ifdef NEWDWARF
820
  count_ins(1);
821
#endif
822
  	/* delay slot */
823
  return ;
824
}
825
 
826
 
827
 
828
 
829
/*
830
  OUTPUT AN EXTERNAL JUMP TO REGISTER INSTRUCTION
831
*/
832
 
833
void extj_reg_ins 
834
    PROTO_N ( ( ins, reg, param_regs_used ) )
835
    PROTO_T ( ins_p ins X int reg X int param_regs_used ){
836
  assert ( IS_FIXREG ( reg ) ) ;
837
  if ( sysV_assembler ) {
838
    /* The SysV assembler likes reg to be R_G1 for calls */
839
    if ( ins == i_call && reg != R_G1 ) {
840
      rr_ins ( i_mov, reg, R_G1 ) ;
841
      reg = R_G1 ;
842
    }
843
  }	
844
  extj_special_ins ( ins, RN ( reg ), param_regs_used ) ;
845
  return ;
846
}	
847
 
848
 
849
void extj_reg_ins_no_delay 
850
    PROTO_N ( ( ins, reg, param_regs_used ) )
851
    PROTO_T ( ins_p ins X int reg X int param_regs_used ){
852
  assert ( IS_FIXREG ( reg ) ) ;
853
  if ( sysV_assembler ) {
854
    /* The SysV assembler likes reg to be R_G1 for calls */
855
    if ( ins == i_call && reg != R_G1 ) {
856
      rr_ins ( i_mov, reg, R_G1 ) ;
857
      reg = R_G1 ;
858
    }
859
  }	
860
  extj_special_ins_no_delay ( ins, RN ( reg ), param_regs_used ) ;
861
  return ;
862
}	
863
 
864
 
865
 
866
/*
867
  OUTPUT AN UNIMP INSTRUCTION
868
*/
869
 
870
void unimp_ins 
871
    PROTO_N ( ( imm ) )
872
    PROTO_T ( long imm ){
873
    fprintf ( as_file, "\tunimp\t%ld\n", imm ) ;
874
#ifdef NEWDWARF
875
    count_ins(1);
876
#endif
877
    return ;
878
}
879
 
880
 
881
/*
882
  OUTPUT A CONDITIONAL INTEGER TEST JUMP
883
*/
884
 
885
void br_ins 
886
    PROTO_N ( ( ins, dest ) )
887
    PROTO_T ( ins_p ins X int dest ){
888
  fprintf ( as_file, "\t%s\t%s%d\n", ins, lab_prefix, dest ) ;
889
  assert (dest > 100);
890
  outs ( "\tnop\n" ) ;	/* delay slot */
891
#ifdef NEWDWARF
892
  count_ins(2);
893
#endif
894
  return ;
895
}
896
 
897
/*
898
  OUTPUT int branch for abs
899
*/
900
 
901
void br_abs 
902
    PROTO_N ( ( lab ) )
903
    PROTO_T ( int lab ){
904
#ifdef NOT_SUN_BUGGY_ASM
905
  fprintf ( as_file, "\t%s\t%s%s\n", "bpos,a", lab_prefix, lab);
906
#ifdef NEWDWARF
907
  count_ins(1);
908
#endif
909
  /* No nop, delay slot used!!! */
910
#else
911
  fprintf ( as_file, "\t%s\t%s%d\n", "bneg", lab_prefix, lab);
912
  fprintf ( as_file, "\tnop\n");
913
#ifdef NEWDWARF
914
  count_ins(2);
915
#endif
916
#endif
917
  return ;
918
}
919
 
920
 
921
/*
922
  OUTPUT A CONDITIONAL FLOATING POINT TEST JUMP
923
 
924
  The instruction before a floating point test jump instruction 
925
  cannot be another floating point instruction.
926
*/
927
 
928
void fbr_ins 
929
    PROTO_N ( ( ins, dest ) )
930
    PROTO_T ( ins_p ins X int dest ){
931
  outs ( "\tnop\n" ) ;
932
  fprintf ( as_file, "\t%s\t%s%d\n", ins, lab_prefix, dest ) ;
933
  assert (dest > 100);
934
  outs ( "\tnop\n" ) ;	/* delay slot */
935
#ifdef NEWDWARF
936
  count_ins(2);
937
#endif
938
  return ;
939
}
940
 
941
 
942
/*
943
  OUTPUT A REGISTER, REGISTER COMPARISON
944
*/
945
 
946
void condrr_ins 
947
    PROTO_N ( ( ins, src1, src2, lab ) )
948
    PROTO_T ( ins_p ins X int src1 X int src2 X int lab ){
949
  if(src2 == R_G0){
950
    fprintf ( as_file, "\ttst\t%s\n",RN(src1) );
951
  }
952
  else{
953
    fprintf ( as_file, "\tcmp\t%s,%s\n", RN ( src1 ), RN ( src2 ) ) ;
954
  }
955
#ifdef NEWDWARF
956
  count_ins(1);
957
#endif
958
  br_ins ( ins, lab ) ;
959
  return ;
960
}
961
 
962
 
963
/*
964
  OUTPUT A REGISTER, IMMEDIATE COMPARISON
965
*/
966
 
967
void condri_ins 
968
    PROTO_N ( ( ins, src1, imm, lab ) )
969
    PROTO_T ( ins_p ins X int src1 X long imm X int lab ){
970
  if ( SIMM13_SIZE(imm) ) {
971
    /* Small constant */
972
    fprintf ( as_file, "\tcmp\t%s,%ld\n", RN ( src1 ), imm ) ;
973
#ifdef NEWDWARF
974
    count_ins(1);
975
#endif
976
    br_ins ( ins, lab ) ;
977
    } 
978
  else {
979
    /* Large constant */
980
    if ( src1 == R_TMP ) {
981
      fail ( "Temporary register problem in condri_ins" ) ;
982
    }
983
    fprintf ( as_file, "\tset\t%ld,%s\n", imm, RN ( R_TMP ) ) ;
984
#ifdef NEWDWARF
985
    lost_count_ins();
986
#endif
987
    condrr_ins ( ins, src1, R_TMP, lab ) ;
988
  }
989
  return ;
990
}
991
 
992
/*
993
    OUTPUT A REGISTER, REGISTER MAX/MIN
994
*/
995
 
996
void fmaxminrr_ins 
997
    PROTO_N ( ( ins, src1, src2, dest, ftype ) )
998
    PROTO_T ( ins_p ins X int src1 X int src2 X int dest X int ftype ) {
999
  ins_p fcmp_ins;
1000
  int lab = new_label() ;
1001
  fcmp_ins = i_fcmps;
1002
  fprintf ( as_file, "\t%s\t%s,%s\n", fcmp_ins,RN ( src1 ), RN ( src2 ) ) ;
1003
  fprintf ( as_file, "\t%s\t%s%d\n", ins, lab_prefix, lab ) ;
1004
  /* USE the delay slot */
1005
  fprintf ( as_file, "\tfmovs %s, %s\n", RN(src1), RN(dest));
1006
  fprintf ( as_file, "\tfmovs %s, %s\n", RN(src2), RN(dest));
1007
#ifdef NEWDWARF
1008
  count_ins(4);
1009
#endif
1010
 
1011
  set_label(lab);
1012
  return ;
1013
}
1014
 
1015
 
1016
 
1017
 
1018
void maxminrr_ins 
1019
    PROTO_N ( ( ins, src1, src2, dest ) )
1020
    PROTO_T ( ins_p ins X int src1 X int src2 X int dest ){
1021
  int lab = new_label() ;
1022
 
1023
  fprintf ( as_file, "\tcmp\t%s,%s\n", RN ( src1 ), RN ( src2 ) ) ;
1024
  fprintf ( as_file, "\t%s\t%s%d\n", ins, lab_prefix, lab ) ;
1025
  /* USE the delay slot */
1026
  fprintf ( as_file, "\tmov %s, %s\n", RN(src1), RN(dest));
1027
  fprintf ( as_file, "\tmov %s, %s\n", RN(src2), RN(dest));
1028
#ifdef NEWDWARF
1029
  count_ins(4);
1030
#endif
1031
 
1032
  set_label(lab);
1033
  return ;
1034
}
1035
 
1036
/*
1037
  OUTPUT A REGISTER, IMMEDIATE MAX/MIN
1038
*/
1039
 
1040
void maxminri_ins 
1041
    PROTO_N ( ( ins, src1, val, dest ) )
1042
    PROTO_T ( ins_p ins X int src1 X long val X int dest ){
1043
  int lab = new_label() ;
1044
 
1045
  if (!SIMM13_SIZE ( val ))  {
1046
    fprintf ( as_file, "\tset\t%ld,%s\n", val, RN ( R_TMP ) ) ;
1047
    fprintf ( as_file, "\tcmp\t%s,%s\n", RN ( src1 ), RN ( R_TMP) ) ;
1048
    fprintf ( as_file, "\t%s\t%s%d\n", ins, lab_prefix, lab ) ;
1049
    /* USE the delay slot */
1050
    fprintf ( as_file, "\tmov %s, %s\n", RN(src1), RN(dest));
1051
			/* note set is two instruction, and
1052
	       	        must not go in the delay slot... */
1053
    fprintf ( as_file, "\tset %ld, %s\n", val, RN(dest));
1054
#ifdef NEWDWARF
1055
    lost_count_ins();
1056
#endif
1057
  } 
1058
  else{
1059
    fprintf ( as_file, "\tcmp\t%s,%ld\n", RN ( src1 ), val ) ;
1060
    fprintf ( as_file, "\t%s\t%s%d\n", ins, lab_prefix, lab ) ;
1061
    /* USE the delay slot */
1062
    fprintf ( as_file, "\tmov %s, %s\n", RN(src1), RN(dest));
1063
    fprintf ( as_file, "\tmov %ld, %s\n", val, RN(dest));
1064
#ifdef NEWDWARF
1065
    count_ins(4);
1066
#endif
1067
 
1068
  }
1069
  set_label(lab);
1070
  return ;
1071
}
1072
 
1073
 
1074
/*
1075
  OUTPUT A LOAD FLOATING REGISTER-OFFSET INSTRUCTION
1076
*/
1077
 
1078
void ldf_ro_ins 
1079
    PROTO_N ( ( ins, a, dest ) )
1080
    PROTO_T ( ins_p ins X baseoff a X int dest ){
1081
  long off = a.offset ;
1082
  assert ( IS_FIXREG ( a.base ) ) ;
1083
  clear_freg ( dest ) ;
1084
  if ( SIMM13_SIZE ( off ) ) {
1085
    /* Small offset */
1086
    CONST char *rn = RN ( a.base ) ;
1087
    if ( off == 0 ) {
1088
      fprintf ( as_file, "\t%s\t[%s],%s\n", ins, rn, FRN(dest) ) ;
1089
    } 
1090
    else if ( off > 0 ) {
1091
      fprintf ( as_file, "\t%s\t[%s+%ld],%s\n", ins, rn, off, FRN(dest) ) ;
1092
    } 
1093
    else /* if ( off < 0 ) */ {
1094
      fprintf ( as_file, "\t%s\t[%s-%ld],%s\n", ins, rn, -off, FRN(dest) ) ;
1095
    }
1096
#ifdef NEWDWARF
1097
    count_ins(1);
1098
#endif
1099
  } 
1100
  else {
1101
    /* Large offset */
1102
    assert ( a.base != R_TMP ) ;
1103
    ir_ins ( i_set, off, R_TMP ) ;
1104
#ifdef NEWDWARF
1105
    lost_count_ins();
1106
#endif
1107
    ldf_rr_ins ( ins, a.base, R_TMP, dest ) ;
1108
  }
1109
  return ;
1110
}
1111
 
1112
 
1113
/*
1114
  OUTPUT A LOAD FLOATING REGISTER-REGISTER INSTRUCTION
1115
*/
1116
 
1117
void ldf_rr_ins 
1118
    PROTO_N ( ( ins, reg1, reg2, dest ) )
1119
    PROTO_T ( ins_p ins X int reg1 X int reg2 X int dest ){
1120
  clear_freg ( dest ) ;
1121
  fprintf ( as_file, "\t%s\t[%s+%s],%s\n", ins,
1122
	    RN ( reg1 ), RN ( reg2 ), FRN(dest) ) ;
1123
#ifdef NEWDWARF
1124
  count_ins(1);
1125
#endif
1126
  return ;
1127
}
1128
 
1129
 
1130
/*
1131
  OUTPUT A LOAD FLOATING INSTRUCTION
1132
 
1133
  If baseoff is a global this may be two instructions and involve
1134
  a temporary register.
1135
*/
1136
 
1137
void ldf_ins 
1138
    PROTO_N ( ( ins, a, dest ) )
1139
    PROTO_T ( ins_p ins X baseoff a X int dest ){
1140
  if ( !IS_FIXREG ( a.base ) ) {
1141
    /* global */
1142
    baseoff tmp_off ;
1143
    tmp_off.base = R_TMP ;
1144
    tmp_off.offset = 0 ;
1145
    set_ins ( a, R_TMP ) ;
1146
    ldf_ro_ins ( ins, tmp_off, dest ) ;
1147
  } 
1148
  else {
1149
    ldf_ro_ins ( ins, a, dest ) ;
1150
  }
1151
  return ;
1152
}
1153
 
1154
 
1155
/*
1156
  OUTPUT A STORE FLOATING REGISTER-OFFSET INSTRUCTION
1157
*/
1158
 
1159
void stf_ro_ins 
1160
    PROTO_N ( ( ins, src, a ) )
1161
    PROTO_T ( ins_p ins X int src X baseoff a ){
1162
  long off = a.offset ;
1163
  assert ( IS_FIXREG ( a.base ) ) ;
1164
  if ( a.base == R_TMP && ABS_OF ( off )  > ( 16 + 1 + 6 ) * 4 ) {
1165
    fail ( "Temporary register problem in stf_ro_ins" ) ;
1166
  }
1167
  if ( SIMM13_SIZE ( off ) ) {
1168
    /* Small offset */
1169
    CONST char *rn = RN ( a.base ) ;
1170
    if ( off == 0 ) {
1171
      fprintf ( as_file, "\t%s\t%s,[%s]\n", ins, FRN(src), rn ) ;
1172
    } 
1173
    else if ( off > 0 ) {
1174
      fprintf ( as_file, "\t%s\t%s,[%s+%ld]\n", ins, FRN(src), rn, off ) ;
1175
    } 
1176
    else /* if ( off < 0 ) */ {
1177
      fprintf ( as_file, "\t%s\t%s,[%s-%ld]\n", ins, FRN(src), rn, -off ) ;
1178
    }
1179
#ifdef NEWDWARF
1180
    count_ins(1);
1181
#endif
1182
   } 
1183
  else {
1184
    /* Large offset */
1185
    assert ( a.base != R_TMP ) ;
1186
    ir_ins ( i_set, off, R_TMP ) ;
1187
#ifdef NEWDWARF
1188
    lost_count_ins();
1189
#endif
1190
    stf_rr_ins ( ins, src, a.base, R_TMP ) ;
1191
  }
1192
  return ;
1193
}
1194
 
1195
 
1196
/*
1197
  OUTPUT A STORE FLOATING REGISTER-REGISTER INSTRUCTION
1198
*/
1199
 
1200
void stf_rr_ins 
1201
    PROTO_N ( ( ins, src, reg1, reg2 ) )
1202
    PROTO_T ( ins_p ins X int src X int reg1 X int reg2 ){
1203
  fprintf ( as_file, "\t%s\t%s,[%s+%s]\n", ins, FRN(src), 
1204
	    RN ( reg1 ), RN ( reg2 ) ) ;
1205
#ifdef NEWDWARF
1206
  count_ins(1);
1207
#endif
1208
  return ;
1209
}
1210
 
1211
 
1212
/*
1213
  OUTPUT A STORE FLOATING INSTRUCTION
1214
 
1215
  If baseoff is a global this may be two instructions and involve
1216
  a temporary register.
1217
*/
1218
 
1219
void stf_ins 
1220
    PROTO_N ( ( ins, src, a ) )
1221
    PROTO_T ( ins_p ins X int src X baseoff a ){
1222
  if ( !IS_FIXREG ( a.base ) ) {
1223
    /* global */
1224
    baseoff tmp_off ;
1225
    tmp_off.base = R_TMP ;
1226
    tmp_off.offset = 0 ;
1227
    set_ins ( a, R_TMP ) ;
1228
    stf_ro_ins ( ins, src, tmp_off ) ;
1229
  } 
1230
  else {
1231
    stf_ro_ins ( ins, src, a ) ;
1232
  }
1233
  return ;
1234
}
1235
 
1236
 
1237
/*
1238
  OUTPUT A FLOATING REGISTER, FLOATING REGISTER COMPARISON
1239
*/
1240
 
1241
void rrf_cmp_ins 
1242
    PROTO_N ( ( ins, src1, src2 ) )
1243
    PROTO_T ( ins_p ins X int src1 X int src2 ){
1244
  fprintf ( as_file, "\t%s\t%s,%s\n", ins, FRN(src1), FRN(src2) ) ;
1245
#ifdef NEWDWARF
1246
  count_ins(1);
1247
#endif
1248
  return ;
1249
}
1250
 
1251
 
1252
/*
1253
  OUTPUT A FLOATING REGISTER, FLOATING REGISTER INSTRUCTION
1254
*/
1255
 
1256
void rrf_ins 
1257
    PROTO_N ( ( ins, src, dest ) )
1258
    PROTO_T ( ins_p ins X int src X int dest ){
1259
  clear_freg ( dest ) ;
1260
  fprintf ( as_file, "\t%s\t%s,%s\n", ins, FRN(src), FRN(dest) ) ;
1261
#ifdef NEWDWARF
1262
  count_ins(1);
1263
#endif
1264
  return ;
1265
}
1266
 
1267
 
1268
/*
1269
  OUTPUT A THREE FLOATING REGISTER INSTRUCTION
1270
*/
1271
 
1272
void rrrf_ins 
1273
    PROTO_N ( ( ins, src1, src2, dest ) )
1274
    PROTO_T ( ins_p ins X int src1 X int src2 X int dest ){
1275
  clear_freg ( dest ) ;
1276
  fprintf ( as_file, "\t%s\t%s,%s,%s\n", ins, FRN(src1), 
1277
	    FRN(src2), FRN(dest) ) ;
1278
#ifdef NEWDWARF
1279
  count_ins(1);
1280
#endif
1281
  return ;
1282
}
1283
 
1284
 
1285
 
1286
/*
1287
  OUTPUT AN OPERAND, AS PART OF AN ASM SEQUENCE
1288
*/
1289
 
1290
void out_asm_reg 
1291
    PROTO_N ( ( r, fp ) )
1292
    PROTO_T ( int r X int fp ){
1293
  outs ((fp ? FRN(r) : RN(r)));
1294
  return ;
1295
}
1296
 
1297
void out_asm_boff 
1298
    PROTO_N ( ( b, o2 ) )
1299
    PROTO_T ( baseoff b X long o2 ){
1300
  long off = b.offset + o2;
1301
  if ( off == 0 )
1302
    fprintf ( as_file, "[%s]", RN(b.base));
1303
  else if ( off > 0 )
1304
    fprintf ( as_file, "[%s+%ld]", RN(b.base), off);
1305
  else /* if ( off < 0 ) */
1306
    fprintf ( as_file, "[%s-%ld]", RN(b.base), -off);
1307
  return ;
1308
}