/
code.h
1093 lines (950 loc) · 33.3 KB
/
code.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (C) 1985-1996 by Symantec
// Copyright (C) 2000-2011 by Digital Mars
// All Rights Reserved
// http://www.digitalmars.com
// Written by Walter Bright
/*
* This source file is made available for personal use
* only. The license is in /dmd/src/dmd/backendlicense.txt
* or /dm/src/dmd/backendlicense.txt
* For any other uses, please contact Digital Mars.
*/
#if __cplusplus && TX86
extern "C" {
#endif
#if MARS
struct LabelDsymbol;
struct Declaration;
#endif
#define CNIL ((code *) NULL)
/* Register definitions */
#define AX 0
#define CX 1
#define DX 2
#define BX 3
#define SP 4
#define BP 5
#define SI 6
#define DI 7
enum // #defining R12-R15 interfere with setjmps' _JUMP_BUFFER members
{
R8 = 8,
R9 = 9,
R10 = 10,
R11 = 11,
R12 = 12,
R13 = 13,
R14 = 14,
R15 = 15,
};
#define XMM0 16
#define XMM1 17
#define XMM2 18
#define XMM3 19
#define XMM4 20
#define XMM5 21
#define XMM6 22
#define XMM7 23
/* There are also XMM8..XMM14 */
#define XMM15 31
#define ES 24
#define PSW 25
#define STACK 26 // top of stack
#define ST0 27 // 8087 top of stack register
#define ST01 28 // top two 8087 registers; for complex types
#define NOREG 29 // no register
#define AL 0
#define CL 1
#define DL 2
#define BL 3
#define AH 4
#define CH 5
#define DH 6
#define BH 7
#define mAX 1
#define mCX 2
#define mDX 4
#define mBX 8
#define mSP 0x10
#define mBP 0x20
#define mSI 0x40
#define mDI 0x80
#define mR8 (1 << R8)
#define mR9 (1 << R9)
#define mR10 (1 << R10)
#define mR11 (1 << R11)
#define mR12 (1 << R12)
#define mR13 (1 << R13)
#define mR14 (1 << R14)
#define mR15 (1 << R15)
#define mXMM0 (1 << XMM0)
#define mXMM1 (1 << XMM1)
#define mXMM2 (1 << XMM2)
#define mXMM3 (1 << XMM3)
#define mXMM4 (1 << XMM4)
#define mXMM5 (1 << XMM5)
#define mXMM6 (1 << XMM6)
#define mXMM7 (1 << XMM7)
#define XMMREGS (mXMM0 |mXMM1 |mXMM2 |mXMM3 |mXMM4 |mXMM5 |mXMM6 |mXMM7)
#define mES (1 << ES) // 0x1000000
#define mPSW (1 << PSW) // 0x2000000
#define mSTACK (1 << STACK) // 0x4000000
#define mST0 (1 << ST0) // 0x20000000
#define mST01 (1 << ST01) // 0x40000000
// Flags for getlvalue (must fit in regm_t)
#define RMload (1 << 30)
#define RMstore (1 << 31)
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
// To support positional independent code,
// must be able to remove BX from available registers
extern regm_t ALLREGS;
#define ALLREGS_INIT (mAX|mBX|mCX|mDX|mSI|mDI)
#define ALLREGS_INIT_PIC (mAX|mCX|mDX|mSI|mDI)
extern regm_t BYTEREGS;
#define BYTEREGS_INIT (mAX|mBX|mCX|mDX)
#define BYTEREGS_INIT_PIC (mAX|mCX|mDX)
#else
#define ALLREGS (mAX|mBX|mCX|mDX|mSI|mDI)
#define ALLREGS_INIT ALLREGS
#undef BYTEREGS
#define BYTEREGS (mAX|mBX|mCX|mDX)
#endif
/* We use the same IDXREGS for the 386 as the 8088, because if
we used ALLREGS, it would interfere with mMSW
*/
#define IDXREGS (mBX|mSI|mDI)
#define FLOATREGS_64 mAX
#define FLOATREGS2_64 mDX
#define DOUBLEREGS_64 mAX
#define DOUBLEREGS2_64 mDX
#define FLOATREGS_32 mAX
#define FLOATREGS2_32 mDX
#define DOUBLEREGS_32 (mAX|mDX)
#define DOUBLEREGS2_32 (mCX|mBX)
#define FLOATREGS_16 (mDX|mAX)
#define FLOATREGS2_16 (mCX|mBX)
#define DOUBLEREGS_16 (mAX|mBX|mCX|mDX)
/*#define _8087REGS (mST0|mST1|mST2|mST3|mST4|mST5|mST6|mST7)*/
/* Segment registers */
#define SEG_ES 0
#define SEG_CS 1
#define SEG_SS 2
#define SEG_DS 3
/*********************
* Masks for register pairs.
* Note that index registers are always LSWs. This is for the convenience
* of implementing far pointers.
*/
#if 0
// Give us an extra one so we can enregister a long
#define mMSW (mCX|mDX|mDI|mES) // most significant regs
#define mLSW (mAX|mBX|mSI) // least significant regs
#else
#define mMSW (mCX|mDX|mES) /* most significant regs */
#define mLSW (mAX|mBX|mSI|mDI) /* least significant regs */
#endif
/* Return !=0 if there is a SIB byte */
#define issib(rm) (((rm) & 7) == 4 && ((rm) & 0xC0) != 0xC0)
#if 0
// relocation field size is always 32bits
#define is32bitaddr(x,Iflags) (1)
#else
//
// is32bitaddr works correctly only when x is 0 or 1. This is
// true today for the current definition of I32, but if the definition
// of I32 changes, this macro will need to change as well
//
// Note: even for linux targets, CFaddrsize can be set by the inline
// assembler.
#define is32bitaddr(x,Iflags) (I64 || ((x) ^(((Iflags) & CFaddrsize) !=0)))
#endif
/*******************
* Some instructions.
*/
#define SEGES 0x26
#define SEGCS 0x2E
#define SEGSS 0x36
#define SEGDS 0x3E
#define SEGFS 0x64
#define SEGGS 0x65
#define CALL 0xE8
#define JMP 0xE9 /* Intra-Segment Direct */
#define JMPS 0xEB /* JMP SHORT */
#define JCXZ 0xE3
#define LOOP 0xE2
#define LES 0xC4
#define LEA 0x8D
#define JO 0x70
#define JNO 0x71
#define JC 0x72
#define JB 0x72
#define JNC 0x73
#define JAE 0x73
#define JE 0x74
#define JNE 0x75
#define JBE 0x76
#define JA 0x77
#define JS 0x78
#define JNS 0x79
#define JP 0x7A
#define JNP 0x7B
#define JL 0x7C
#define JGE 0x7D
#define JLE 0x7E
#define JG 0x7F
/* NOP is used as a placeholder in the linked list of instructions, no */
/* actual code will be generated for it. */
#define NOP 0x2E /* actually CS: (we don't use 0x90 because the */
/* silly Windows stuff wants to output 0x90's) */
#define ESCAPE 0x3E // marker that special information is here
// (Iop2 is the type of special information)
// (Same as DS:, but we will never generate
// a separate DS: opcode anyway)
#define ESClinnum (1 << 8) // line number information
#define ESCctor (2 << 8) // object is constructed
#define ESCdtor (3 << 8) // object is destructed
#define ESCmark (4 << 8) // mark eh stack
#define ESCrelease (5 << 8) // release eh stack
#define ESCoffset (6 << 8) // set code offset for eh
#define ESCadjesp (7 << 8) // adjust ESP by IEV2.Vint
#define ESCmark2 (8 << 8) // mark eh stack
#define ESCrelease2 (9 << 8) // release eh stack
#define ESCframeptr (10 << 8) // replace with load of frame pointer
#define ESCdctor (11 << 8) // D object is constructed
#define ESCddtor (12 << 8) // D object is destructed
#define ESCadjfpu (13 << 8) // adjust fpustackused by IEV2.Vint
#define ASM 0x36 // string of asm bytes, actually an SS: opcode
/*********************************
* Macros to ease generating code
* modregrm: generate mod reg r/m field
* modregxrm: reg could be R8..R15
* modregrmx: rm could be R8..R15
* modregxrmx: reg or rm could be R8..R15
* NEWREG: change reg field of x to r
* genorreg: OR t,f
*/
#define modregrm(m,r,rm) (((m)<<6)|((r)<<3)|(rm))
#define modregxrm(m,r,rm) ((((r)&8)<<15)|modregrm((m),(r)&7,rm))
#define modregrmx(m,r,rm) ((((rm)&8)<<13)|modregrm((m),r,(rm)&7))
#define modregxrmx(m,r,rm) ((((r)&8)<<15)|(((rm)&8)<<13)|modregrm((m),(r)&7,(rm)&7))
#define NEWREXR(x,r) ((x)=((x)&~REX_R)|(((r)&8)>>1))
#define NEWREG(x,r) ((x)=((x)&~(7<<3))|((r)<<3))
#define code_newreg(c,r) (NEWREG((c)->Irm,(r)&7),NEWREXR((c)->Irex,(r)))
#define genorreg(c,t,f) genregs((c),0x09,(f),(t))
#define REX 0x40 // REX prefix byte, OR'd with the following bits:
#define REX_W 8 // 0 = default operand size, 1 = 64 bit operand size
#define REX_R 4 // high bit of reg field of modregrm
#define REX_X 2 // high bit of sib index reg
#define REX_B 1 // high bit of rm field, sib base reg, or opcode reg
#define VEX2_B1(ivex) \
( \
ivex.r << 7 | \
ivex.vvvv << 3 | \
ivex.l << 2 | \
ivex.pp \
)
#define VEX3_B1(ivex) \
( \
ivex.r << 7 | \
ivex.x << 6 | \
ivex.b << 5 | \
ivex.mmmm \
)
#define VEX3_B2(ivex) \
( \
ivex.w << 7 | \
ivex.vvvv << 3 | \
ivex.l << 2 | \
ivex.pp \
)
/**********************
* C library routines.
* See callclib().
*/
enum CLIB
{
CLIBlcmp,
CLIBlmul,
CLIBldiv,
CLIBlmod,
CLIBuldiv,
CLIBulmod,
#if TARGET_WINDOS
CLIBdmul,CLIBddiv,CLIBdtst0,CLIBdtst0exc,CLIBdcmp,CLIBdcmpexc,CLIBdneg,CLIBdadd,CLIBdsub,
CLIBfmul,CLIBfdiv,CLIBftst0,CLIBftst0exc,CLIBfcmp,CLIBfcmpexc,CLIBfneg,CLIBfadd,CLIBfsub,
#endif
CLIBdbllng,CLIBlngdbl,CLIBdblint,CLIBintdbl,
CLIBdbluns,CLIBunsdbl,
CLIBdblulng,
#if TARGET_WINDOS
// used the GNU way of converting unsigned long long to signed
CLIBulngdbl,
#endif
CLIBdblflt,CLIBfltdbl,
CLIBdblllng,
CLIBllngdbl,
CLIBdblullng,
CLIBullngdbl,
CLIBdtst,
CLIBvptrfptr,CLIBcvptrfptr,
CLIB87topsw,CLIBfltto87,CLIBdblto87,CLIBdblint87,CLIBdbllng87,
CLIBftst,
CLIBfcompp,
CLIBftest,
CLIBftest0,
CLIBfdiv87,
// Complex numbers
CLIBcmul,
CLIBcdiv,
CLIBccmp,
CLIBu64_ldbl,
CLIBld_u64,
CLIBMAX
};
/**********************************
* Code data type
*/
union evc
{
targ_int Vint; // also used for tmp numbers (FLtmp)
targ_uns Vuns;
targ_long Vlong;
targ_llong Vllong;
targ_size_t Vsize_t;
struct
{ targ_size_t Vpointer;
int Vseg; // segment the pointer is in
}_EP;
Srcpos Vsrcpos; // source position for OPlinnum
struct elem *Vtor; // OPctor/OPdtor elem
struct block *Vswitch; // when FLswitch and we have a switch table
code *Vcode; // when code is target of a jump (FLcode)
struct block *Vblock; // when block " (FLblock)
struct
{
targ_size_t Voffset; // offset from symbol
symbol *Vsym; // pointer to symbol table (FLfunc,FLextern)
} sp;
#if MARS
struct
{
targ_size_t Voffset; // offset from symbol
Declaration *Vsym; // pointer to D symbol table
} dsp;
struct
{
targ_size_t Voffset; // offset from symbol
LabelDsymbol *Vsym; // pointer to Label
} lab;
#endif
struct
{ size_t len;
char *bytes;
} as; // asm node (FLasm)
};
struct code
{
code *next;
unsigned Iflags;
#define CFes 1 // generate an ES: segment override for this instr
#define CFjmp16 2 // need 16 bit jump offset (long branch)
#define CFtarg 4 // this code is the target of a jump
#define CFseg 8 // get segment of immediate value
#define CFoff 0x10 // get offset of immediate value
#define CFss 0x20 // generate an SS: segment override (not with
// CFes at the same time, though!)
#define CFpsw 0x40 // we need the flags result after this instruction
#define CFopsize 0x80 // prefix with operand size
#define CFaddrsize 0x100 // prefix with address size
#define CFds 0x200 // need DS override (not with es, ss, or cs )
#define CFcs 0x400 // need CS override
#define CFfs 0x800 // need FS override
#define CFgs (CFcs | CFfs) // need GS override
#define CFwait 0x1000 // If I32 it indicates when to output a WAIT
#define CFselfrel 0x2000 // if self-relative
#define CFunambig 0x4000 // indicates cannot be accessed by other addressing
// modes
#define CFtarg2 0x8000 // like CFtarg, but we can't optimize this away
#define CFvolatile 0x10000 // volatile reference, do not schedule
#define CFclassinit 0x20000 // class init code
#define CFoffset64 0x40000 // offset is 64 bits
#define CFpc32 0x80000 // I64: PC relative 32 bit fixup
#define CFvex 0x100000 // vex prefix
#define CFvex3 0x200000 // 3 byte vex prefix
#define CFPREFIX (CFSEG | CFopsize | CFaddrsize)
#define CFSEG (CFes | CFss | CFds | CFcs | CFfs | CFgs)
union {
unsigned _Iop;
struct {
#pragma pack(1)
unsigned char op;
unsigned short pp : 2;
unsigned short l : 1;
unsigned short vvvv : 4;
unsigned short w : 1;
unsigned short mmmm : 5;
unsigned short b : 1;
unsigned short x : 1;
unsigned short r : 1;
unsigned char pfx; // always 0xC4
#pragma pack()
} _Ivex;
} _OP;
/* The _EA is the "effective address" for the instruction, and consists of the modregrm byte,
* the sib byte, and the REX prefix byte. The 16 bit code generator just used the modregrm,
* the 32 bit x86 added the sib, and the 64 bit one added the rex.
*/
union
{ unsigned _Iea;
struct
{
unsigned char _Irm; // reg/mode
unsigned char _Isib; // SIB byte
unsigned char _Irex; // REX prefix
} _ea;
} _EA;
#define Iop _OP._Iop
#define Ivex _OP._Ivex
#define Iea _EA._Iea
#define Irm _EA._ea._Irm
#define Isib _EA._ea._Isib
#define Irex _EA._ea._Irex
/* IFL1 and IEV1 are the first operand, which usually winds up being the offset to the Effective
* Address. IFL1 is the tag saying which variant type is in IEV1. IFL2 and IEV2 is the second
* operand, usually for immediate instructions.
*/
unsigned char IFL1,IFL2; // FLavors of 1st, 2nd operands
union evc IEV1; // 1st operand, if any
#define IEVpointer1 IEV1._EP.Vpointer
#define IEVseg1 IEV1._EP.Vseg
#define IEVsym1 IEV1.sp.Vsym
#define IEVdsym1 IEV1.dsp.Vsym
#define IEVoffset1 IEV1.sp.Voffset
#define IEVlsym1 IEV1.lab.Vsym
#define IEVint1 IEV1.Vint
union evc IEV2; // 2nd operand, if any
#define IEVpointer2 IEV2._EP.Vpointer
#define IEVseg2 IEV2._EP.Vseg
#define IEVsym2 IEV2.sp.Vsym
#define IEVdsym2 IEV2.dsp.Vsym
#define IEVoffset2 IEV2.sp.Voffset
#define IEVlsym2 IEV2.lab.Vsym
#define IEVint2 IEV2.Vint
#define IEVllong2 IEV2.Vllong
void print(); // pretty-printer
code() { next = NULL; Iflags = 0; Iop = 0; Iea = 0; IFL1 = 0; IFL2 = 0; } // constructor
void orReg(unsigned reg)
{ if (reg & 8)
Irex |= REX_R;
Irm |= modregrm(0, reg & 7, 0);
}
void setReg(unsigned reg)
{
Irex &= ~REX_R;
Irm &= ~modregrm(0, 7, 0);
orReg(reg);
}
bool isJumpOP() { return Iop == JMP || Iop == JMPS; }
};
// !=0 if we have to add FWAIT to floating point ops
#define ADDFWAIT() (config.target_cpu <= TARGET_80286)
/********************** PUBLIC FUNCTIONS *******************/
code *code_calloc(void);
void code_free (code *);
void code_term(void);
#define code_next(c) ((c)->next)
//#define code_calloc() ((code *) mem_calloc(sizeof(code)))
typedef code *code_p;
/**********************************
* Set value in regimmed for reg.
* NOTE: For 16 bit generator, this is always a (targ_short) sign-extended
* value.
*/
#define regimmed_set(reg,e) \
(regcon.immed.value[reg] = (e),regcon.immed.mval |= 1 << (reg))
extern con_t regcon;
/****************************
* Table of common subexpressions stored on the stack.
* csextab[] array of info on saved CSEs
* CSEpe pointer to saved elem
* CSEregm mask of register that was saved (so for multi-
* register variables we know which part we have)
* cstop = # of entries in table
*/
struct CSE
{ elem *e; // pointer to elem
code csimple; // if CSEsimple, this is the code to regenerate it
regm_t regm; // mask of register stored there
char flags; // flag bytes
#define CSEload 1 // set if the CSE was ever loaded
#define CSEsimple 2 // CSE can be regenerated easilly
// != 0 if CSE was ever loaded
#define CSE_loaded(i) (csextab[i].flags & CSEload)
};
/************************************
*/
#if TX86
struct NDP
{
elem *e; // which elem is stored here (NULL if none)
unsigned offset; // offset from e (used for complex numbers)
static NDP *save;
static int savemax; // # of entries in save[]
static int savetop; // # of entries used in save[]
};
extern NDP _8087elems[8];
#endif
/************************************
* Register save state.
*/
extern "C++"
{
struct REGSAVE
{
targ_size_t off; // offset on stack
unsigned top; // high water mark
unsigned idx; // current number in use
int alignment; // 8 or 16
void reset() { off = 0; top = 0; idx = 0; alignment = REGSIZE; }
code *save(code *c, int reg, unsigned *pidx);
code *restore(code *c, int reg, unsigned idx);
};
}
extern REGSAVE regsave;
/*******************************
* As we generate code, collect information about
* what parts of NT exception handling we need.
*/
extern unsigned usednteh;
#define NTEH_try 1 // used _try statement
#define NTEH_except 2 // used _except statement
#define NTEHexcspec 4 // had C++ exception specification
#define NTEHcleanup 8 // destructors need to be called
#define NTEHtry 0x10 // had C++ try statement
#define NTEHcpp (NTEHexcspec | NTEHcleanup | NTEHtry)
#define EHcleanup 0x20
#define EHtry 0x40
#define NTEHjmonitor 0x80 // uses Jupiter monitor
#define NTEHpassthru 0x100
/********************** Code Generator State ***************/
typedef struct CGstate
{
int stackclean; // if != 0, then clean the stack after function call
} CGstate;
extern CGstate cgstate;
/***********************************************************/
extern regm_t msavereg,mfuncreg,allregs;
/*long cxmalloc,cxcalloc,cx1;*/
typedef code *cd_t (elem *e , regm_t *pretregs );
extern int BPRM;
extern regm_t FLOATREGS;
extern regm_t FLOATREGS2;
extern regm_t DOUBLEREGS;
extern const char datafl[],stackfl[],segfl[],flinsymtab[];
extern char needframe,usedalloca,gotref;
extern targ_size_t localsize,Toff,Poff,Aoff,
Poffset,funcoffset,
framehandleroffset,
Aoffset,Toffset,EEoffset;
extern int Aalign;
extern int cseg;
extern int STACKALIGN;
#if TARGET_OSX
extern targ_size_t localgotoffset;
#endif
/* cgcod.c */
extern int pass;
#define PASSinit 0 // initial pass through code generator
#define PASSreg 1 // register assignment pass
#define PASSfinal 2 // final pass
extern int dfoidx;
extern struct CSE *csextab;
extern unsigned cstop;
#if TX86
extern bool floatreg;
#endif
extern targ_size_t retoffset;
extern unsigned stackpush;
extern int stackchanged;
extern int refparam;
extern int reflocal;
extern char anyiasm;
extern char calledafunc;
extern code *(*cdxxx[])(elem *,regm_t *);
void stackoffsets(int);
void codgen (void );
#ifdef DEBUG
unsigned findreg (regm_t regm , int line , const char *file );
#define findreg(regm) findreg((regm),__LINE__,__FILE__)
#else
unsigned findreg (regm_t regm );
#endif
#define findregmsw(regm) findreg((regm) & mMSW)
#define findreglsw(regm) findreg((regm) & (mLSW | mBP))
void freenode (elem *e );
int isregvar (elem *e , regm_t *pregm , unsigned *preg );
#ifdef DEBUG
code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym , int line , const char *file );
#define allocreg(a,b,c) allocreg((a),(b),(c),__LINE__,__FILE__)
#else
code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym );
#endif
void useregs (regm_t regm );
code *getregs (regm_t r );
code *getregs_imm (regm_t r );
code *cse_flush(int);
bool cse_simple(code *c, elem *e);
code* gen_testcse(code *c, unsigned sz, targ_uns i);
code* gen_loadcse(code *c, unsigned reg, targ_uns i);
void cssave (elem *e , regm_t regm , unsigned opsflag );
bool evalinregister (elem *e );
regm_t getscratch();
code *codelem (elem *e , regm_t *pretregs , bool constflag );
code *scodelem (elem *e , regm_t *pretregs , regm_t keepmsk , bool constflag );
const char *regm_str(regm_t rm);
int numbitsset(regm_t);
/* cod1.c */
extern int clib_inited;
int isscaledindex(elem *);
int ssindex(int op,targ_uns product);
void buildEA(code *c,int base,int index,int scale,targ_size_t disp);
unsigned buildModregrm(int mod, int reg, int rm);
void andregcon (con_t *pregconsave);
void genEEcode();
code *docommas (elem **pe );
void gensaverestore(regm_t, code **, code **);
void gensaverestore2(regm_t regm,code **csave,code **crestore);
code *genstackclean(code *c,unsigned numpara,regm_t keepmsk);
code *logexp (elem *e , int jcond , unsigned fltarg , code *targ );
code *loadea (elem *e , code *cs , unsigned op , unsigned reg , targ_size_t offset , regm_t keepmsk , regm_t desmsk );
unsigned getaddrmode (regm_t idxregs );
void setaddrmode(code *c, regm_t idxregs);
void getlvalue_msw(code *);
void getlvalue_lsw(code *);
code *getlvalue (code *pcs , elem *e , regm_t keepmsk );
code *fltregs (code *pcs , tym_t tym );
code *tstresult (regm_t regm , tym_t tym , unsigned saveflag );
code *fixresult (elem *e , regm_t retregs , regm_t *pretregs );
code *callclib (elem *e , unsigned clib , regm_t *pretregs , regm_t keepmask );
cd_t cdfunc;
cd_t cdstrthis;
code *params(elem *, unsigned);
code *offsetinreg (elem *e , regm_t *pretregs );
code *loaddata (elem *e , regm_t *pretregs );
/* cod2.c */
int movOnly(elem *e);
regm_t idxregm(code *c);
#if TARGET_WINDOS
code *opdouble (elem *e , regm_t *pretregs , unsigned clib );
#endif
cd_t cdorth;
cd_t cdmul;
cd_t cdnot;
cd_t cdcom;
cd_t cdbswap;
cd_t cdcond;
void WRcodlst (code *c );
cd_t cdcomma;
cd_t cdloglog;
cd_t cdshift;
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
cd_t cdindpic;
#endif
cd_t cdind;
cd_t cdstrlen;
cd_t cdstrcmp;
cd_t cdstrcpy;
cd_t cdmemchr;
cd_t cdmemcmp;
cd_t cdmemcpy;
cd_t cdmemset;
cd_t cdstreq;
cd_t cdrelconst;
code *getoffset (elem *e , unsigned reg );
cd_t cdneg;
cd_t cdabs;
cd_t cdpost;
cd_t cderr;
cd_t cdinfo;
cd_t cddctor;
cd_t cdddtor;
cd_t cdctor;
cd_t cddtor;
cd_t cdmark;
cd_t cdnullcheck;
cd_t cdclassinit;
/* cod3.c */
extern int BPoff;
int cod3_EA(code *c);
regm_t cod3_useBP();
void cod3_initregs();
void cod3_setdefault();
void cod3_set32 (void );
void cod3_set64 (void );
void cod3_align_bytes (size_t nbytes);
void cod3_align (void );
code* cod3_stackadj(code* c, int nbytes);
regm_t regmask(tym_t tym, tym_t tyf);
void cgreg_dst_regs(unsigned *dst_integer_reg, unsigned *dst_float_reg);
void cgreg_set_priorities(tym_t ty, char **pseq, char **pseqmsw);
void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, symbol** retsym, const regm_t mfuncregsave );
void doswitch (block *b );
void outjmptab (block *b );
void outswitab (block *b );
int jmpopcode (elem *e );
void cod3_ptrchk(code **pc,code *pcs,regm_t keepmsk);
code *genregs (code *c , unsigned op , unsigned dstreg , unsigned srcreg );
code *gentstreg (code *c , unsigned reg );
code *genpush (code *c , unsigned reg );
code *genpop (code *c , unsigned reg );
code* gensavereg(unsigned& reg, targ_uns slot);
code *genmovreg (code *c , unsigned to , unsigned from );
code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm);
code *genshift(code *);
code *movregconst (code *c , unsigned reg , targ_size_t value , regm_t flags );
code *genjmp (code *c , unsigned op , unsigned fltarg , block *targ );
code *prolog (void );
void epilog (block *b);
code *gen_spill_reg(Symbol *s, bool toreg);
cd_t cdframeptr;
cd_t cdgot;
code *load_localgot();
targ_size_t cod3_spoff();
code *cod3_load_got();
void makeitextern (symbol *s );
void fltused(void);
int branch(block *bl, int flag);
void cod3_adjSymOffsets();
void assignaddr (block *bl );
void assignaddrc (code *c );
targ_size_t cod3_bpoffset(symbol *s);
void pinholeopt (code *c , block *bn );
void simplify_code(code *c);
void jmpaddr (code *c );
int code_match(code *c1,code *c2);
unsigned calcblksize (code *c);
unsigned calccodsize(code *c);
unsigned codout (code *c );
void addtofixlist (symbol *s , targ_size_t soffset , int seg , targ_size_t val , int flags );
void searchfixlist (symbol *s );
void outfixlist (void );
void code_hydrate(code **pc);
void code_dehydrate(code **pc);
/* cod4.c */
extern const unsigned dblreg[];
extern int cdcmp_flag;
int doinreg(symbol *s, elem *e);
code *modEA(code *c);
cd_t cdeq;
cd_t cdaddass;
cd_t cdmulass;
cd_t cdshass;
cd_t cdcmp;
cd_t cdcnvt;
cd_t cdshtlng;
cd_t cdbyteint;
cd_t cdlngsht;
cd_t cdmsw;
cd_t cdport;
cd_t cdasm;
cd_t cdsetjmp;
cd_t cdvoid;
cd_t cdhalt;
cd_t cdfar16;
cd_t cdbt;
cd_t cdbscan;
cd_t cdpair;
code *longcmp (elem *,bool,unsigned,code *);
/* cod5.c */
void cod5_prol_epi();
void cod5_noprol();
/* cgxmm.c */
code *movxmmconst(unsigned reg, unsigned sz, targ_size_t value, regm_t flags);
code *orthxmm(elem *e, regm_t *pretregs);
code *xmmeq(elem *e, regm_t *pretregs);
code *xmmcnvt(elem *e,regm_t *pretregs);
code *xmmopass(elem *e, regm_t *pretregs);
code *xmmneg(elem *e, regm_t *pretregs);
unsigned xmmload(tym_t tym);
unsigned xmmstore(tym_t tym);
code *cdvector(elem *e, regm_t *pretregs);
/* cg87.c */
void note87(elem *e, unsigned offset, int i);
#ifdef DEBUG
void pop87(int, const char *);
#else
void pop87();
#endif
code *push87 (void );
code *save87 (void );
code *save87regs(unsigned n);
void gensaverestore87(regm_t, code **, code **);
code *genfltreg(code *c,unsigned opcode,unsigned reg,targ_size_t offset);
code *genfwait(code *c);
code *comsub87(elem *e, regm_t *pretregs);
code *fixresult87 (elem *e , regm_t retregs , regm_t *pretregs );
code *fixresult_complex87(elem *e,regm_t retregs,regm_t *pretregs);
code *orth87 (elem *e , regm_t *pretregs );
code *load87(elem *e, unsigned eoffset, regm_t *pretregs, elem *eleft, int op);
int cmporder87 (elem *e );
code *eq87 (elem *e , regm_t *pretregs );
code *complex_eq87 (elem *e , regm_t *pretregs );
code *opass87 (elem *e , regm_t *pretregs );
code *cdnegass87 (elem *e , regm_t *pretregs );
code *post87 (elem *e , regm_t *pretregs );
code *cnvt87 (elem *e , regm_t *pretregs );
code *cnvteq87 (elem *e , regm_t *pretregs );
cd_t cdrndtol;
cd_t cdscale;
code *neg87 (elem *e , regm_t *pretregs );
code *neg_complex87(elem *e, regm_t *pretregs);
code *cdind87(elem *e,regm_t *pretregs);
#if TX86
extern int stackused;
#endif
code *cdconvt87(elem *e, regm_t *pretregs);
code *cload87(elem *e, regm_t *pretregs);
#ifdef DEBUG
#define pop87() pop87(__LINE__,__FILE__)
#endif
/* iasm.c */
void iasm_term( void );
regm_t iasm_regs( block *bp );
// nteh.c
code *nteh_prolog(void);
code *nteh_epilog(void);
void nteh_usevars(void);
void nteh_filltables(void);
void nteh_gentables(void);
code *nteh_setsp(int op);
code *nteh_filter(block *b);
void nteh_framehandler(symbol *);
code *nteh_gensindex(int);
#define GENSINDEXSIZE 7
code *nteh_monitor_prolog(Symbol *shandle);
code *nteh_monitor_epilog(regm_t retregs);
code *nteh_patchindex(code* c, int index);
// cgen.c
code *code_last(code *c);
void code_orflag(code *c,unsigned flag);
void code_orrex(code *c,unsigned rex);
code *setOpcode(code *c, code *cs, unsigned op);
code * __pascal cat (code *c1 , code *c2 );
code * cat3 (code *c1 , code *c2 , code *c3 );
code * cat4 (code *c1 , code *c2 , code *c3 , code *c4 );
code * cat6 (code *c1 , code *c2 , code *c3 , code *c4 , code *c5 , code *c6 );
code *gen (code *c , code *cs );
code *gen1 (code *c , unsigned op );
code *gen2 (code *c , unsigned op , unsigned rm );
code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib);
code *genasm (code *c , char *s , unsigned slen );
code *gencsi (code *c , unsigned op , unsigned rm , unsigned FL2 , SYMIDX si );
code *gencs (code *c , unsigned op , unsigned rm , unsigned FL2 , symbol *s );
code *genc2 (code *c , unsigned op , unsigned rm , targ_size_t EV2 );
code *genc1 (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 );
code *genc (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 , unsigned FL2 , targ_size_t EV2 );
code *genlinnum(code *,Srcpos);
void cgen_linnum(code **pc,Srcpos srcpos);
void cgen_prelinnum(code **pc,Srcpos srcpos);
code *genadjesp(code *c, int offset);
code *genadjfpu(code *c, int offset);
code *gennop(code *);
code *gencodelem(code *c,elem *e,regm_t *pretregs,bool constflag);
bool reghasvalue (regm_t regm , targ_size_t value , unsigned *preg );
code *regwithvalue (code *c , regm_t regm , targ_size_t value , unsigned *preg , regm_t flags );
// cgreg.c
void cgreg_init();
void cgreg_term();
void cgreg_reset();
void cgreg_used(unsigned bi,regm_t used);
void cgreg_spillreg_prolog(block *b,Symbol *s,code **pcstore,code **pcload);
void cgreg_spillreg_epilog(block *b,Symbol *s,code **pcstore,code **pcload);
int cgreg_assign(Symbol *retsym);
void cgreg_unregister(regm_t conflict);
// cgsched.c
void cgsched_block(block *b);
// Data and code can be in any number of sections
//
// Generalize the Windows platform concept of CODE,DATA,UDATA,etc
// into multiple segments
struct Ledatarec; // OMF
struct linnum_data; // Elf, Mach
typedef unsigned int IDXSTR;
typedef unsigned int IDXSEC;
typedef unsigned int IDXSYM;
struct seg_data
{
int SDseg; // index into SegData[]
targ_size_t SDoffset; // starting offset for data
int SDalignment; // power of 2