Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1996
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
			    VERSION INFORMATION
31
			    ===================
32
 
33
--------------------------------------------------------------------------
34
$Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/output.c,v 1.1.1.1 1998/01/17 15:55:50 release Exp $
35
--------------------------------------------------------------------------
36
$Log: output.c,v $
37
 * Revision 1.1.1.1  1998/01/17  15:55:50  release
38
 * First version to be checked into rolling release.
39
 *
40
Revision 1.4  1997/11/13 08:27:18  ma
41
All avs test passed (except add_to_ptr).
42
 
43
Revision 1.3  1997/11/10 15:38:10  ma
44
.
45
 
46
Revision 1.2  1997/11/09 14:21:00  ma
47
.
48
 
49
Revision 1.1.1.1  1997/10/13 12:42:57  ma
50
First version.
51
 
52
Revision 1.3  1997/06/18 12:04:56  ma
53
Merged with Input Baseline changes.
54
 
55
Revision 1.2  1997/05/13 11:30:38  ma
56
Introduced make_comment for debug.
57
 
58
Revision 1.1.1.1  1997/03/14 07:50:16  ma
59
Imported from DRA
60
 
61
 * Revision 1.2  1996/09/20  13:51:41  john
62
 * *** empty log message ***
63
 *
64
 * Revision 1.1.1.1  1996/09/20  10:56:58  john
65
 *
66
 * Revision 1.1.1.1  1996/03/26  15:45:16  john
67
 *
68
 * Revision 1.2  94/02/21  16:02:42  16:02:42  ra (Robert Andrews)
69
 * Put in an explicit cast.
70
 *
71
 * Revision 1.1  93/02/22  17:16:29  17:16:29  ra (Robert Andrews)
72
 * Initial revision
73
 *
74
--------------------------------------------------------------------------
75
*/
76
 
77
 
78
#include "config.h"
79
#include "common_types.h"
80
#include "assembler.h"
81
#include "instrs.h"
82
#include "fbase.h"
83
#include "mach.h"
84
#include "mach_ins.h"
85
#include "mach_op.h"
86
#include "output.h"
87
#include "codex.h"
88
 
89
 
90
/*
91
    OUTPUT FILE
92
*/
93
 
94
FILE *fpout ;
95
 
96
 
97
/*
98
    OPEN OUTPUT FILE
99
 
100
    This routine opens the file with the given name for output.  If the
101
    name is null, the standard output is used.
102
*/
103
 
104
void open_output
105
    PROTO_N ( ( nm ) )
106
    PROTO_T ( char *nm )
107
{
108
    if ( nm == null ) {
109
	fpout = stdout ;
110
    } else {
111
	fpout = fopen ( nm, "w" ) ;
112
	if ( fpout == null ) {
113
	    error ( "Can't open output file, %s", nm ) ;
114
	    exit ( EXIT_FAILURE ) ;
115
	}
116
    }
117
    return ;
118
}
119
 
120
 
121
/*
122
    ARRAY OF INSTRUCTION NAMES
123
 
124
    This table gives the mapping between instruction numbers and the
125
    corresponding names.
126
*/
127
 
128
#ifdef asm_dotty_instrs
129
#define INSTR_SET_0
130
#endif /* asm_dotty_instrs */
131
 
132
#ifdef asm_simple_instrs
133
#define INSTR_SET_1
134
#endif /* asm_simple_instrs */
135
 
136
char *instr_names [] = {
137
#include "instr_aux.h"
138
} ;
139
 
140
 
141
/*
142
    ARRAY OF GLOBAL REGISTER NAMES
143
 
144
    This table gives the mapping between register numbers and register
145
    names.
146
*/
147
 
148
#ifdef asm_percent_regs
149
#define REGISTER_SET_0
150
#endif /* asm_percent_regs */
151
 
152
#ifdef asm_simple_regs
153
#define REGISTER_SET_1
154
#endif /* asm_simple_regs */
155
 
156
static char *glob_reg_names [] = {
157
#include "instr_aux.h"
158
} ;
159
 
160
 
161
/*
162
    ARRAY OF LOCAL REGISTER NAMES
163
 
164
    This table gives the local mapping between register numbers and
165
    register names.  It is initialized from the table of global register
166
    names, but may be changed thereafter.
167
*/
168
 
169
char *reg_names [ NO_OF_REGS ] ;
170
 
171
 
172
/*
173
    OUTPUT A REGISTER NAME
174
 
175
    This routine outputs the register name corresponding to a given
176
    register number.
177
*/
178
 
179
#define  out_reg_name( X )	outs ( reg_names [ ( X ) ] )
180
 
181
 
182
/*
183
    OUTPUT A SUM OF DATA, EXTERNALS AND LABELS
184
 
185
    This routine prints the sum of all data, external and labels, starting
186
    with ptr, and moving down the plus-chain.
187
*/
188
 
189
static void out_data
190
    PROTO_N ( ( ptr ) )
191
    PROTO_T ( mach_op *ptr )
192
{
193
    mach_op *p ;
194
    bool neg_next = 0 ;
195
    bool need_plus = 0 ;
196
    for ( p = ptr ; p ; p = p->plus ) {
197
	switch ( p->type ) {
198
 
199
	    case MACH_EXT :
200
	    case MACH_EXTQ : {
201
		if ( need_plus || neg_next ) outc ( neg_next ? '-' : '+' ) ;
202
		outs ( p->def.str ) ;
203
		need_plus = 1 ;
204
		neg_next = 0 ;
205
		break ;
206
	    }
207
 
208
	    case MACH_LAB :
209
	    case MACH_LABQ : {
210
		if ( need_plus || neg_next ) outc ( neg_next ? '-' : '+' ) ;
211
		outc ( LPREFIX ) ;
212
		outn ( p->def.num ) ;
213
		need_plus = 1 ;
214
		neg_next = 0 ;
215
		break ;
216
	    }
217
 
218
	    case MACH_SPEC :
219
	    case MACH_SPECQ : {
220
		if ( !output_immediately && p->def.str == special_str ) {
221
		    /* The value of LSx is known, so use it */
222
		    long n = ldisp ;
223
		    if ( neg_next ) n = ( -n ) ;
224
		    if ( p->plus && p->plus->type == MACH_VAL ) {
225
			p->plus->def.num += n ;
226
		    } else {
227
			if ( need_plus && n >= 0 ) outc ( '+' ) ;
228
			outn ( n ) ;
229
			need_plus = 1 ;
230
		    }
231
		} else {
232
		    if ( need_plus || neg_next ) outc ( neg_next ? '-' : '+' ) ;
233
		    outc ( LPREFIX ) ;
234
		    outs ( p->def.str ) ;
235
		    outn ( ( long ) special_no ) ;
236
		    need_plus = 1 ;
237
		}
238
		neg_next = 0 ;
239
		break ;
240
	    }
241
 
242
	    case MACH_VAL :
243
	    case MACH_VALQ : {
244
		long n = p->def.num ;
245
		if ( neg_next ) n = ( -n ) ;
246
		if ( need_plus && n >= 0 ) outc ( '+' ) ;
247
		outn ( n ) ;
248
		need_plus = 1 ;
249
		neg_next = 0 ;
250
		break ;
251
	    }
252
 
253
	    case MACH_HEX :
254
	    case MACH_HEXQ : {
255
		long n = p->def.num ;
256
		if ( neg_next ) n = ( -n ) ;
257
		if ( need_plus && n >= 0 ) outc ( '+' ) ;
258
		outh ( n ) ;
259
		need_plus = 1 ;
260
		neg_next = 0 ;
261
		break ;
262
	    }
263
 
264
	    case MACH_NEG : {
265
		neg_next = 1 ;
266
		break ;
267
	    }
268
 
269
	    default : return ;
270
	}
271
    }
272
    return ;
273
}
274
 
275
 
276
/*
277
    OUTPUT A SCALED OPERAND
278
 
279
    This routine outputs a scaled register operand.
280
*/
281
 
282
static void out_scaled
283
    PROTO_N ( ( ptr ) )
284
    PROTO_T ( mach_op *ptr )
285
{
286
    long sf = ptr->def.num ;
287
    asm_scale_before ;
288
    out_reg_name ( ptr->of->def.num ) ;
289
    if ( sf == 1 ) {
290
	asm_scale_1 ;
291
    } else {
292
	asm_scale ;
293
	outn ( sf ) ;
294
    }
295
    return ;
296
}
297
 
298
 
299
/*
300
    OUTPUT A FLOATING POINT NUMBER
301
 
302
    This routine outputs a floating point number.
303
*/
304
 
305
static void out_float
306
    PROTO_N ( ( f ) )
307
    PROTO_T ( flt *f )
308
{
309
#if ( FBASE == 10 )
310
    int i ;
311
    asm_fprefix ;
312
    if ( f->sign < 0 ) outc ( '-' ) ;
313
    outc ( '0' + f->mant [0] ) ;
314
    outc ( '.' ) ;
315
    for ( i = 1 ; i < MANT_SIZE ; i++ ) outc ( '0' + f->mant [i] ) ;
316
    outc ( 'e' ) ;
317
    if ( f->exp >= 0 ) outc ( '+' ) ;
318
    outn ( f->exp ) ;
319
#else
320
    error ( "Illegal floating point constant" ) ;
321
#endif
322
    return ;
323
}
324
 
325
 
326
/*
327
    MACROS FOR CONSTRUCTS DEPENDING ON asm_data_first
328
*/
329
 
330
#ifdef asm_data_first
331
 
332
#define  out_data_1( X )	if ( X ) out_data ( X )
333
#define  out_data_1a( X )	if ( X ) { out_data ( X ) ; outc ( ',' ) ; }
334
#define  out_data_1b( X )	if ( X ) { outc ( ',' ) ; out_data ( X ) ; }
335
#define  out_sf_data( X, Y )	if ( Y ) out_scaled ( Y )
336
 
337
#else /* asm_data_first */
338
 
339
#define  out_data_1( X )	/* empty */
340
#define  out_data_1a( X )	/* empty */
341
#define  out_data_1b( X )	/* empty */
342
#define  out_sf_data( X, Y )	\
343
    if ( X ) {			\
344
	outc ( '(' ) ;		\
345
	out_data ( X ) ;	\
346
	if ( Y ) {		\
347
	    outc ( ',' ) ;	\
348
	    out_scaled ( Y ) ;	\
349
	}			\
350
	outc ( ')' ) ;		\
351
    } else {			\
352
	if ( Y ) {		\
353
	    outc ( '(' ) ;	\
354
	    out_scaled ( Y ) ;	\
355
	    outc ( ')' ) ;	\
356
	}			\
357
    }
358
 
359
#endif /* asm_data_first */
360
 
361
 
362
/*
363
    OUTPUT A MACHINE OPERAND
364
 
365
    This routine prints a machine operand.
366
*/
367
 
368
static void out_mach_op
369
    PROTO_N ( ( ptr ) )
370
    PROTO_T ( mach_op *ptr )
371
{
372
    mach_op *p = ptr ;
373
    switch ( p->type ) {
374
 
375
	case MACH_BF : {
376
	    /* Bitfield operands */
377
	    long bf_off = p->def.num ;
378
	    long bf_bits = p->plus->def.num ;
379
	    out_mach_op ( p->of ) ;
380
	    asm_bf_before ;
381
	    asm_nprefix ;
382
	    outn ( bf_off ) ;
383
	    asm_bf_middle ;
384
	    asm_nprefix ;
385
	    outn ( bf_bits ) ;
386
	    asm_bf_after ;
387
	    return ;
388
	}
389
 
390
	case MACH_CONT : {
391
	    p = p->of ;
392
	    switch ( p->type ) {
393
 
394
		case MACH_CONT : {
395
		    /* Memory indirect (post- or pre-indexed) */
396
		    mach_op *p1 = p->plus ;
397
		    mach_op *p2 = null ;
398
		    mach_op *q = p->of ;
399
		    mach_op *q1 = q->plus ;
400
		    mach_op *q2 = null ;
401
		    if ( p1 && p1->type == MACH_SCALE ) {
402
			p2 = p1 ;
403
			p1 = p2->plus ;
404
		    }
405
		    if ( q1 && q1->type == MACH_SCALE ) {
406
			if ( p2 ) {
407
			    error ( "Illegal addressing mode" ) ;
408
			    outs ( "error" ) ;
409
			    return ;
410
			}
411
			q2 = q1 ;
412
			q1 = q2->plus ;
413
		    }
414
		    asm_mem_before ;
415
		    out_data_1a ( q1 ) ;
416
		    out_reg_name ( q->def.num ) ;
417
		    asm_mem_second ;
418
		    out_sf_data ( q1, q2 ) ;
419
		    asm_mem_third ;
420
		    out_sf_data ( p1, p2 ) ;
421
		    if ( p2 ) out_scaled ( p2 ) ;
422
		    out_data_1b ( p1 ) ;
423
		    asm_mem_after ;
424
		    return ;
425
		}
426
 
427
		case MACH_REG : {
428
		    /* Register indirect (with displacement or index) */
429
		    mach_op *p1 = p->plus ;
430
		    mach_op *p2 = null ;
431
		    if ( p1 ) {
432
			if ( p1->type == MACH_SCALE ) {
433
			    p2 = p1 ;
434
			    p1 = p2->plus ;
435
			}
436
			out_data_1 ( p1 ) ;
437
		    }
438
		    asm_ind_before ;
439
		    out_reg_name ( p->def.num ) ;
440
		    asm_ind_middle ;
441
		    out_sf_data ( p1, p2 ) ;
442
		    asm_ind_after ;
443
		    return ;
444
		}
445
 
446
		case MACH_EXTQ : {
447
		    /* External indirect (with displacement or index) */
448
		    mach_op *p1 = p->plus ;
449
		    mach_op *p2 = null ;
450
		    if ( p1 ) {
451
			if ( p1->type == MACH_SCALE ) {
452
			    p2 = p1 ;
453
			    p1 = p2->plus ;
454
			}
455
			out_data_1 ( p1 ) ;
456
		    }
457
		    asm_ind_before ;
458
		    outs ( p->def.str ) ;
459
		    asm_ind_middle ;
460
		    out_sf_data ( p1, p2 ) ;
461
		    asm_ind_after ;
462
		    return ;
463
		}
464
 
465
		case MACH_EXT :
466
		case MACH_LAB :
467
		case MACH_SPEC :
468
		case MACH_VAL :
469
		case MACH_HEX :
470
		case MACH_NEG : {
471
		    /* Contents of immediate data, externals, labels */
472
		    out_data ( p ) ;
473
		    return ;
474
		}
475
	    }
476
	    error ( "Illegal addressing mode" ) ;
477
	    outs ( "error" ) ;
478
	    return ;
479
	}
480
 
481
	case MACH_DEC : {
482
	    /* Register indirect with predecrement */
483
	    asm_predec_before ;
484
	    out_reg_name ( p->def.num ) ;
485
	    asm_predec_after ;
486
	    return ;
487
	}
488
 
489
	case MACH_INC : {
490
	    /* Register indirect with postincrement */
491
	    asm_postinc_before ;
492
	    out_reg_name ( p->def.num ) ;
493
	    asm_postinc_after ;
494
	    return ;
495
	}
496
 
497
	case MACH_REG : {
498
	    /* Register direct */
499
	    out_reg_name ( p->def.num ) ;
500
	    return ;
501
	}
502
 
503
	case MACH_RPAIR : {
504
	    /* Register pair */
505
	    out_reg_name ( p->def.num ) ;
506
	    asm_rpair_sep ;
507
	    out_reg_name ( p->plus->def.num ) ;
508
	    return ;
509
	}
510
 
511
	case MACH_EXT :
512
	case MACH_LAB :
513
	case MACH_SPEC :
514
	case MACH_VAL :
515
	case MACH_HEX : {
516
	    /* Immediate data, externals, labels */
517
	    asm_nprefix ;
518
	    out_data ( p ) ;
519
	    return ;
520
	}
521
 
522
	case MACH_EXTQ :
523
	case MACH_LABQ :
524
	case MACH_SPECQ : {
525
	    /* Contents of externals, labels */
526
	    out_data ( p ) ;
527
	    return ;
528
	}
529
 
530
	case MACH_FLOATQ : {
531
	    /* Floating-point data */
532
	    out_float ( p->def.fp ) ;
533
	    return ;
534
	}
535
 
536
	case MACH_VALQ : {
537
	    /* Integer data */
538
	    outn ( p->def.num ) ;
539
	    return ;
540
	}
541
 
542
	case MACH_HEXQ : {
543
	    /* Integer data */
544
	    outh ( p->def.num ) ;
545
	    return ;
546
	}
547
    }
548
    error ( "Illegal addressing mode" ) ;
549
    outs ( "error" ) ;
550
    return ;
551
}
552
 
553
 
554
/*
555
    OUTPUT ALL MACHINE INSTRUCTIONS
556
 
557
    This routine outputs all the machine instructions, together with their
558
    operands (if any).
559
*/
560
 
561
void output_all
562
    PROTO_Z ()
563
{
564
    int n ;
565
    mach_ins *p ;
566
    for ( p = all_mach_ins ; p ; p = p->next ) {
567
	n = p->ins_no ;
568
#ifdef EBUG
569
#if 1
570
        if ( n != m_comment ) {
571
           outs ( "#inst" ) ;
572
           outn ( p->id ) ;
573
           outnl () ;
574
        }
575
        if ( p->id == 4921 ) {
576
           int found = 1 ;
577
        }
578
#endif
579
#endif
580
	switch ( n ) {
581
#ifdef EBUG
582
            case m_comment : {
583
               outs ( "#" ) ;
584
               outs ( p->op1->def.str ) ;
585
               outnl () ;
586
               break ;
587
            }
588
#endif
589
 
590
#ifdef m_ignore_ins
591
	    case m_ignore_ins : {
592
		/* Ignore */
593
		break ;
594
	    }
595
#endif /* m_ignore_ins */
596
 
597
	    case m_label_ins : {
598
		/* Labels */
599
		outc ( LPREFIX ) ;
600
		outn ( p->op1->def.num ) ;
601
		outc ( ':' ) ;
602
		outnl () ;
603
		break ;
604
	    }
605
 
606
	    case m_extern_ins : {
607
		/* Externals */
608
		out_data ( p->op1 ) ;
609
		outc ( ':' ) ;
610
		outnl () ;
611
		break ;
612
	    }
613
 
614
#ifdef asm_uses_equals
615
	    case m_as_assign : {
616
		out_mach_op ( p->op1 ) ;
617
		outc ( '=' ) ;
618
		out_mach_op ( p->op2 ) ;
619
		outnl () ;
620
		break ;
621
	    }
622
#endif /* asm_uses_equals */
623
 
624
	    case m_as_byte :
625
	    case m_as_short :
626
	    case m_as_long :
627
	    case m_stabs :
628
	    case m_stabd :
629
	    case m_stabn :
630
	    case m_dd_special : {
631
		/* Data */
632
		mach_op *q ;
633
		bool started = 0 ;
634
		int c = 0 ;
635
		for ( q = p->op1 ; q ; q = q->of ) {
636
		    if ( c == 0 ) {
637
			if ( started ) outnl () ;
638
			outs ( instr_names [n] ) ;
639
		    } else {
640
			outc ( ',' ) ;
641
		    }
642
		    out_data ( q ) ;
643
		    started = 1 ;
644
		    if ( ++c == 8 ) c = 0 ;
645
		}
646
		outnl () ;
647
		break ;
648
	    }
649
 
650
	    default : {
651
		if ( is_jump ( n ) ) {
652
		    /* Jumps */
653
#ifndef asm_does_jump_lens
654
		    if ( is_unsized ( n ) ) n += long_jump ;
655
#endif /* !asm_does_jump_lens */
656
		    outs ( instr_names [n] ) ;
657
		    outc ( LPREFIX ) ;
658
		    outn ( p->op1->def.num ) ;
659
		    if ( n == m_bra || n == m_brab ||
660
			 n == m_braw || n == m_bral ) {
661
			/* Align after unconditional jumps */
662
			outnl () ;
663
#ifndef no_align_directives
664
                        outs ( instr_names [ m_as_align4 ] ) ;
665
#endif
666
		    }
667
		} else {
668
		    /* Simple instructions */
669
		    outs ( instr_names [n] ) ;
670
		    if ( p->op1 ) out_mach_op ( p->op1 ) ;
671
		    if ( p->op2 ) {
672
			outc ( ',' ) ;
673
#ifdef EBUG
674
			outc ( ' ' ) ;
675
#endif /* EBUG */
676
			out_mach_op ( p->op2 ) ;
677
		    }
678
		}
679
		outnl () ;
680
		break ;
681
	    }
682
	}
683
    }
684
    return ;
685
}
686
 
687
 
688
/*
689
    INITIALIZE INSTRUCTIONS
690
 
691
    Apply a couple of patches for odd instruction quirks.
692
*/
693
 
694
void init_instructions
695
    PROTO_Z ()
696
{
697
#ifdef asm_no_btst_suffix
698
    instr_names [ m_btstb ] = instr_names [ m_btst ] ;
699
    instr_names [ m_btstl ] = instr_names [ m_btst ] ;
700
#endif /* asm_no_btst_suffix */
701
    return ;
702
}
703
 
704
 
705
/*
706
    INITIALIZE OUTPUT ROUTINES
707
 
708
    This routine copies the table of global register names into the
709
    table of global register names and
710
*/
711
 
712
void init_output
713
    PROTO_Z ()
714
{
715
    memcpy ( reg_names, glob_reg_names, sizeof ( glob_reg_names ) ) ;
716
#ifdef SYSV_ABI
717
    {
718
	char *r = reg_names [ REG_A0 ] ;
719
	reg_names [ REG_A0 ] = reg_names [ REG_A1 ] ;
720
	reg_names [ REG_A1 ] = r ;
721
    }
722
#endif /* SYS_ABI */
723
    all_mach_ins = null ;
724
    current_ins = null ;
725
    return ;
726
}
727
 
728
 
729
#ifdef EBUG
730
 
731
extern bool seek_line ;
732
extern int seek_line_no ;
733
 
734
 
735
/*
736
    OUTPUT NEW LINE (DEBUG MODE ONLY)
737
 
738
    In debug mode a count is keep of the current line number in the
739
    output file to allow stopping the debugger at a given line.  Normally
740
    outnl is a macro which just outputs a newline character.
741
*/
742
 
743
void outnl
744
    PROTO_Z ()
745
{
746
    static int line_no = 0 ;
747
    outc ( '\n' ) ;
748
    line_no++ ;
749
    if ( seek_line && line_no == seek_line_no ) {
750
	warning ( "Line %d reached", line_no ) ;
751
	breakpoint () ;
752
    }
753
    return ;
754
}
755
 
756
#endif /* EBUG */