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-2005 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) 1997
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
 
61
/* 80x86/instr.c */
62
 
63
/**********************************************************************
64
$Author: pwe $
65
$Date: 1998/03/15 16:00:19 $
66
$Revision: 1.2 $
67
$Log: instr.c,v $
68
 * Revision 1.2  1998/03/15  16:00:19  pwe
69
 * regtrack dwarf dagnostics added
70
 *
71
 * Revision 1.1.1.1  1998/01/17  15:55:51  release
72
 * First version to be checked into rolling release.
73
 *
74
 * Revision 1.28  1997/04/17  11:55:47  pwe
75
 * dwarf2 improvements
76
 *
77
 * Revision 1.27  1997/03/24  11:15:13  pwe
78
 * dwarf2 option/default
79
 *
80
 * Revision 1.26  1997/03/20  16:23:41  pwe
81
 * dwarf2
82
 *
83
 * Revision 1.25  1997/02/18  11:42:52  pwe
84
 * NEWDIAGS for debugging optimised code
85
 *
86
 * Revision 1.24  1996/12/13  14:39:27  pwe
87
 * prep NEWDIAGS
88
 *
89
 * Revision 1.23  1996/07/09  09:43:39  pwe
90
 * caller env_offset if callees present, and tidy
91
 *
92
 * Revision 1.22  1996/05/20  14:30:11  pwe
93
 * improved 64-bit handling
94
 *
95
 * Revision 1.21  1996/05/13  12:51:55  pwe
96
 * undo premature commit
97
 *
98
 * Revision 1.19  1996/01/17  11:24:31  pwe
99
 * resurrect performance
100
 *
101
 * Revision 1.18  1995/11/01  18:41:14  pwe
102
 * PIC tail_call and exception handling
103
 *
104
 * Revision 1.17  1995/10/24  17:02:43  pwe
105
 * local calls to avoid PLT, Solaris constraint
106
 *
107
 * Revision 1.16  1995/10/16  14:55:19  pwe
108
 * stack change v fpucon
109
 *
110
 * Revision 1.15  1995/09/26  16:46:48  pwe
111
 * compare with zero to ignore previous overflow
112
 *
113
 * Revision 1.14  1995/09/15  17:39:13  pwe
114
 * tidy and correct fistp
115
 *
116
 * Revision 1.13  1995/09/08  12:51:07  pwe
117
 * exceptions improved
118
 *
119
 * Revision 1.12  1995/09/06  16:29:20  pwe
120
 * exceptions now OK
121
 *
122
 * Revision 1.11  1995/09/05  16:24:51  pwe
123
 * specials and exception changes
124
 *
125
 * Revision 1.10  1995/09/01  17:30:05  pwe
126
 * traps and Build scripts
127
 *
128
 * Revision 1.9  1995/08/30  16:06:33  pwe
129
 * prepare exception trapping
130
 *
131
 * Revision 1.8  1995/08/23  09:42:42  pwe
132
 * track fpu control word for trap etc
133
 *
134
 * Revision 1.7  1995/08/14  13:53:36  pwe
135
 * several corrections, tail calls and error jumps
136
 *
137
 * Revision 1.6  1995/08/04  08:29:23  pwe
138
 * 4.0 general procs implemented
139
 *
140
 * Revision 1.5  1995/04/12  17:05:54  pwe
141
 * name_prefix required for call_libfn
142
 *
143
 * Revision 1.4  1995/02/16  18:47:08  pwe
144
 * transformed subtract inverts, sets and adds carry in case of error_jump
145
 *
146
 * Revision 1.3  1995/01/30  12:56:18  pwe
147
 * Ownership -> PWE, tidy banners
148
 *
149
 * Revision 1.2  1994/11/08  09:55:03  jmf
150
 * Unknown?
151
 *
152
 * Revision 1.1  1994/10/27  14:15:22  jmf
153
 * Initial revision
154
 *
155
 * Revision 1.4  1994/08/08  15:54:29  jmf
156
 * Dont keep_short after label
157
 *
158
 * Revision 1.3  1994/07/15  13:59:23  jmf
159
 * Change fstack popping to use fstp st(0).
160
 *
161
 * Revision 1.2  1994/07/12  15:19:18  jmf
162
 * No change
163
 *
164
 * Revision 1.1  1994/07/12  14:33:55  jmf
165
 * Initial revision
166
 *
167
**********************************************************************/
168
 
169
 
170
/**********************************************************************
171
                           instr.c
172
 
173
 
174
   defines the general routines for outputting instructions and labels:
175
 
176
 
177
 
178
**********************************************************************/
179
 
180
 
181
#include "config.h"
182
#include "common_types.h"
183
#include "out.h"
184
#include "operand.h"
185
#include "instrmacs.h"
186
#include "expmacs.h"
187
#include "exp.h"
188
#include "instr386.h"
189
#include "flags.h"
190
#include "tags.h"
191
#include "shapemacs.h"
192
#include "flpt.h"
193
#include "flpttypes.h"
194
#include "coder.h"
195
#include "basicread.h"
196
#include "reg_record.h"
197
#include "installglob.h"
198
#include "table_fns.h"
199
#include "codermacs.h"
200
#include "install_fns.h"
201
#include "machine.h"
202
#include "localflags.h"
203
#include "assembler.h"
204
#include "messages_8.h"
205
#include "readglob.h"
206
#include "check.h"
207
#include "label_ops.h"
208
#include "externs.h"
209
#include "xalloc.h"
210
 
211
#include "instr.h"
212
 
213
#ifdef NEWDWARF
214
#include "dw2_config.h"
215
#include "dw2_extra.h"
216
#endif
217
 
218
 
219
/* LOCAL TYPE */
220
 
221
typedef union eu_u {int i; exp e;} punner;
222
 
223
/* MACROS */
224
 
225
#define fstack_base 8
226
 
227
/* VARIABLES */
228
/* All variables initialised */
229
 
230
int  extra_stack = 0;	/* init by init_all */
231
int max_extra_stack = 0;	/* init by cproc */
232
int no_frame;		/* init by cproc */
233
#ifndef NEWDIAGS
234
static long  last_jump_pos;	/* set locally */
235
#endif
236
int  last_jump_label;	/* cleared to -1 by outnl */
237
 
238
static exp cont_err_handler = nilexp;
239
 
240
 
241
/* IDENTITIES */
242
 
243
char *margin = " ";		/* instruction left margin */
244
char *spx = " ";		/* separates instruction from operands */
245
char *sep = ",";		/* separates operands */
246
 
247
char *reg_name_long[8] = {
248
  "%eax", "%edx", "%ecx", "%ebx", "%edi", "%esi", "%ebp", "%esp"
249
};
250
char *reg_name_word[7] = {
251
  "%ax", "%dx", "%cx", "%bx", "%di", "%si", "%bp"
252
};
253
char *reg_name_byte[7] = {
254
  "%al", "%dl", "%cl", "%bl", "%??", "%??", "%??"
255
};
256
 
257
char *fl_reg_name[8] = {
258
  "%st", "%st(1)", "%st(2)", "%st(3)", "%st(4)", "%st(5)", "%st(6)",
259
  "%st(7)",
260
};
261
 
262
/* PROCEDURES */
263
 
264
void temp_push_fl
6 7u83 265
(void)
2 7u83 266
{
267
  ++fstack_pos;
268
  return;
269
}
270
void temp_pop_fl
6 7u83 271
(void)
2 7u83 272
{
273
  --fstack_pos;
274
  return;
275
}
276
 
277
 
278
/***************************************************************
279
 
280
outreal outputs a floating point number
281
 
282
****************************************************************/
283
 
284
void outreal
6 7u83 285
(exp e)
2 7u83 286
{
287
  flt * f = &flptnos[no(e)];
288
  int sw = name(sh(e)) - shrealhd;
289
  r2l longs;
290
 
291
  longs = real2longs_IEEE(f, sw);
292
 
293
  switch (sw) {
294
    case 0:
295
      outhex(longs.i1);
296
      outnl();
297
      break;
298
    case 1:
299
      outhex(longs.i1);
300
      outs(",");
301
      outhex(longs.i2);
302
      outnl();
303
      break;
304
    case 2:
305
      outhex(longs.i1);
306
      outs(",");
307
      outhex(longs.i2);
308
      outs(",");
309
      outhex(longs.i3);
310
      outnl();
311
      break;
312
  };
313
 
314
  return;
315
}
316
 
317
/* output operand i (in bytes) relative to
318
   stack pointer  uses address relative to
319
   frame pointer if it might be shorter */
320
void rel_sp
6 7u83 321
(int i, int b)
2 7u83 322
{
323
  int  n = i + (extra_stack / 8);
324
  if (!must_use_bp) {
325
				/* if we might use alloca all
326
				   displacements must be relative to frame
327
				   pointer */
328
    if (n == 0) {
6 7u83 329
      outs("(%esp");
2 7u83 330
      if (b)
6 7u83 331
	outs(")");
2 7u83 332
      return;
333
    };
334
    if (n <= 127 || no_frame || stack_aligned_8byte) {
335
				/* use stack pointer if displacement from
336
				   it is small */
6 7u83 337
      outn((long)n);
338
      outs("(%esp");
2 7u83 339
      if (b)
6 7u83 340
	outs(")");
2 7u83 341
      return;
342
    };
343
  };
344
  /* otherwise use displacement from frame pointer */
6 7u83 345
  outn((long)(i + (stack_dec / 8)));
2 7u83 346
  outs("-");
347
  outs(local_prefix);
6 7u83 348
  outs("disp");
349
  outn((long)crt_proc_id);
350
  outs("(%ebp");
2 7u83 351
  if (b)
6 7u83 352
    outs(")");
2 7u83 353
  return;
354
}
355
 
356
/* output operand i (in bytes) relative to
357
   stack pointer */
358
void rel_cp
6 7u83 359
(int i, int b)
2 7u83 360
{
361
  int  n = i + (extra_stack / 8);
362
  if (n == 0) {
6 7u83 363
    outs("(%esp");
2 7u83 364
    if (b)
6 7u83 365
      outs(")");
2 7u83 366
    return;
367
  };
6 7u83 368
  outn((long)n);
369
  outs("(%esp");
2 7u83 370
  if (b)
6 7u83 371
    outs(")");
2 7u83 372
  return;
373
}
374
 
375
/* output operand relative to frame
376
   pointer */
377
void rel_ap
6 7u83 378
(int i, int b)
2 7u83 379
{
380
  if (no_frame) {
6 7u83 381
    outn((long)(i + ((extra_stack - stack_dec) / 8)));
2 7u83 382
    outs("+");
383
    outs(local_prefix);
6 7u83 384
    outs("disp");
385
    outn((long)crt_proc_id);
386
    outs("(%esp");
2 7u83 387
    if (b)
6 7u83 388
      outs(")");
2 7u83 389
    return;
390
  }
391
  else {
6 7u83 392
    outn((long)i + 4);
393
    outs("(%ebp");
2 7u83 394
    if (b)
6 7u83 395
      outs(")");
2 7u83 396
    return;
397
  };
398
}
399
 
400
/* output operand relative to frame
401
   pointer and push space*/
402
void rel_ap1
6 7u83 403
(int i, int b)
2 7u83 404
{
405
  if (no_frame) {
6 7u83 406
    outn((long)(i + ((extra_stack - stack_dec) / 8)));
2 7u83 407
    outs("+");
408
    outs(local_prefix);
6 7u83 409
    outs("fcwdisp");
410
    outn((long)crt_proc_id);
411
    outs("(%esp");
2 7u83 412
    if (b)
6 7u83 413
      outs(")");
2 7u83 414
    return;
415
  }
416
  else {
6 7u83 417
    outn((long)i);
2 7u83 418
    outs("-");
419
    outs(local_prefix);
6 7u83 420
    outs("fcwdisp");
421
    outn((long)crt_proc_id);
422
    outs("(%ebp");
2 7u83 423
    if (b)
6 7u83 424
      outs(")");
2 7u83 425
    return;
426
  };
427
}
428
 
429
int  get_reg_no
6 7u83 430
(int regs)
2 7u83 431
{
432
  frr fr;
433
  /* find the registers associated with the bit pattern regs */
434
 
6 7u83 435
  fr = first_reg(regs);
2 7u83 436
  if (regs == 0x10000 || fr.fr_no == (fstack_pos))
6 7u83 437
    return(fstack_pos);
2 7u83 438
  return (fr.fr_no);		/* this is the register number */
439
}
440
 
441
/* output a register address, regs is a
442
   bit pattern, rdisp is an offset in bit
443
   units. le tells us how to refer to the
444
   register (eg al or ax or eax) */
445
void regn
6 7u83 446
(int regs, int rdisp, exp ldname, int le)
2 7u83 447
{
448
  int  z;
449
  char **rn;
450
  UNUSED(rdisp);
6 7u83 451
  z = get_reg_no(regs);
2 7u83 452
 
6 7u83 453
  if (name(ldname) == name_tag && islastuse(ldname))
2 7u83 454
    regsinuse = regsinuse & ~regs;
455
 
456
  if (z >= first_fl_reg) {
457
    if (z == first_fl_reg) {
6 7u83 458
      outs(fl_reg_name[0]);
2 7u83 459
      return;
460
    };
461
    if (fstack_pos > 16) {
6 7u83 462
      failer(BAD_FSTACK);
2 7u83 463
      exit(EXIT_FAILURE);
464
    };
6 7u83 465
    outs(fl_reg_name[fstack_pos - z]);
2 7u83 466
    /* variables held in the floating point registers have to be addressed
467
       relative to the current stack position, because the registers are a
468
       stack as well as a register bank */
469
    return;
470
  };
471
 
472
  switch (le) {
473
    case 8:
474
      rn = reg_name_byte;
475
      break;
476
    case 16:
477
      rn = reg_name_word;
478
      break;
479
    default:
480
      rn = reg_name_long;
481
      break;
482
  };
483
  outs (rn[z]);			/* this outputs the register name */
484
  return;
485
}
486
 
487
 
488
/* output a displacement from register operand */
489
void ind_reg
6 7u83 490
(int regs, int rdisp, int offset, exp ldname, int b)
2 7u83 491
{
492
  if (regs == 128)
493
    offset += extra_stack;
494
 
495
  if (offset == 0) {
6 7u83 496
    outs("(");
497
    regn(regs, rdisp, ldname, 32);
2 7u83 498
    if (b)
6 7u83 499
      outs(")");
2 7u83 500
  }
501
  else {
6 7u83 502
    outn((long)offset / 8);
503
    outs("(");
504
    regn(regs, rdisp, ldname, 32);
2 7u83 505
    if (b)
6 7u83 506
      outs(")");
2 7u83 507
  };
508
  return;
509
}
510
 
511
/* use indexed addressing */
512
void index_opnd
6 7u83 513
(where whmain, where wh, int sc)
2 7u83 514
{
515
  exp m = whmain.where_exp;
6 7u83 516
  if ((name(m) == name_tag && ptno(son(m)) == reg_pl) ||
517
     (name(m) == cont_tag && name(son(m)) == name_tag &&
518
	isvar(son(son(m))) && ptno(son(son(m))) == reg_pl))
519
    outs("(");
520
  operand(32, whmain, 0, 0);
521
  outs(",");
522
  operand(32, wh, 1, 0);
2 7u83 523
  if (sc != 1) {
6 7u83 524
    outs(",");
525
    outn((long)sc);
2 7u83 526
  };
6 7u83 527
  outs(")");
2 7u83 528
  return;
529
}
530
 
531
 
532
/* output an external operand */
533
void extn
6 7u83 534
(exp id, int off, int b)
2 7u83 535
{
536
  dec * et;
537
 
6 7u83 538
  et = brog(id);
2 7u83 539
 
540
  if (PIC_code)
541
   {
542
     char * got;
543
     if (et -> dec_u.dec_val.extnamed)
544
        got = "GOT";
545
     else
546
        got = "GOTOFF";
6 7u83 547
     outs(et -> dec_u.dec_val.dec_id);
2 7u83 548
     outs("@");
549
     outs(got);
550
     if (off != 0)
551
      {
6 7u83 552
        outs("+");
553
        outn((long)off / 8);
2 7u83 554
      };
555
     outs("(%ebx");
556
     if (b)
557
       outs(")");
558
     return;
559
   };
560
 
561
  if (off == 0)
6 7u83 562
    outs(et -> dec_u.dec_val.dec_id);
2 7u83 563
  else {
6 7u83 564
    outs(et -> dec_u.dec_val.dec_id);
565
    outs("+");
566
    outn((long)off / 8);
2 7u83 567
  };
568
  if (!b)
6 7u83 569
    outs("(");
2 7u83 570
  return;
571
}
572
 
573
/* an integer constant */
574
void int_operand
6 7u83 575
(int k, int l)
2 7u83 576
{
577
  int  mask;
578
  switch (l) {
579
    case 8:
580
      mask = 0xff;
581
      break;
582
    case 16:
583
      mask = 0xffff;
584
      break;
585
    default:
586
      mask = 0xffffffff;
587
  };
6 7u83 588
  outs("$");
589
  outn((long)k & mask);
2 7u83 590
  return;
591
}
592
 
593
 
594
/* an external literal */
595
void const_extn
6 7u83 596
(exp ident, int noff)
2 7u83 597
{
598
  if (!PIC_code)
6 7u83 599
    outs("$");
600
  extn(ident, noff, 1);
2 7u83 601
  return;
602
}
603
 
604
/* an external literal */
605
void proc_extn
6 7u83 606
(exp id, int off)
2 7u83 607
{
608
  if (PIC_code)
609
   {
610
     dec * et;
6 7u83 611
     et = brog(id);
2 7u83 612
     if (off == 0)
6 7u83 613
       outs(et -> dec_u.dec_val.dec_id);
2 7u83 614
     else {
6 7u83 615
        outn((long)off / 8);
616
        outs("+");
617
        outs(et -> dec_u.dec_val.dec_id);
2 7u83 618
     };
619
     if (et -> dec_u.dec_val.extnamed)
620
        outs("@PLT");
621
   }
622
  else
623
   {
6 7u83 624
     outs("$");
625
     extn(id, off, 1);
2 7u83 626
   };
627
 
628
  return;
629
}
630
 
631
void ldisp
6 7u83 632
(void)
2 7u83 633
{
634
   outs(local_prefix);
635
   outs("disp");
636
   outn((long)crt_proc_id);
637
}
638
 
639
void label_operand
6 7u83 640
(exp e)
2 7u83 641
{
642
  punner l;
643
  l.e = pt(e);
644
  outs("$");
645
  outs(local_prefix);
646
  outs("V");
647
  outn((long)l.i);
648
  return;
649
}
650
 
651
void set_lv_label
6 7u83 652
(exp e)
2 7u83 653
{
654
  punner l;
655
  l.e = e;
656
  min_rfree |= 0x78;  /* save all callee registers */
657
 
658
  outs(local_prefix);
659
  outs("V");
660
  outn((long)l.i);
661
  outs(":");
662
  outnl();
663
  return;
664
}
665
 
666
void set_env_off
6 7u83 667
(int s, exp n)
2 7u83 668
{
669
  punner l;
670
  l.e = n;
671
  outs(".set ");
672
  outs(local_prefix);
673
  outs("O");
674
  outn((long)l.i);		/* produce an identifying number */
675
  outs(",");
676
  if (s<4)
677
   {
6 7u83 678
    outn((long) -s/8);
2 7u83 679
    outs("-");
680
    outs(local_prefix);
6 7u83 681
    outs("disp");
682
    outn((long)crt_proc_id);
2 7u83 683
   }
684
  else
685
   outn((long)s/8);
686
  outnl();
687
}
688
 
689
void envoff_operand
6 7u83 690
(exp e, int off)
2 7u83 691
{
692
  punner l;
693
  l.e = e;
694
  if (off != 0)
695
   {
696
    outn((long)off);
697
    outs("+");
698
   };
699
  outs(local_prefix);
700
  outs("O");
701
  outn((long)l.i);		/* produce an identifying number */
702
  return;
703
}
704
 
705
void envsize_operand
6 7u83 706
(exp e)
2 7u83 707
{
708
  dec * et = brog(e);
6 7u83 709
  outs(local_prefix);
710
  outs("ESZ");
711
  outs(et -> dec_u.dec_val.dec_id);
2 7u83 712
  return;
713
}
714
 
715
/* 80386 instruction with no operands */
716
void ins0
6 7u83 717
(char *i)
2 7u83 718
{
6 7u83 719
  outs(margin);
720
  outs(i);
721
  outnl();
2 7u83 722
  return;
723
}
724
 
725
/* one operand */
726
void ins1
6 7u83 727
(char *i, int le1, where a1)
2 7u83 728
{
6 7u83 729
  outs(margin);
730
  outs(i);
731
  outs(spx);
732
  operand(le1, a1, 1, 0);
733
  outnl();
2 7u83 734
  return;
735
}
736
 
737
/* one operand, which is indirect */
738
void ins1ind
6 7u83 739
(char *i, int le1, where a1)
2 7u83 740
{
6 7u83 741
  outs(margin);
742
  outs(i);
743
  outs(spx);
744
  outs("*");
745
  operand(le1, a1, 1, 0);
746
  outnl();
2 7u83 747
  return;
748
}
749
 
750
/* one operand, which is immediate */
751
void ins1lit
6 7u83 752
(char *i, int le1, where a1)
2 7u83 753
{
6 7u83 754
  outs(margin);
755
  outs(i);
756
  outs(spx);
757
  operand(le1, a1, 1, 1);
758
  outnl();
2 7u83 759
  return;
760
}
761
 
762
/* two operands */
763
void ins2
6 7u83 764
(char *i, int le1, int le2, where a1, where a2)
2 7u83 765
{
6 7u83 766
  outs(margin);
767
  outs(i);
768
  outs(spx);
769
  operand(le1, a1, 1, 0);
770
  outs(sep);
771
  operand(le2, a2, 1, 0);
772
  outnl();
2 7u83 773
  return;
774
}
775
 
776
/* three operands */
777
void ins3
6 7u83 778
(char *i, int le1, int le2, int le3, where a1, where a2, where a3)
2 7u83 779
{
6 7u83 780
  outs(margin);
781
  outs(i);
782
  outs(spx);
783
  operand(le1, a1, 1, 0);
784
  outs(sep);
785
  operand(le2, a2, 1, 0);
786
  outs(sep);
787
  operand(le3, a3, 1, 0);
788
  outnl();
2 7u83 789
  return;
790
}
791
 
792
 
793
void simplest_set_lab
6 7u83 794
(int labno)
2 7u83 795
{
796
  outs(local_prefix);
6 7u83 797
  outn((long)labno);
798
  outs(":");
799
  outnl();
2 7u83 800
}
801
 
802
 
803
void simple_set_label
6 7u83 804
(int labno)
2 7u83 805
{
806
#ifdef CHECKIMPROVE
807
  if (labno == last_jump_label)
808
    failer("redundant jump");
809
#endif
810
#ifndef NEWDIAGS
811
  int   st = 0;
812
  if (!diagnose && labno == last_jump_label) {
6 7u83 813
    st = fseek(fpout, last_jump_pos, 0);
2 7u83 814
  };
815
  /* eliminate immediately previous jump to this label */
816
  if (st == -1) {
6 7u83 817
    failer(SEEK_FAILURE);
2 7u83 818
    exit(EXIT_FAILURE);
819
  };
820
#endif
821
 
822
  cond1_set = 0;
823
  cond2_set = 0;
824
  outs(local_prefix);
825
  outn ((long)labno);		/* the label no is held in the ptr field
826
				*/
6 7u83 827
  outs(":");
828
  outnl();
2 7u83 829
/* Removed for experiments: improves compress?
830
  keep_short = 1;
831
*/
832
  return;
833
}
834
 
835
/* set label described by the jump record jr */
836
void set_label
6 7u83 837
(exp jr)
2 7u83 838
{
6 7u83 839
  simple_set_label(ptno(jr));
2 7u83 840
}
841
 
842
/*  jump record: exp
843
    pt - label;
844
    last - forward;
845
    son - stack_dec;
846
    prop - floating stack position
847
*/
848
 
849
void discard_fstack
6 7u83 850
(void)
2 7u83 851
{
6 7u83 852
  outs(" fstp %st(0)");
853
  outnl();
2 7u83 854
  pop_fl;
855
  return;
856
}
857
 
858
void discard_st1
6 7u83 859
(void)
2 7u83 860
{
6 7u83 861
  outs(" fstp %st(1)");
862
  outnl();
2 7u83 863
  pop_fl;
864
}
865
 
866
 
867
/* output a jump to the label described by
868
   jump record jr */
869
void jump
6 7u83 870
(exp jr, int with_fl_reg)
2 7u83 871
{
6 7u83 872
  int  fs_dest = (int)fstack_pos_of(jr);
2 7u83 873
  int  good_fs = fstack_pos;
874
  int  good_sd = stack_dec;
875
  if (fs_dest < first_fl_reg)
6 7u83 876
    failer(FSTACK_UNSET);
2 7u83 877
  if (with_fl_reg) {		/* jumping with a floating value */
878
    /* clear off any unwanted stack registers */
879
    while (fstack_pos > (fs_dest + 1))
6 7u83 880
      discard_st1();
2 7u83 881
    fstack_pos = good_fs - 1;
882
  }
883
  else {
884
    /* clear off any unwanted stack registers */
885
    while (fstack_pos > fs_dest)
6 7u83 886
      discard_fstack();
2 7u83 887
    fstack_pos = good_fs;
888
  };
889
 
890
  if (sonno(jr) > stack_dec) {
6 7u83 891
    add(slongsh, mw(zeroe,(sonno(jr) -stack_dec) / 8), sp, sp);
2 7u83 892
    stack_dec = sonno(jr);
893
  }
894
 
895
  reset_fpucon();
896
  stack_dec = good_sd;
897
 
898
#ifndef NEWDIAGS
899
  if (flush_before_tell)
900
    IGNORE fflush(fpout);
6 7u83 901
  last_jump_pos = ftell(fpout);
2 7u83 902
#endif
6 7u83 903
  outs(margin);
904
  outs(jmp);
905
  outs(spx);
2 7u83 906
  outs(local_prefix);
6 7u83 907
  outn((long)ptno(jr));
908
  outnl();
909
  last_jump_label = ptno(jr);
2 7u83 910
  return;
911
}
912
 
913
static char* xse = "<=0";	/* no corresponding jump instruction */
914
static char* xnse = ">0";
915
 
916
 
917
/* output code for a branch instruction
918
   determined by test_no. The test is
919
   signed if sg is true */
920
static char *out_branch
6 7u83 921
(int sg, int test_no, int shnm)
2 7u83 922
{
923
  if (shnm >= shrealhd && shnm <= doublehd) {
924
    switch (test_no) {
925
      case 1:
6 7u83 926
	return(jne);
2 7u83 927
 
928
      case 2:
6 7u83 929
	return(jne);
2 7u83 930
 
931
      case 3:
6 7u83 932
	return(jpe);
2 7u83 933
 
934
      case 4:
6 7u83 935
	return(jpe);
2 7u83 936
 
937
      case 5:
6 7u83 938
	return(jpe);
2 7u83 939
 
940
      case 6:
6 7u83 941
	return(jpo);
2 7u83 942
 
943
      case 7:
6 7u83 944
	return(jpo);
2 7u83 945
 
946
      case 8:
6 7u83 947
	return(jpo);
2 7u83 948
 
949
      case 9:
6 7u83 950
	return(je);
2 7u83 951
 
952
      case 10:
6 7u83 953
	return(je);
2 7u83 954
 
955
      case 11:
6 7u83 956
	return(jne);
2 7u83 957
 
958
      case 12:
6 7u83 959
	return(je);
2 7u83 960
 
961
      case 13:
6 7u83 962
	return(jne);
2 7u83 963
 
964
      case 14:
6 7u83 965
	return(je);
2 7u83 966
 
967
      default:
6 7u83 968
	failer(BAD_TESTNO);
2 7u83 969
    };
970
  };
971
 
972
  if (sg) {
973
    switch (test_no) {
974
      case 1:
6 7u83 975
	return(sg<0 ? xse : jle);
2 7u83 976
      case 2:
6 7u83 977
	return(sg<0 ? js : jl);
2 7u83 978
 
979
      case 3:
6 7u83 980
	return(sg<0 ? jns : jge);
2 7u83 981
 
982
      case 4:
6 7u83 983
	return(sg<0 ? xnse : jg);
2 7u83 984
 
985
      case 5:
6 7u83 986
	return(jne);
2 7u83 987
 
988
      case 6:
6 7u83 989
	return(je);
2 7u83 990
 
991
      default:
6 7u83 992
	failer(BAD_TESTNO);
2 7u83 993
    };
994
  }
995
  else {
996
    switch (test_no) {
997
      case 1:
6 7u83 998
	return(jbe);
2 7u83 999
 
1000
      case 2:
6 7u83 1001
	return(jb);
2 7u83 1002
 
1003
      case 3:
6 7u83 1004
	return(jae);
2 7u83 1005
 
1006
      case 4:
6 7u83 1007
	return(ja);
2 7u83 1008
 
1009
      case 5:
6 7u83 1010
	return(jne);
2 7u83 1011
 
1012
      case 6:
6 7u83 1013
	return(je);
2 7u83 1014
 
1015
      default:
6 7u83 1016
	failer(BAD_TESTNO);
2 7u83 1017
    };
1018
  };
6 7u83 1019
  return((char *)0);
2 7u83 1020
}
1021
 
1022
void simple_branch
6 7u83 1023
(char *j, int labno)
2 7u83 1024
{
6 7u83 1025
  outs(margin);
1026
  outs(j);
1027
  outs(spx);
2 7u83 1028
  outs(local_prefix);
6 7u83 1029
  outn((long)labno);
1030
  outnl();
2 7u83 1031
 
1032
}
1033
 
1034
 
1035
/* output conditional jump to jr. testno
1036
   specifies kind of test. sg is 1 if
1037
   signed arithmetic, 0 unsigned, -1 if
1038
   signed vs zero (ignoring overflow).
1039
   shnm name of shape */
1040
void branch
6 7u83 1041
(int test_no, exp jr, int sg, int shnm)
2 7u83 1042
{
6 7u83 1043
  int  fs_dest = (int)fstack_pos_of(jr);
2 7u83 1044
  int  good_fs = fstack_pos;
1045
  int  good_fpucon = fpucon;
1046
  if (fs_dest < first_fl_reg)
6 7u83 1047
    failer(FSTACK_UNSET);
1048
  if (fstack_pos > fs_dest || sonno(jr)!= stack_dec || fpucon != normal_fpucon
2 7u83 1049
	|| cmp_64hilab >= 0) {
1050
	/* floating point stack or call stack need attention */
6 7u83 1051
    int  nl = next_lab();
2 7u83 1052
    int inv_test_no = (flpt_always_comparable ||
6 7u83 1053
			(shnm < shrealhd || shnm > doublehd))
1054
				?(int)int_inverse_ntest[test_no]
1055
				:(int)real_inverse_ntest[test_no];
2 7u83 1056
 
6 7u83 1057
    char* cj = out_branch((cmp_64hilab >= 0 ? 0 : sg), inv_test_no, shnm);
2 7u83 1058
    if (*cj == 'j') {
6 7u83 1059
      simple_branch(cj, nl);
2 7u83 1060
    }
1061
    else	/* compare with zero, ignoring overflow */
1062
    if (*cj == '>') {
6 7u83 1063
      int nl1 = next_lab();
1064
      simple_branch(js, nl1);
1065
      simple_branch(jne, nl);
1066
      simplest_set_lab(nl1);
2 7u83 1067
    }
1068
    else {
6 7u83 1069
      simple_branch(js, nl);
1070
      simple_branch(je, nl);
2 7u83 1071
    }
1072
 
1073
    if (cmp_64hilab >= 0) {
6 7u83 1074
      int nl2 = ptno(jr);
2 7u83 1075
      if (shnm != s64hd)
6 7u83 1076
	failer("uncompleted 64-bit comparison");
1077
      if (fstack_pos > fs_dest || sonno(jr)!= stack_dec || fpucon != normal_fpucon) {
1078
	nl2 = next_lab();
1079
	simplest_set_lab(nl2);
2 7u83 1080
      }
6 7u83 1081
      jump(jr, 0);
1082
      simplest_set_lab(cmp_64hilab);
1083
      simple_branch(out_branch(1, test_no, shnm), nl2);
2 7u83 1084
      cmp_64hilab = -1;
1085
    }
1086
    else
6 7u83 1087
      jump(jr, 0);
2 7u83 1088
 
1089
    fstack_pos = good_fs;
1090
    fpucon = good_fpucon;
6 7u83 1091
    simplest_set_lab(nl);
2 7u83 1092
    return;
1093
  };
1094
 
1095
  {
6 7u83 1096
    char* cj = out_branch(sg, test_no, shnm);
2 7u83 1097
    if (*cj == 'j') {
6 7u83 1098
      simple_branch(cj, ptno(jr));
2 7u83 1099
    }
1100
    else	/* compare with zero, ignoring overflow */
1101
    if (*cj == '>') {
6 7u83 1102
      int nl1 = next_lab();
1103
      simple_branch(js, nl1);
1104
      simple_branch(jne, ptno(jr));
1105
      simplest_set_lab(nl1);
2 7u83 1106
    }
1107
    else {
6 7u83 1108
      simple_branch(js, ptno(jr));
1109
      simple_branch(je, ptno(jr));
2 7u83 1110
    }
1111
  }
1112
  return;
1113
}
1114
 
1115
void setcc
6 7u83 1116
(int test_no, int sg, int shnm)
2 7u83 1117
{
1118
  char * b;
1119
  if (cmp_64hilab >= 0) {
1120
    int chl = cmp_64hilab;
6 7u83 1121
    int nl = next_lab();
2 7u83 1122
    if (shnm != s64hd)
6 7u83 1123
      failer("uncompleted 64-bit comparison");
2 7u83 1124
    cmp_64hilab = -1;
6 7u83 1125
    setcc(test_no, 0, ulonghd);
1126
    simple_branch(jmp, nl);
1127
    simplest_set_lab(chl);
1128
    setcc(test_no, sg, slonghd);
1129
    simplest_set_lab(nl);
2 7u83 1130
  }
1131
 
6 7u83 1132
  b = out_branch(sg, test_no, shnm);
2 7u83 1133
  if (*b != 'j')
1134
    failer(NO_SETCC);
1135
  outs(margin);
1136
  outs("set");
1137
  outs(&b[1]);
1138
  outs(spx);
1139
  outs(reg_name_byte[0]);
1140
  outnl();
1141
  return;
1142
}
1143
 
1144
/* output conditional jump to jr if overflow
1145
   sg is 1 if signed arithmetic, 0 unsigned */
1146
void jmp_overflow
6 7u83 1147
(exp jr, int sg, int inv)
2 7u83 1148
{
6 7u83 1149
  int  fs_dest = (int)fstack_pos_of(jr);
2 7u83 1150
  int  good_fs = fstack_pos;
1151
  int  good_fpucon = fpucon;
1152
  if (fs_dest < first_fl_reg)
6 7u83 1153
    failer(FSTACK_UNSET);
1154
  if (fstack_pos > fs_dest || sonno(jr)!= stack_dec || fpucon != normal_fpucon) {
2 7u83 1155
	/* floating point stack or call stack need attention */
6 7u83 1156
    int  nl = next_lab();
2 7u83 1157
    if (sg)
1158
      simple_branch(jno, nl);
1159
    else
1160
      simple_branch((inv ? jb : jae), nl);
6 7u83 1161
    jump(jr, 0);
2 7u83 1162
    fstack_pos = good_fs;
1163
    fpucon = good_fpucon;
6 7u83 1164
    simplest_set_lab(nl);
2 7u83 1165
    return;
1166
  };
1167
  if (sg)
1168
    simple_branch(jo, ptno(jr));
1169
  else
1170
    simple_branch((inv ? jae : jb), ptno(jr));
1171
  return;
1172
}
1173
 
1174
 
1175
/* software interrupt */
1176
void trap_ins
6 7u83 1177
(int s)
2 7u83 1178
{
1179
#ifndef AVOID_INTOV
1180
  if (s == f_overflow) {
1181
    ins0 ("int $4");	/* numeric interrupt */
1182
    return;
1183
  }
1184
#else
1185
#if (AVOID_INTOV == 16)
1186
  if (s == f_overflow) {
1187
    ins0 ("int $16");	/* mimic floating point interrupt */
1188
    return;
1189
  }
1190
#endif
1191
#endif
1192
  if (cont_err_handler == nilexp) {
6 7u83 1193
    cont_err_handler = make_extn("__trans386_errhandler", f_proc, 1);
2 7u83 1194
    if (!PIC_code)
6 7u83 1195
      cont_err_handler = getexp(f_proc, nilexp, 1, cont_err_handler, nilexp, 0, 0, cont_tag);
2 7u83 1196
  }
6 7u83 1197
  ins1(pushl, 32, mw(zeroe, s));
2 7u83 1198
#ifdef NEWDWARF
1199
  if (diagnose && dwarf2 && no_frame)
1200
    dw2_track_push();
1201
#endif
6 7u83 1202
  ins2(movl, 32, 32, mw(cont_err_handler, 0), reg0);
2 7u83 1203
  if (PIC_code)
6 7u83 1204
    ins1ind(call, 32, ind_reg0);
2 7u83 1205
  else
6 7u83 1206
    ins1ind(call, 32, reg0);
2 7u83 1207
  return;
1208
}
1209
 
1210
 
1211
/* output software interrupt if overflow
1212
   sg is 1 if signed arithmetic, 0 unsigned */
1213
void trap_overflow
6 7u83 1214
(int sg, int inv)
2 7u83 1215
{
1216
#ifdef AVOID_INTOV
6 7u83 1217
    int nl = next_lab();
2 7u83 1218
    if (sg)
1219
      simple_branch(jno, nl);
1220
    else
1221
      simple_branch((inv ? jb : jae), nl);
1222
    trap_ins(f_overflow);
6 7u83 1223
    simplest_set_lab(nl);
2 7u83 1224
#else
1225
  if (sg)
1226
    ins0(into);
1227
  else {
6 7u83 1228
    int nl = next_lab();
2 7u83 1229
    simple_branch((inv ? jb : jae), nl);
1230
    trap_ins(f_overflow);
6 7u83 1231
    simplest_set_lab(nl);
2 7u83 1232
  }
1233
#endif
1234
  return;
1235
}
1236
 
1237
 
1238
/* conditional software interrupt
1239
   sg is 1 if signed arithmetic
1240
   shnm name of shape */
1241
void test_trap
6 7u83 1242
(int test_no, int sg, int shnm)
2 7u83 1243
{
6 7u83 1244
  int nl = next_lab();
2 7u83 1245
  int inv_test_no = (flpt_always_comparable ||
6 7u83 1246
			(shnm < shrealhd || shnm > doublehd))
1247
				?(int)int_inverse_ntest[test_no]
1248
				:(int)real_inverse_ntest[test_no];
1249
  simple_branch(out_branch(sg, inv_test_no, shnm), nl);
2 7u83 1250
  trap_ins(f_overflow);
6 7u83 1251
  simplest_set_lab(nl);
2 7u83 1252
  return;
1253
}
1254
 
1255
 
1256
 
1257
/* special output for doing multiply by
1258
   using index instructions */
1259
void mult_op
6 7u83 1260
(int inc, where rmain, where rind, int sc, where dest)
2 7u83 1261
{
6 7u83 1262
  outs(margin);
1263
  outs("leal");
1264
  outs(spx);
2 7u83 1265
  if (inc != 0)
6 7u83 1266
    outn((long)inc);
1267
  outs("(");
1268
  if (name(rmain.where_exp)!= val_tag ||
1269
     (no(rmain.where_exp) + rmain.where_off)!= 0)
1270
    operand(32, rmain, 1, 0);
1271
  outs(",");
1272
  operand(32, rind, 1, 0);
2 7u83 1273
  if (sc != 1) {
6 7u83 1274
    outs(",");
1275
    outn((long)sc);
2 7u83 1276
  };
6 7u83 1277
  outs("),");
2 7u83 1278
 
6 7u83 1279
  if (inmem(dest)) {
1280
    operand(32, reg0, 1, 0);
1281
    outnl();
1282
    invalidate_dest(reg0);
1283
    end_contop();
1284
    move(slongsh, reg0, dest);
2 7u83 1285
  }
1286
  else {
6 7u83 1287
    operand(32, dest, 1, 0);
1288
    outnl();
1289
    end_contop();
2 7u83 1290
  };
1291
  return;
1292
}
1293
 
1294
/* output the case switch jump and the jump table */
1295
void caseins
6 7u83 1296
(int sz, exp arg, int min, int max, int *v, int exhaustive, int in_eax, exp case_exp)
2 7u83 1297
{
1298
  int tab;
1299
  int absent;
1300
  where a;
1301
  int need_label_flag=0;
1302
  exp next= short_next_jump(case_exp);
6 7u83 1303
  if (next != nilexp && name(next) ==goto_tag)
2 7u83 1304
  {
1305
    exp lab=final_dest(pt(next));
1306
    absent=ptno(pt(son(lab)));
1307
  }
1308
  else
1309
  {
6 7u83 1310
    absent = (exhaustive)? -1 : next_lab();
2 7u83 1311
    need_label_flag=1;
1312
  }
1313
 
6 7u83 1314
  tab = next_lab();
1315
  a = mw(arg, 0);
2 7u83 1316
 
6 7u83 1317
  if (inmem(mw(arg, 0)) || sz != 32) {
2 7u83 1318
    if (!in_eax)
6 7u83 1319
      change_var(slongsh, a, reg0);
2 7u83 1320
    a = reg0;
1321
  }
1322
 
1323
  /* the switch jump */
1324
  out_switch_jump(tab, a, min);
1325
 
1326
  /* table of offsets */
1327
  out_switch_table(tab, min, max, v, absent);
1328
 
1329
  if (!exhaustive && need_label_flag==1) {
1330
    /*  label for default of switch; continue here */
1331
    outs(local_prefix);
6 7u83 1332
    outn((long)absent);
1333
    outs(":");
1334
    outnl();
2 7u83 1335
#ifdef NEWDWARF
6 7u83 1336
    START_BB();
2 7u83 1337
#endif
1338
  };
1339
  return;
1340
}
1341
 
1342
 
1343
void const_intnl
6 7u83 1344
(int addr, int lab, int off)
2 7u83 1345
{
1346
  if (PIC_code)
1347
   {
1348
    outs(local_prefix);
6 7u83 1349
    outn((long)lab);
2 7u83 1350
    outs("@GOTOFF");
1351
    if (off != 0) {
6 7u83 1352
      outs("+");
1353
      outn((long)off / 8);
2 7u83 1354
    };
1355
    outs("(%ebx)");
1356
    return;
1357
   }
1358
  else
1359
   {
1360
    if (addr)
6 7u83 1361
      outs("$");
2 7u83 1362
    outs(local_prefix);
6 7u83 1363
    outn((long)lab);
2 7u83 1364
    if (off != 0) {
6 7u83 1365
      outs("+");
1366
      outn((long)off / 8);
2 7u83 1367
    };
1368
    return;
1369
  };
1370
}
1371
 
1372
void load_stack0
6 7u83 1373
(void)
2 7u83 1374
{
6 7u83 1375
  outs(" fld %st(0)");
1376
  outnl();
2 7u83 1377
  return;
1378
}
1379
 
1380
void outbp
6 7u83 1381
(void)
2 7u83 1382
{
1383
  outs("%ebp");
1384
}
1385
 
1386
void set_stack_from_bp
6 7u83 1387
(void)
2 7u83 1388
{
6 7u83 1389
  outs(margin);
1390
  outs(leal);
1391
  outs(spx);
2 7u83 1392
  outn((long)stack_dec/8);
1393
  outs("-");
1394
  outs(local_prefix);
1395
  outs("disp");
1396
  outn((long)crt_proc_id);
6 7u83 1397
  outs("(%ebp)");
1398
  outs(sep);
2 7u83 1399
  outs("%esp");
6 7u83 1400
  outnl();
2 7u83 1401
  return;
1402
}
1403
 
1404
void testah
6 7u83 1405
(int mask)
2 7u83 1406
{
1407
  outs(" testb $");
1408
  outn((long)mask);
1409
  outs(",%ah");
1410
  outnl();
1411
  return;
1412
}
1413
 
1414
exp make_extn
6 7u83 1415
(char * n, shape s, int v)
2 7u83 1416
{
6 7u83 1417
  dec * g = (dec *)(xmalloc(sizeof(dec)));
1418
  exp id = getexp(s, nilexp, 1, nilexp, nilexp, 0, 0, ident_tag);
1419
  exp nme = getexp(s, nilexp, 1, id, nilexp, 0, 0, name_tag);
1420
  setglob(id);
2 7u83 1421
  if (v) {
1422
#if keep_PIC_vars
1423
        setvar(id);
1424
#else
1425
        if (PIC_code)
1426
          sh(id) = f_pointer(f_alignment(s));
1427
        else
1428
          setvar(id);
1429
#endif
1430
  }
1431
  brog(id) = g;
1432
  if (prefix_length != 0) {
6 7u83 1433
    int nl = (int)strlen(n);
2 7u83 1434
    int j;
6 7u83 1435
    char * newn = (char *)xcalloc((nl + prefix_length + 1), sizeof(char));
2 7u83 1436
    for (j = 0; j < prefix_length; ++j)
1437
      newn[j] = name_prefix[j];
1438
    for (j = 0; j < nl; ++j)
1439
      newn[j+prefix_length] = n[j];
1440
    newn[nl+prefix_length] = 0;
1441
    n = newn;
1442
  }
1443
  g -> dec_u.dec_val.dec_exp = id;
1444
  g -> dec_u.dec_val.dec_id = n;
1445
  g -> dec_u.dec_val.extnamed = 1;
6 7u83 1446
  return(nme);
2 7u83 1447
}
1448
 
1449
 
1450
 
1451
/* shift or rotate 64 bits in reg0/reg1 */
1452
void rotshift64
6 7u83 1453
(int shft, int sig, where wshift)
2 7u83 1454
{
1455
  if (name(wshift.where_exp) == val_tag) {	/* no of places is constant */
6 7u83 1456
    int places = no(wshift.where_exp) + wshift.where_off;
2 7u83 1457
    if (places >= 32) {
1458
      places -= 32;
1459
      switch (shft) {
1460
	case 0:
1461
	  if (places)
6 7u83 1462
	    ins2(shll, 8, 32, mw(zeroe,places), reg0);
1463
	  move(ulongsh, reg0, reg1);
1464
	  move(ulongsh, zero, reg0);
2 7u83 1465
	  return;
1466
	case 1:
6 7u83 1467
	  move(ulongsh, reg1, reg0);
2 7u83 1468
	  if (places)
6 7u83 1469
	    ins2((sig ? sarl : shrl), 8, 32, mw(zeroe,places), reg0);
2 7u83 1470
	  if (sig)
6 7u83 1471
	    ins2(sarl, 8, 32, mw(zeroe,31), reg1);
2 7u83 1472
	  else
6 7u83 1473
	    move(ulongsh, zero, reg1);
2 7u83 1474
	  return;
1475
	default: {
1476
	  if (!places) {
6 7u83 1477
	    ins2(xchg, 32, 32, reg0, reg1);
2 7u83 1478
	    return;
1479
	  }
1480
	  places = 32 - places;
1481
	  shft = 5 - shft;	/* reverse rotate */
1482
	}
1483
      }
1484
    };
1485
    if (places == 0)
1486
      return;
1487
    switch (shft) {	/* between 1 and 31 places */
1488
      case 0:
6 7u83 1489
	ins3(shldl, 8, 32, 32, mw(zeroe,places), reg0, reg1);
1490
	ins2(shll, 8, 32, mw(zeroe,places), reg0);
2 7u83 1491
	return;
1492
      case 1:
6 7u83 1493
	ins3(shrdl, 8, 32, 32, mw(zeroe,places), reg1, reg0);
1494
	ins2((sig ? sarl : shrl), 8, 32, mw(zeroe,places), reg1);
2 7u83 1495
	return;
1496
      default: {
1497
	char * dsh = (shft == 2 ? shrdl : shldl);
1498
        extra_stack += 64;
1499
	check_stack_max;
6 7u83 1500
	ins0(pushedx);
2 7u83 1501
#ifdef NEWDWARF
1502
	if (diagnose && dwarf2 && no_frame)
1503
	  dw2_track_push();
1504
#endif
6 7u83 1505
	ins0(pusheax);
2 7u83 1506
#ifdef NEWDWARF
1507
	if (diagnose && dwarf2 && no_frame)
1508
	  dw2_track_push();
1509
#endif
6 7u83 1510
	ins3(dsh, 8, 32, 32, mw(zeroe,places),
2 7u83 1511
		reg1, mw(ind_sp.where_exp,-32));
6 7u83 1512
	ins3(dsh, 8, 32, 32, mw(zeroe,places),
2 7u83 1513
		reg0, mw(ind_sp.where_exp,-64));
6 7u83 1514
	ins0(popeax);
2 7u83 1515
#ifdef NEWDWARF
1516
	if (diagnose && dwarf2 && no_frame)
1517
	  dw2_track_pop();
1518
#endif
6 7u83 1519
	ins0(popedx);
2 7u83 1520
#ifdef NEWDWARF
1521
	if (diagnose && dwarf2 && no_frame)
1522
	  dw2_track_pop();
1523
#endif
6 7u83 1524
	invalidate_dest(ind_sp);
2 7u83 1525
        extra_stack -= 64;
1526
	return;
1527
      }
1528
    }
1529
  };
1530
  {				/* number of places in reg2 */
6 7u83 1531
    int lablow = next_lab();
1532
    int labend = next_lab();
1533
    ins2(cmpl, 32, 32, mw(zeroe,32), reg2);
1534
    simple_branch(jl, lablow);
2 7u83 1535
    switch (shft) {
1536
      case 0:
6 7u83 1537
	ins2(subl, 32, 32, mw(zeroe,32), reg2);
1538
	ins2(shll, 8, 32, reg2, reg0);
1539
	move(ulongsh, reg0, reg1);
1540
	move(ulongsh, zero, reg0);
2 7u83 1541
	break;
1542
      case 1:
6 7u83 1543
	ins2(subl, 32, 32, mw(zeroe,32), reg2);
1544
	move(ulongsh, reg1, reg0);
1545
	ins2((sig ? sarl : shrl), 8, 32, reg2, reg0);
2 7u83 1546
	if (sig)
6 7u83 1547
	  ins2(sarl, 8, 32, mw(zeroe,31), reg1);
2 7u83 1548
	else
6 7u83 1549
	  move(ulongsh, zero, reg1);
2 7u83 1550
	break;
1551
      default: {
6 7u83 1552
	int labx = next_lab();
2 7u83 1553
	char * dsh = (shft == 2 ? shldl : shrdl);	/* reversed rotate */
6 7u83 1554
	simple_branch(je, labx);
1555
	ins2(subl, 32, 32, mw(zeroe,64), reg2);
1556
	ins1(negl, 32, reg2);
2 7u83 1557
        extra_stack += 64;
1558
	check_stack_max;
6 7u83 1559
	ins0(pushedx);
2 7u83 1560
#ifdef NEWDWARF
1561
	if (diagnose && dwarf2 && no_frame)
1562
	  dw2_track_push();
1563
#endif
6 7u83 1564
	ins0(pusheax);
2 7u83 1565
#ifdef NEWDWARF
1566
	if (diagnose && dwarf2 && no_frame)
1567
	  dw2_track_push();
1568
#endif
6 7u83 1569
	ins3(dsh, 8, 32, 32, reg2, reg1, mw(ind_sp.where_exp,-32));
1570
	ins3(dsh, 8, 32, 32, reg2, reg0, mw(ind_sp.where_exp,-64));
1571
	ins0(popeax);
2 7u83 1572
#ifdef NEWDWARF
1573
	if (diagnose && dwarf2 && no_frame)
1574
	  dw2_track_pop();
1575
#endif
6 7u83 1576
	ins0(popedx);
2 7u83 1577
#ifdef NEWDWARF
1578
	if (diagnose && dwarf2 && no_frame)
1579
	  dw2_track_pop();
1580
#endif
6 7u83 1581
	invalidate_dest(ind_sp);
2 7u83 1582
        extra_stack -= 64;
6 7u83 1583
	simple_branch(jmp, labend);
1584
	simplest_set_lab(labx);
1585
	ins2(xchg, 32, 32, reg0, reg1);
2 7u83 1586
      }
1587
    }
6 7u83 1588
    simple_branch(jmp, labend);
1589
    simplest_set_lab(lablow);
2 7u83 1590
    switch (shft) {	/* between 0 and 31 places */
1591
      case 0:
6 7u83 1592
	ins3(shldl, 8, 32, 32, reg2, reg0, reg1);
1593
	ins2(shll, 8, 32, reg2, reg0);
2 7u83 1594
	break;
1595
      case 1:
6 7u83 1596
	ins3(shrdl, 8, 32, 32, reg2, reg1, reg0);
1597
	ins2((sig ? sarl : shrl), 8, 32, reg2, reg1);
2 7u83 1598
	break;
1599
      default: {
1600
	char * dsh = (shft == 2 ? shrdl : shldl);
1601
        extra_stack += 64;
1602
	check_stack_max;
6 7u83 1603
	ins0(pushedx);
2 7u83 1604
#ifdef NEWDWARF
1605
	if (diagnose && dwarf2 && no_frame)
1606
	  dw2_track_push();
1607
#endif
6 7u83 1608
	ins0(pusheax);
2 7u83 1609
#ifdef NEWDWARF
1610
	if (diagnose && dwarf2 && no_frame)
1611
	  dw2_track_push();
1612
#endif
6 7u83 1613
	ins3(dsh, 8, 32, 32, reg2, reg1, mw(ind_sp.where_exp,-32));
1614
	ins3(dsh, 8, 32, 32, reg2, reg0, mw(ind_sp.where_exp,-64));
1615
	ins0(popeax);
2 7u83 1616
#ifdef NEWDWARF
1617
	if (diagnose && dwarf2 && no_frame)
1618
	  dw2_track_pop();
1619
#endif
6 7u83 1620
	ins0(popedx);
2 7u83 1621
#ifdef NEWDWARF
1622
	if (diagnose && dwarf2 && no_frame)
1623
	  dw2_track_pop();
1624
#endif
6 7u83 1625
	invalidate_dest(ind_sp);
2 7u83 1626
        extra_stack -= 64;
1627
      }
1628
    }
6 7u83 1629
    simplest_set_lab(labend);
2 7u83 1630
  };
1631
  return;
1632
}