Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

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