Subversion Repositories Kolibri OS

Rev

Rev 8097 | Rev 9847 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 8097 Rev 8859
1
(*
1
(*
2
    BSD 2-Clause License
2
    BSD 2-Clause License
3
 
3
 
4
    Copyright (c) 2018-2020, Anton Krotov
4
    Copyright (c) 2018-2021, Anton Krotov
5
    All rights reserved.
5
    All rights reserved.
6
*)
6
*)
7
 
7
 
8
MODULE AMD64;
8
MODULE AMD64;
9
 
9
 
10
IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, TARGETS,
10
IMPORT IL, BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PATHS, PROG, TARGETS,
11
       REG, UTILS, S := STRINGS, PE32, ELF, X86, ERRORS;
11
       REG, UTILS, S := STRINGS, PE32, ELF, X86, ERRORS;
12
 
12
 
13
 
13
 
14
CONST
14
CONST
15
 
15
 
16
    rax = REG.R0;
16
    rax = REG.R0;
17
    r10 = REG.R10;
17
    r10 = REG.R10;
18
    r11 = REG.R11;
18
    r11 = REG.R11;
19
 
19
 
20
    rcx = REG.R1;
20
    rcx = REG.R1;
21
    rdx = REG.R2;
21
    rdx = REG.R2;
22
    r8  = REG.R8;
22
    r8  = REG.R8;
23
    r9  = REG.R9;
23
    r9  = REG.R9;
24
 
24
 
25
    rsp = 4;
25
    rsp = 4;
26
    rbp = 5;
26
    rbp = 5;
27
    rsi = 6;
27
    rsi = 6;
28
    rdi = 7;
28
    rdi = 7;
29
 
29
 
30
    MAX_XMM = 5;
30
    MAX_XMM = 5;
31
 
31
 
32
    je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H;
32
    je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H;
33
 
33
 
34
    sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H;
34
    sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H;
35
 
35
 
36
    shl = IL.opLSL2; shr = IL.opLSR2; sar = IL.opASR2; ror = IL.opROR2;
36
    shl = IL.opLSL2; shr = IL.opLSR2; sar = IL.opASR2; ror = IL.opROR2;
37
 
37
 
38
    sCODE = BIN.PICCODE;
38
    sCODE = BIN.PICCODE;
39
    sDATA = BIN.PICDATA;
39
    sDATA = BIN.PICDATA;
40
    sBSS  = BIN.PICBSS;
40
    sBSS  = BIN.PICBSS;
41
    sIMP  = BIN.PICIMP;
41
    sIMP  = BIN.PICIMP;
42
 
42
 
43
    FPR_ERR = 41;
43
    FPR_ERR = 41;
44
 
44
 
45
 
45
 
46
TYPE
46
TYPE
47
 
47
 
48
    COMMAND = IL.COMMAND;
48
    COMMAND = IL.COMMAND;
49
 
49
 
50
    Number = POINTER TO RECORD (LISTS.ITEM) value: INTEGER END;
50
    Number = POINTER TO RECORD (LISTS.ITEM) value: INTEGER END;
51
 
51
 
52
    OPRR = PROCEDURE (reg1, reg2: INTEGER);
52
    OPRR = PROCEDURE (reg1, reg2: INTEGER);
53
 
53
 
54
 
54
 
55
VAR
55
VAR
56
 
56
 
57
    R: REG.REGS;
57
    R: REG.REGS;
58
 
58
 
59
    Numbers: LISTS.LIST;
59
    Numbers: LISTS.LIST;
60
    Numbers_Count: INTEGER;
60
    Numbers_Count: INTEGER;
61
    Numbers_Offs: INTEGER;
61
    Numbers_Offs: INTEGER;
62
 
62
 
63
    prog: BIN.PROGRAM;
63
    prog: BIN.PROGRAM;
64
 
64
 
65
    tcount: INTEGER;
65
    tcount: INTEGER;
66
 
66
 
67
    dllret, sofinit: INTEGER;
67
    dllret, sofinit: INTEGER;
68
 
68
 
69
    Win64RegPar: ARRAY 4 OF INTEGER;
69
    Win64RegPar: ARRAY 4 OF INTEGER;
70
    SystemVRegPar: ARRAY 6 OF INTEGER;
70
    SystemVRegPar: ARRAY 6 OF INTEGER;
71
 
71
 
72
    Xmm: ARRAY 1000 OF INTEGER;
72
    Xmm: ARRAY 1000 OF INTEGER;
73
 
73
 
74
    fname: PATHS.PATH;
74
    fname: PATHS.PATH;
75
 
75
 
76
 
76
 
77
PROCEDURE OutByte (b: BYTE);
77
PROCEDURE OutByte (b: BYTE);
78
BEGIN
78
BEGIN
79
    X86.OutByte(b)
79
    X86.OutByte(b)
80
END OutByte;
80
END OutByte;
81
 
81
 
82
 
82
 
83
PROCEDURE OutByte2 (a, b: BYTE);
83
PROCEDURE OutByte2 (a, b: BYTE);
84
BEGIN
84
BEGIN
85
    X86.OutByte(a);
85
    X86.OutByte(a);
86
    X86.OutByte(b)
86
    X86.OutByte(b)
87
END OutByte2;
87
END OutByte2;
88
 
88
 
89
 
89
 
90
PROCEDURE OutByte3 (a, b, c: BYTE);
90
PROCEDURE OutByte3 (a, b, c: BYTE);
91
BEGIN
91
BEGIN
92
    X86.OutByte(a);
92
    X86.OutByte(a);
93
    X86.OutByte(b);
93
    X86.OutByte(b);
94
    X86.OutByte(c)
94
    X86.OutByte(c)
95
END OutByte3;
95
END OutByte3;
96
 
96
 
97
 
97
 
98
PROCEDURE OutInt (n: INTEGER);
98
PROCEDURE OutInt (n: INTEGER);
99
BEGIN
99
BEGIN
100
    X86.OutByte(n MOD 256);
100
    X86.OutByte(n MOD 256);
101
    X86.OutByte(UTILS.Byte(n, 1));
101
    X86.OutByte(UTILS.Byte(n, 1));
102
    X86.OutByte(UTILS.Byte(n, 2));
102
    X86.OutByte(UTILS.Byte(n, 2));
103
    X86.OutByte(UTILS.Byte(n, 3))
103
    X86.OutByte(UTILS.Byte(n, 3))
104
END OutInt;
104
END OutInt;
105
 
105
 
106
 
106
 
107
PROCEDURE short (n: INTEGER): INTEGER;
107
PROCEDURE short (n: INTEGER): INTEGER;
108
    RETURN 2 * ORD(X86.isByte(n))
108
    RETURN 2 * ORD(X86.isByte(n))
109
END short;
109
END short;
110
 
110
 
111
 
111
 
112
PROCEDURE long (n: INTEGER): INTEGER;
112
PROCEDURE long (n: INTEGER): INTEGER;
113
    RETURN 40H * ORD(~X86.isByte(n))
113
    RETURN 40H * ORD(~X86.isByte(n))
114
END long;
114
END long;
115
 
115
 
116
 
116
 
117
PROCEDURE OutIntByte (n: INTEGER);
117
PROCEDURE OutIntByte (n: INTEGER);
118
BEGIN
118
BEGIN
119
    IF X86.isByte(n) THEN
119
    IF X86.isByte(n) THEN
120
        OutByte(n MOD 256)
120
        OutByte(n MOD 256)
121
    ELSE
121
    ELSE
122
        OutInt(n)
122
        OutInt(n)
123
    END
123
    END
124
END OutIntByte;
124
END OutIntByte;
125
 
125
 
126
 
126
 
127
PROCEDURE isLong (n: INTEGER): BOOLEAN;
127
PROCEDURE isLong (n: INTEGER): BOOLEAN;
128
    RETURN (n > UTILS.max32) OR (n < UTILS.min32)
128
    RETURN (n > UTILS.max32) OR (n < UTILS.min32)
129
END isLong;
129
END isLong;
130
 
130
 
131
 
131
 
132
PROCEDURE NewNumber (value: INTEGER);
132
PROCEDURE NewNumber (value: INTEGER);
133
VAR
133
VAR
134
    number: Number;
134
    number: Number;
135
 
135
 
136
BEGIN
136
BEGIN
137
    NEW(number);
137
    NEW(number);
138
    number.value := value;
138
    number.value := value;
139
    LISTS.push(Numbers, number);
139
    LISTS.push(Numbers, number);
140
    INC(Numbers_Count)
140
    INC(Numbers_Count)
141
END NewNumber;
141
END NewNumber;
142
 
142
 
143
 
143
 
144
PROCEDURE NewLabel (): INTEGER;
144
PROCEDURE NewLabel (): INTEGER;
145
BEGIN
145
BEGIN
146
    BIN.NewLabel(prog)
146
    BIN.NewLabel(prog)
147
    RETURN IL.NewLabel()
147
    RETURN IL.NewLabel()
148
END NewLabel;
148
END NewLabel;
149
 
149
 
150
 
150
 
151
PROCEDURE Rex (reg1, reg2: INTEGER);
151
PROCEDURE Rex (reg1, reg2: INTEGER);
152
BEGIN
152
BEGIN
153
    OutByte(48H + reg1 DIV 8 + 4 * (reg2 DIV 8))
153
    OutByte(48H + reg1 DIV 8 + 4 * (reg2 DIV 8))
154
END Rex;
154
END Rex;
155
 
155
 
156
 
156
 
157
PROCEDURE lea (reg, offset, section: INTEGER);
157
PROCEDURE lea (reg, offset, section: INTEGER);
158
BEGIN
158
BEGIN
159
    Rex(0, reg);
159
    Rex(0, reg);
160
    OutByte2(8DH, 05H + 8 * (reg MOD 8)); (* lea reg, [rip + offset] *)
160
    OutByte2(8DH, 05H + 8 * (reg MOD 8)); (* lea reg, [rip + offset] *)
161
    X86.Reloc(section, offset)
161
    X86.Reloc(section, offset)
162
END lea;
162
END lea;
163
 
163
 
164
 
164
 
165
PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
165
PROCEDURE oprr (op: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
166
BEGIN
166
BEGIN
167
    Rex(reg1, reg2);
167
    Rex(reg1, reg2);
168
    OutByte2(op, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
168
    OutByte2(op, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
169
END oprr;
169
END oprr;
170
 
170
 
171
 
171
 
172
PROCEDURE oprr2 (op1, op2: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
172
PROCEDURE oprr2 (op1, op2: BYTE; reg1, reg2: INTEGER); (* op reg1, reg2 *)
173
BEGIN
173
BEGIN
174
    Rex(reg1, reg2);
174
    Rex(reg1, reg2);
175
    OutByte3(op1, op2, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
175
    OutByte3(op1, op2, 0C0H + 8 * (reg2 MOD 8) + reg1 MOD 8)
176
END oprr2;
176
END oprr2;
177
 
177
 
178
 
178
 
179
PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *)
179
PROCEDURE mov (reg1, reg2: INTEGER); (* mov reg1, reg2 *)
180
BEGIN
180
BEGIN
181
    oprr(89H, reg1, reg2)
181
    oprr(89H, reg1, reg2)
182
END mov;
182
END mov;
183
 
183
 
184
 
184
 
185
PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *)
185
PROCEDURE xor (reg1, reg2: INTEGER); (* xor reg1, reg2 *)
186
BEGIN
186
BEGIN
187
    oprr(31H, reg1, reg2)
187
    oprr(31H, reg1, reg2)
188
END xor;
188
END xor;
189
 
189
 
190
 
190
 
191
PROCEDURE and (reg1, reg2: INTEGER); (* and reg1, reg2 *)
191
PROCEDURE and (reg1, reg2: INTEGER); (* and reg1, reg2 *)
192
BEGIN
192
BEGIN
193
    oprr(21H, reg1, reg2)
193
    oprr(21H, reg1, reg2)
194
END and;
194
END and;
195
 
195
 
196
 
196
 
197
PROCEDURE _or (reg1, reg2: INTEGER); (* or reg1, reg2 *)
197
PROCEDURE _or (reg1, reg2: INTEGER); (* or reg1, reg2 *)
198
BEGIN
198
BEGIN
199
    oprr(09H, reg1, reg2)
199
    oprr(09H, reg1, reg2)
200
END _or;
200
END _or;
201
 
201
 
202
 
202
 
203
PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *)
203
PROCEDURE add (reg1, reg2: INTEGER); (* add reg1, reg2 *)
204
BEGIN
204
BEGIN
205
    oprr(01H, reg1, reg2)
205
    oprr(01H, reg1, reg2)
206
END add;
206
END add;
207
 
207
 
208
 
208
 
209
PROCEDURE sub (reg1, reg2: INTEGER); (* sub reg1, reg2 *)
209
PROCEDURE sub (reg1, reg2: INTEGER); (* sub reg1, reg2 *)
210
BEGIN
210
BEGIN
211
    oprr(29H, reg1, reg2)
211
    oprr(29H, reg1, reg2)
212
END sub;
212
END sub;
213
 
213
 
214
 
214
 
215
PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *)
215
PROCEDURE xchg (reg1, reg2: INTEGER); (* xchg reg1, reg2 *)
216
BEGIN
216
BEGIN
217
    IF rax IN {reg1, reg2} THEN
217
    IF rax IN {reg1, reg2} THEN
218
        Rex(reg1 + reg2, 0);
218
        Rex(reg1 + reg2, 0);
219
        OutByte(90H + (reg1 + reg2) MOD 8)
219
        OutByte(90H + (reg1 + reg2) MOD 8)
220
    ELSE
220
    ELSE
221
        oprr(87H, reg1, reg2)
221
        oprr(87H, reg1, reg2)
222
    END
222
    END
223
END xchg;
223
END xchg;
224
 
224
 
225
 
225
 
226
PROCEDURE cmprr (reg1, reg2: INTEGER);  (* cmp reg1, reg2 *)
226
PROCEDURE cmprr (reg1, reg2: INTEGER);  (* cmp reg1, reg2 *)
227
BEGIN
227
BEGIN
228
    oprr(39H, reg1, reg2)
228
    oprr(39H, reg1, reg2)
229
END cmprr;
229
END cmprr;
230
 
230
 
231
 
231
 
232
PROCEDURE pop (reg: INTEGER); (* pop reg *)
232
PROCEDURE pop (reg: INTEGER); (* pop reg *)
233
BEGIN
233
BEGIN
234
    IF reg >= 8 THEN
234
    IF reg >= 8 THEN
235
        OutByte(41H)
235
        OutByte(41H)
236
    END;
236
    END;
237
    OutByte(58H + reg MOD 8)
237
    OutByte(58H + reg MOD 8)
238
END pop;
238
END pop;
239
 
239
 
240
 
240
 
241
PROCEDURE push (reg: INTEGER); (* push reg *)
241
PROCEDURE push (reg: INTEGER); (* push reg *)
242
BEGIN
242
BEGIN
243
    IF reg >= 8 THEN
243
    IF reg >= 8 THEN
244
        OutByte(41H)
244
        OutByte(41H)
245
    END;
245
    END;
246
    OutByte(50H + reg MOD 8)
246
    OutByte(50H + reg MOD 8)
247
END push;
247
END push;
248
 
248
 
249
 
249
 
250
PROCEDURE decr (reg: INTEGER);
250
PROCEDURE decr (reg: INTEGER);
251
BEGIN
251
BEGIN
252
    Rex(reg, 0);
252
    Rex(reg, 0);
253
    OutByte2(0FFH, 0C8H + reg MOD 8) (* dec reg1 *)
253
    OutByte2(0FFH, 0C8H + reg MOD 8) (* dec reg1 *)
254
END decr;
254
END decr;
255
 
255
 
256
 
256
 
257
PROCEDURE incr (reg: INTEGER);
257
PROCEDURE incr (reg: INTEGER);
258
BEGIN
258
BEGIN
259
    Rex(reg, 0);
259
    Rex(reg, 0);
260
    OutByte2(0FFH, 0C0H + reg MOD 8) (* inc reg1 *)
260
    OutByte2(0FFH, 0C0H + reg MOD 8) (* inc reg1 *)
261
END incr;
261
END incr;
262
 
262
 
263
 
263
 
264
PROCEDURE drop;
264
PROCEDURE drop;
265
BEGIN
265
BEGIN
266
    REG.Drop(R)
266
    REG.Drop(R)
267
END drop;
267
END drop;
268
 
268
 
269
 
269
 
270
PROCEDURE GetAnyReg (): INTEGER;
270
PROCEDURE GetAnyReg (): INTEGER;
271
    RETURN REG.GetAnyReg(R)
271
    RETURN REG.GetAnyReg(R)
272
END GetAnyReg;
272
END GetAnyReg;
273
 
273
 
274
 
-
 
275
PROCEDURE GetVarReg (offs: INTEGER): INTEGER;
-
 
276
    RETURN REG.GetVarReg(R, offs)
-
 
277
END GetVarReg;
-
 
278
 
-
 
279
 
274
 
280
PROCEDURE callimp (label: INTEGER);
275
PROCEDURE callimp (label: INTEGER);
281
BEGIN
276
BEGIN
282
    OutByte2(0FFH, 15H);    (* call qword[rip + label + IMP] *)
277
    OutByte2(0FFH, 15H);    (* call qword[rip + label + IMP] *)
283
    X86.Reloc(sIMP, label)
278
    X86.Reloc(sIMP, label)
284
END callimp;
279
END callimp;
285
 
280
 
286
 
281
 
287
PROCEDURE pushDA (offs: INTEGER);
282
PROCEDURE pushDA (offs: INTEGER);
288
VAR
283
VAR
289
    reg: INTEGER;
284
    reg: INTEGER;
290
 
285
 
291
BEGIN
286
BEGIN
292
    reg := GetAnyReg();
287
    reg := GetAnyReg();
293
    lea(reg, offs, sDATA);
288
    lea(reg, offs, sDATA);
294
    push(reg);
289
    push(reg);
295
    drop
290
    drop
296
END pushDA;
291
END pushDA;
297
 
292
 
298
 
293
 
299
PROCEDURE CallRTL (proc: INTEGER);
294
PROCEDURE CallRTL (proc: INTEGER);
300
VAR
295
VAR
301
    label: INTEGER;
296
    label: INTEGER;
302
 
297
 
303
BEGIN
298
BEGIN
304
    REG.Store(R);
-
 
305
    label := IL.codes.rtl[proc];
299
    label := IL.codes.rtl[proc];
306
    IF label < 0 THEN
300
    IF label < 0 THEN
307
        callimp(-label)
301
        callimp(-label)
308
    ELSE
302
    ELSE
309
        X86.call(label)
303
        X86.call(label)
310
    END;
304
    END
311
    REG.Restore(R)
-
 
312
END CallRTL;
305
END CallRTL;
313
 
306
 
314
 
307
 
315
PROCEDURE UnOp (VAR reg: INTEGER);
308
PROCEDURE UnOp (VAR reg: INTEGER);
316
BEGIN
309
BEGIN
317
    REG.UnOp(R, reg)
310
    REG.UnOp(R, reg)
318
END UnOp;
311
END UnOp;
319
 
312
 
320
 
313
 
321
PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
314
PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
322
BEGIN
315
BEGIN
323
    REG.BinOp(R, reg1, reg2)
316
    REG.BinOp(R, reg1, reg2)
324
END BinOp;
317
END BinOp;
325
 
318
 
326
 
319
 
327
PROCEDURE PushAll (NumberOfParameters: INTEGER);
320
PROCEDURE PushAll (NumberOfParameters: INTEGER);
328
BEGIN
321
BEGIN
329
    REG.PushAll(R);
322
    REG.PushAll(R);
330
    DEC(R.pushed, NumberOfParameters)
323
    DEC(R.pushed, NumberOfParameters)
331
END PushAll;
324
END PushAll;
332
 
325
 
333
 
326
 
334
PROCEDURE movabs (reg, n: INTEGER);
327
PROCEDURE movabs (reg, n: INTEGER);
335
VAR
328
VAR
336
    i: INTEGER;
329
    i: INTEGER;
337
 
330
 
338
BEGIN
331
BEGIN
339
    Rex(reg, 0);
332
    Rex(reg, 0);
340
    OutByte(0B8H + reg MOD 8); (* movabs reg, n *)
333
    OutByte(0B8H + reg MOD 8); (* movabs reg, n *)
341
    FOR i := 0 TO 7 DO
334
    FOR i := 0 TO 7 DO
342
        OutByte(UTILS.Byte(n, i))
335
        OutByte(UTILS.Byte(n, i))
343
    END
336
    END
344
END movabs;
337
END movabs;
345
 
338
 
346
 
339
 
347
PROCEDURE movrc (reg, n: INTEGER); (* mov reg, n *)
340
PROCEDURE movrc (reg, n: INTEGER); (* mov reg, n *)
348
BEGIN
341
BEGIN
349
    IF isLong(n) THEN
342
    IF isLong(n) THEN
350
        movabs(reg, n)
343
        movabs(reg, n)
351
    ELSIF n = 0 THEN
344
    ELSIF n = 0 THEN
352
        xor(reg, reg)
345
        xor(reg, reg)
353
    ELSE
346
    ELSE
354
        Rex(reg, 0);
347
        Rex(reg, 0);
355
        OutByte2(0C7H, 0C0H + reg MOD 8);
348
        OutByte2(0C7H, 0C0H + reg MOD 8);
356
        OutInt(n)
349
        OutInt(n)
357
    END
350
    END
358
END movrc;
351
END movrc;
359
 
352
 
360
 
353
 
361
PROCEDURE test (reg: INTEGER); (* test reg, reg *)
354
PROCEDURE test (reg: INTEGER); (* test reg, reg *)
362
BEGIN
355
BEGIN
363
    oprr(85H, reg, reg)
356
    oprr(85H, reg, reg)
364
END test;
357
END test;
365
 
358
 
366
 
359
 
367
PROCEDURE oprlongc (reg, n: INTEGER; oprr: OPRR);
360
PROCEDURE oprlongc (reg, n: INTEGER; oprr: OPRR);
368
VAR
361
VAR
369
    reg2: INTEGER;
362
    reg2: INTEGER;
370
 
363
 
371
BEGIN
364
BEGIN
372
    reg2 := GetAnyReg();
365
    reg2 := GetAnyReg();
373
    ASSERT(reg2 # reg);
366
    ASSERT(reg2 # reg);
374
    movabs(reg2, n);
367
    movabs(reg2, n);
375
    oprr(reg, reg2);
368
    oprr(reg, reg2);
376
    drop
369
    drop
377
END oprlongc;
370
END oprlongc;
378
 
371
 
379
 
372
 
380
PROCEDURE oprc (op, reg, n: INTEGER; oprr: OPRR);
373
PROCEDURE oprc (op, reg, n: INTEGER; oprr: OPRR);
381
BEGIN
374
BEGIN
382
    IF isLong(n) THEN
375
    IF isLong(n) THEN
383
        oprlongc(reg, n, oprr)
376
        oprlongc(reg, n, oprr)
384
    ELSE
377
    ELSE
385
        Rex(reg, 0);
378
        Rex(reg, 0);
386
        X86.oprc(op, reg, n)
379
        X86.oprc(op, reg, n)
387
    END
380
    END
388
END oprc;
381
END oprc;
389
 
382
 
390
 
383
 
391
PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *)
384
PROCEDURE cmprc (reg, n: INTEGER); (* cmp reg, n *)
392
BEGIN
385
BEGIN
393
    IF n = 0 THEN
386
    IF n = 0 THEN
394
        test(reg)
387
        test(reg)
395
    ELSE
388
    ELSE
396
        oprc(0F8H, reg, n, cmprr)
389
        oprc(0F8H, reg, n, cmprr)
397
    END
390
    END
398
END cmprc;
391
END cmprc;
399
 
392
 
400
 
393
 
401
PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *)
394
PROCEDURE addrc (reg, n: INTEGER); (* add reg, n *)
402
BEGIN
395
BEGIN
403
    oprc(0C0H, reg, n, add)
396
    oprc(0C0H, reg, n, add)
404
END addrc;
397
END addrc;
405
 
398
 
406
 
399
 
407
PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *)
400
PROCEDURE subrc (reg, n: INTEGER); (* sub reg, n *)
408
BEGIN
401
BEGIN
409
    oprc(0E8H, reg, n, sub)
402
    oprc(0E8H, reg, n, sub)
410
END subrc;
403
END subrc;
411
 
404
 
412
 
405
 
413
PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *)
406
PROCEDURE andrc (reg, n: INTEGER); (* and reg, n *)
414
BEGIN
407
BEGIN
415
    oprc(0E0H, reg, n, and)
408
    oprc(0E0H, reg, n, and)
416
END andrc;
409
END andrc;
417
 
410
 
418
 
411
 
419
PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *)
412
PROCEDURE orrc (reg, n: INTEGER); (* or reg, n *)
420
BEGIN
413
BEGIN
421
    oprc(0C8H, reg, n, _or)
414
    oprc(0C8H, reg, n, _or)
422
END orrc;
415
END orrc;
423
 
416
 
424
 
417
 
425
PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *)
418
PROCEDURE xorrc (reg, n: INTEGER); (* xor reg, n *)
426
BEGIN
419
BEGIN
427
    oprc(0F0H, reg, n, xor)
420
    oprc(0F0H, reg, n, xor)
428
END xorrc;
421
END xorrc;
429
 
422
 
430
 
423
 
431
PROCEDURE pushc (n: INTEGER);
424
PROCEDURE pushc (n: INTEGER);
432
VAR
425
VAR
433
    reg2: INTEGER;
426
    reg2: INTEGER;
434
 
427
 
435
BEGIN
428
BEGIN
436
    IF isLong(n) THEN
429
    IF isLong(n) THEN
437
        reg2 := GetAnyReg();
430
        reg2 := GetAnyReg();
438
        movabs(reg2, n);
431
        movabs(reg2, n);
439
        push(reg2);
432
        push(reg2);
440
        drop
433
        drop
441
    ELSE
434
    ELSE
442
        X86.pushc(n)
435
        X86.pushc(n)
443
    END
436
    END
444
END pushc;
437
END pushc;
445
 
438
 
446
 
439
 
447
PROCEDURE not (reg: INTEGER); (* not reg *)
440
PROCEDURE not (reg: INTEGER); (* not reg *)
448
BEGIN
441
BEGIN
449
    Rex(reg, 0);
442
    Rex(reg, 0);
450
    OutByte2(0F7H, 0D0H + reg MOD 8)
443
    OutByte2(0F7H, 0D0H + reg MOD 8)
451
END not;
444
END not;
452
 
445
 
453
 
446
 
454
PROCEDURE neg (reg: INTEGER); (* neg reg *)
447
PROCEDURE neg (reg: INTEGER); (* neg reg *)
455
BEGIN
448
BEGIN
456
    Rex(reg, 0);
449
    Rex(reg, 0);
457
    OutByte2(0F7H, 0D8H + reg MOD 8)
450
    OutByte2(0F7H, 0D8H + reg MOD 8)
458
END neg;
451
END neg;
459
 
452
 
460
 
453
 
461
PROCEDURE movzx (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *)
454
PROCEDURE movzx (reg1, reg2, offs: INTEGER; word: BOOLEAN); (* movzx reg1, byte/word[reg2 + offs] *)
462
BEGIN
455
BEGIN
463
    Rex(reg2, reg1);
456
    Rex(reg2, reg1);
464
    X86.movzx(reg1, reg2, offs, word)
457
    X86.movzx(reg1, reg2, offs, word)
465
END movzx;
458
END movzx;
466
 
459
 
467
 
460
 
468
PROCEDURE movmr32 (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2_32 *)
461
PROCEDURE movmr32 (reg1, offs, reg2: INTEGER); (* mov dword[reg1+offs], reg2_32 *)
469
BEGIN
462
BEGIN
470
    X86._movrm(reg2, reg1, offs, 32, TRUE)
463
    X86._movrm(reg2, reg1, offs, 32, TRUE)
471
END movmr32;
464
END movmr32;
472
 
465
 
473
 
466
 
474
PROCEDURE movrm32 (reg1, reg2, offs: INTEGER); (* mov reg1_32, dword[reg2+offs] *)
467
PROCEDURE movrm32 (reg1, reg2, offs: INTEGER); (* mov reg1_32, dword[reg2+offs] *)
475
BEGIN
468
BEGIN
476
    X86._movrm(reg1, reg2, offs, 32, FALSE)
469
    X86._movrm(reg1, reg2, offs, 32, FALSE)
477
END movrm32;
470
END movrm32;
478
 
471
 
479
 
472
 
480
PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov qword[reg1+offs], reg2 *)
473
PROCEDURE movmr (reg1, offs, reg2: INTEGER); (* mov qword[reg1+offs], reg2 *)
481
BEGIN
474
BEGIN
482
    X86._movrm(reg2, reg1, offs, 64, TRUE)
475
    X86._movrm(reg2, reg1, offs, 64, TRUE)
483
END movmr;
476
END movmr;
484
 
477
 
485
 
478
 
486
PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, qword[reg2+offs] *)
479
PROCEDURE movrm (reg1, reg2, offs: INTEGER); (* mov reg1, qword[reg2+offs] *)
487
BEGIN
480
BEGIN
488
    X86._movrm(reg1, reg2, offs, 64, FALSE)
481
    X86._movrm(reg1, reg2, offs, 64, FALSE)
489
END movrm;
482
END movrm;
490
 
483
 
491
 
484
 
492
PROCEDURE comisd (xmm1, xmm2: INTEGER); (* comisd xmm1, xmm2 *)
485
PROCEDURE comisd (xmm1, xmm2: INTEGER); (* comisd xmm1, xmm2 *)
493
BEGIN
486
BEGIN
494
    OutByte(66H);
487
    OutByte(66H);
495
    IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
488
    IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
496
        OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
489
        OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
497
    END;
490
    END;
498
    OutByte3(0FH, 2FH, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
491
    OutByte3(0FH, 2FH, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
499
END comisd;
492
END comisd;
500
 
493
 
501
 
494
 
502
PROCEDURE _movsdrm (xmm, reg, offs: INTEGER; mr: BOOLEAN);
495
PROCEDURE _movsdrm (xmm, reg, offs: INTEGER; mr: BOOLEAN);
503
VAR
496
VAR
504
    b: BYTE;
497
    b: BYTE;
505
 
498
 
506
BEGIN
499
BEGIN
507
    OutByte(0F2H);
500
    OutByte(0F2H);
508
    IF (xmm >= 8) OR (reg >= 8) THEN
501
    IF (xmm >= 8) OR (reg >= 8) THEN
509
        OutByte(40H + (xmm DIV 8) * 4 + reg DIV 8)
502
        OutByte(40H + (xmm DIV 8) * 4 + reg DIV 8)
510
    END;
503
    END;
511
    OutByte2(0FH, 10H + ORD(mr));
504
    OutByte2(0FH, 10H + ORD(mr));
512
    IF (offs = 0) & (reg # rbp) THEN
505
    IF (offs = 0) & (reg # rbp) THEN
513
        b := 0
506
        b := 0
514
    ELSE
507
    ELSE
515
        b := 40H + long(offs)
508
        b := 40H + long(offs)
516
    END;
509
    END;
517
    OutByte(b + (xmm MOD 8) * 8 + reg MOD 8);
510
    OutByte(b + (xmm MOD 8) * 8 + reg MOD 8);
518
    IF reg = rsp THEN
511
    IF reg = rsp THEN
519
        OutByte(24H)
512
        OutByte(24H)
520
    END;
513
    END;
521
    IF b # 0 THEN
514
    IF b # 0 THEN
522
        OutIntByte(offs)
515
        OutIntByte(offs)
523
    END
516
    END
524
END _movsdrm;
517
END _movsdrm;
525
 
518
 
526
 
519
 
527
PROCEDURE movsdrm (xmm, reg, offs: INTEGER); (* movsd xmm, qword[reg+offs] *)
520
PROCEDURE movsdrm (xmm, reg, offs: INTEGER); (* movsd xmm, qword[reg+offs] *)
528
BEGIN
521
BEGIN
529
    _movsdrm(xmm, reg, offs, FALSE)
522
    _movsdrm(xmm, reg, offs, FALSE)
530
END movsdrm;
523
END movsdrm;
531
 
524
 
532
 
525
 
533
PROCEDURE movsdmr (reg, offs, xmm: INTEGER); (* movsd qword[reg+offs], xmm *)
526
PROCEDURE movsdmr (reg, offs, xmm: INTEGER); (* movsd qword[reg+offs], xmm *)
534
BEGIN
527
BEGIN
535
    _movsdrm(xmm, reg, offs, TRUE)
528
    _movsdrm(xmm, reg, offs, TRUE)
536
END movsdmr;
529
END movsdmr;
537
 
530
 
538
 
531
 
539
PROCEDURE opxx (op, xmm1, xmm2: INTEGER);
532
PROCEDURE opxx (op, xmm1, xmm2: INTEGER);
540
BEGIN
533
BEGIN
541
    OutByte(0F2H);
534
    OutByte(0F2H);
542
    IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
535
    IF (xmm1 >= 8) OR (xmm2 >= 8) THEN
543
        OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
536
        OutByte(40H + (xmm1 DIV 8) * 4 + xmm2 DIV 8)
544
    END;
537
    END;
545
    OutByte3(0FH, op, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
538
    OutByte3(0FH, op, 0C0H + (xmm1 MOD 8) * 8 + xmm2 MOD 8)
546
END opxx;
539
END opxx;
547
 
540
 
548
 
541
 
549
PROCEDURE jcc (cc, label: INTEGER); (* jcc label *)
542
PROCEDURE jcc (cc, label: INTEGER); (* jcc label *)
550
BEGIN
543
BEGIN
551
    X86.jcc(cc, label)
544
    X86.jcc(cc, label)
552
END jcc;
545
END jcc;
553
 
546
 
554
 
547
 
555
PROCEDURE shiftrc (op, reg, n: INTEGER);
548
PROCEDURE shiftrc (op, reg, n: INTEGER);
556
BEGIN
549
BEGIN
557
    Rex(reg, 0);
550
    Rex(reg, 0);
558
    IF n = 1 THEN
551
    IF n = 1 THEN
559
        OutByte(0D1H)
552
        OutByte(0D1H)
560
    ELSE
553
    ELSE
561
        OutByte(0C1H)
554
        OutByte(0C1H)
562
    END;
555
    END;
563
    X86.shift(op, reg MOD 8);
556
    X86.shift(op, reg MOD 8);
564
    IF n # 1 THEN
557
    IF n # 1 THEN
565
        OutByte(n)
558
        OutByte(n)
566
    END
559
    END
567
END shiftrc;
560
END shiftrc;
568
 
561
 
569
 
-
 
570
PROCEDURE getVar (variables: LISTS.LIST; offset: INTEGER): IL.LOCALVAR;
-
 
571
VAR
-
 
572
    cur: IL.LOCALVAR;
-
 
573
 
-
 
574
BEGIN
-
 
575
    cur := variables.first(IL.LOCALVAR);
-
 
576
    WHILE (cur # NIL) & (cur.offset # offset) DO
-
 
577
        cur := cur.next(IL.LOCALVAR)
-
 
578
    END
-
 
579
 
-
 
580
    RETURN cur
-
 
581
END getVar;
-
 
582
 
-
 
583
 
-
 
584
PROCEDURE allocReg (cmd: COMMAND);
-
 
585
VAR
-
 
586
    leave:      BOOLEAN;
-
 
587
    leaf:       BOOLEAN;
-
 
588
    cur:        COMMAND;
-
 
589
    variables:  LISTS.LIST;
-
 
590
    lvar, rvar: IL.LOCALVAR;
-
 
591
    reg:        INTEGER;
-
 
592
    max:        INTEGER;
-
 
593
    loop:       INTEGER;
-
 
594
 
-
 
595
BEGIN
-
 
596
    loop := 1;
-
 
597
    variables := cmd.variables;
-
 
598
    leave := FALSE;
-
 
599
    leaf := TRUE;
-
 
600
 
-
 
601
    cur := cmd.next(COMMAND);
-
 
602
    REPEAT
-
 
603
        CASE cur.opcode OF
-
 
604
        |IL.opLLOAD64,
-
 
605
         IL.opLLOAD8,
-
 
606
         IL.opLLOAD16,
-
 
607
         IL.opLLOAD32,
-
 
608
         IL.opLLOAD64_PARAM,
-
 
609
         IL.opLLOAD32_PARAM,
-
 
610
         IL.opLADR_SAVE,
-
 
611
         IL.opLADR_INC,
-
 
612
         IL.opLADR_DEC,
-
 
613
         IL.opLADR_INCB,
-
 
614
         IL.opLADR_DECB,
-
 
615
         IL.opLADR_INCL,
-
 
616
         IL.opLADR_EXCL,
-
 
617
         IL.opLADR_UNPK:
-
 
618
            lvar := getVar(variables, cur.param2);
-
 
619
            IF (lvar # NIL) & (lvar.count # -1) THEN
-
 
620
                INC(lvar.count, loop)
-
 
621
            END
-
 
622
 
-
 
623
        |IL.opLADR_SAVEC,
-
 
624
         IL.opLADR_INCC,
-
 
625
         IL.opLADR_INCCB,
-
 
626
         IL.opLADR_DECCB,
-
 
627
         IL.opLADR_INCLC,
-
 
628
         IL.opLADR_EXCLC:
-
 
629
            lvar := getVar(variables, cur.param1);
-
 
630
            IF (lvar # NIL) & (lvar.count # -1) THEN
-
 
631
                INC(lvar.count, loop)
-
 
632
            END
-
 
633
 
-
 
634
        |IL.opLADR:
-
 
635
            lvar := getVar(variables, cur.param2);
-
 
636
            IF (lvar # NIL) & (lvar.count # -1) THEN
-
 
637
                lvar.count := -1
-
 
638
            END
-
 
639
 
-
 
640
        |IL.opLOOP:
-
 
641
            INC(loop, 10)
-
 
642
 
-
 
643
        |IL.opENDLOOP:
-
 
644
            DEC(loop, 10)
-
 
645
 
-
 
646
        |IL.opLEAVE,
-
 
647
         IL.opLEAVER,
-
 
648
         IL.opLEAVEF:
-
 
649
            leave := TRUE
-
 
650
 
-
 
651
        |IL.opCALL, IL.opCALLP, IL.opCALLI,
-
 
652
         IL.opWIN64CALL, IL.opWIN64CALLP, IL.opWIN64CALLI,
-
 
653
         IL.opSYSVCALL, IL.opSYSVCALLP, IL.opSYSVCALLI,
-
 
654
 
-
 
655
         IL.opSAVES, IL.opRSET, IL.opRSETR,
-
 
656
         IL.opRSETL, IL.opRSET1,
-
 
657
         IL.opEQS .. IL.opGES,
-
 
658
         IL.opEQSW .. IL.opGESW,
-
 
659
         IL.opCOPY, IL.opMOVE, IL.opCOPYA,
-
 
660
         IL.opCOPYS, IL.opROT,
-
 
661
         IL.opNEW, IL.opDISP, IL.opISREC,
-
 
662
         IL.opIS, IL.opTYPEGR, IL.opTYPEGP,
-
 
663
         IL.opTYPEGD, IL.opCASET, IL.opDIV,
-
 
664
         IL.opDIVL, IL.opMOD,
-
 
665
         IL.opMODL, IL.opLENGTH, IL.opLENGTHW:
-
 
666
            leaf := FALSE
-
 
667
 
-
 
668
        |IL.opDIVR, IL.opMODR:
-
 
669
            leaf := UTILS.Log2(cur.param2) >= 0
-
 
670
 
-
 
671
        ELSE
-
 
672
 
-
 
673
        END;
-
 
674
        cur := cur.next(COMMAND)
-
 
675
    UNTIL leave OR ~leaf;
-
 
676
 
-
 
677
    IF leaf THEN
-
 
678
        REPEAT
-
 
679
            reg := -1;
-
 
680
            max := -1;
-
 
681
            rvar := NIL;
-
 
682
            lvar := variables.first(IL.LOCALVAR);
-
 
683
            WHILE lvar # NIL DO
-
 
684
                IF lvar.count > max THEN
-
 
685
                    max := lvar.count;
-
 
686
                    rvar := lvar
-
 
687
                END;
-
 
688
                lvar := lvar.next(IL.LOCALVAR)
-
 
689
            END;
-
 
690
 
-
 
691
            IF rvar # NIL THEN
-
 
692
                reg := REG.GetAnyVarReg(R);
-
 
693
                IF reg # -1 THEN
-
 
694
                    REG.Lock(R, reg, rvar.offset, rvar.size);
-
 
695
                    REG.Load(R, reg);
-
 
696
                    rvar.count := -1
-
 
697
                END
-
 
698
            END
-
 
699
 
-
 
700
        UNTIL (rvar = NIL) OR (reg = -1)
-
 
701
    END
-
 
702
 
-
 
703
END allocReg;
-
 
704
 
-
 
705
 
562
 
706
PROCEDURE GetRegA;
563
PROCEDURE GetRegA;
707
BEGIN
564
BEGIN
708
    ASSERT(REG.GetReg(R, rax))
565
    ASSERT(REG.GetReg(R, rax))
709
END GetRegA;
566
END GetRegA;
710
 
567
 
711
 
568
 
712
PROCEDURE Win64Passing (params: INTEGER);
569
PROCEDURE Win64Passing (params: INTEGER);
713
VAR
570
VAR
714
    n, i: INTEGER;
571
    n, i: INTEGER;
715
 
572
 
716
BEGIN
573
BEGIN
717
    n := params MOD 32;
574
    n := params MOD 32;
718
    params := params DIV 32;
575
    params := params DIV 32;
719
    FOR i := 0 TO n - 1 DO
576
    FOR i := 0 TO n - 1 DO
720
        IF i IN BITS(params) THEN
577
        IF i IN BITS(params) THEN
721
            movsdrm(i, rsp, i * 8)
578
            movsdrm(i, rsp, i * 8)
722
        ELSE
579
        ELSE
723
            movrm(Win64RegPar[i], rsp, i * 8)
580
            movrm(Win64RegPar[i], rsp, i * 8)
724
        END
581
        END
725
    END
582
    END
726
END Win64Passing;
583
END Win64Passing;
727
 
584
 
728
 
585
 
729
PROCEDURE SysVPassing (params: INTEGER);
586
PROCEDURE SysVPassing (params: INTEGER);
730
VAR
587
VAR
731
    n, i, s, p, ofs: INTEGER;
588
    n, i, s, p, ofs: INTEGER;
732
    i_count, f_count: INTEGER;
589
    i_count, f_count: INTEGER;
733
    reg: BOOLEAN;
590
    reg: BOOLEAN;
734
 
591
 
735
BEGIN
592
BEGIN
736
    ASSERT(r10 IN R.regs);
593
    ASSERT(r11 IN R.regs);
737
    n := params MOD 32;
594
    n := params MOD 32;
738
    params := params DIV 32;
595
    params := params DIV 32;
739
    s := 0;
596
    s := 0;
740
 
597
 
741
    i_count := 0;
598
    i_count := 0;
742
    f_count := 0;
599
    f_count := 0;
743
    FOR i := 0 TO n - 1 DO
600
    FOR i := 0 TO n - 1 DO
744
        IF i IN BITS(params) THEN
601
        IF i IN BITS(params) THEN
745
            INC(f_count)
602
            INC(f_count)
746
        ELSE
603
        ELSE
747
            INC(i_count)
604
            INC(i_count)
748
        END
605
        END
749
    END;
606
    END;
750
 
607
 
751
    s := MAX(0, f_count - 8) + MAX(0, i_count - 6);
608
    s := MAX(0, f_count - 8) + MAX(0, i_count - 6);
752
    p := 0;
609
    p := 0;
753
 
610
 
754
    subrc(rsp, s * 8);
611
    subrc(rsp, s * 8);
755
 
612
 
756
    i_count := 0;
613
    i_count := 0;
757
    f_count := 0;
614
    f_count := 0;
758
    FOR i := 0 TO n - 1 DO
615
    FOR i := 0 TO n - 1 DO
759
        ofs := (i + s) * 8;
616
        ofs := (i + s) * 8;
760
        IF i IN BITS(params) THEN
617
        IF i IN BITS(params) THEN
761
            reg := f_count <= 7;
618
            reg := f_count <= 7;
762
            IF reg THEN
619
            IF reg THEN
763
                movsdrm(f_count, rsp, ofs);
620
                movsdrm(f_count, rsp, ofs);
764
                INC(f_count)
621
                INC(f_count)
765
            END
622
            END
766
        ELSE
623
        ELSE
767
            reg := i_count <= 5;
624
            reg := i_count <= 5;
768
            IF reg THEN
625
            IF reg THEN
769
                movrm(SystemVRegPar[i_count], rsp, ofs);
626
                movrm(SystemVRegPar[i_count], rsp, ofs);
770
                INC(i_count)
627
                INC(i_count)
771
            END
628
            END
772
        END;
629
        END;
773
 
630
 
774
        IF ~reg THEN
631
        IF ~reg THEN
775
            movrm(r10, rsp, ofs);
632
            movrm(r11, rsp, ofs);
776
            movmr(rsp, p, r10);
633
            movmr(rsp, p, r11);
777
            INC(p, 8)
634
            INC(p, 8)
778
        END
635
        END
779
    END
636
    END
780
END SysVPassing;
637
END SysVPassing;
781
 
638
 
782
 
639
 
783
PROCEDURE fcmp (op: INTEGER; xmm: INTEGER);
640
PROCEDURE fcmp (op: INTEGER; xmm: INTEGER);
784
VAR
641
VAR
785
    cc, reg: INTEGER;
642
    cc, reg: INTEGER;
786
 
643
 
787
BEGIN
644
BEGIN
788
    reg := GetAnyReg();
645
    reg := GetAnyReg();
789
    xor(reg, reg);
646
    xor(reg, reg);
790
    CASE op OF
647
    CASE op OF
791
    |IL.opEQF:
648
    |IL.opEQF:
792
        comisd(xmm - 1, xmm);
649
        comisd(xmm - 1, xmm);
793
        cc := sete
650
        cc := sete
794
 
651
 
795
    |IL.opNEF:
652
    |IL.opNEF:
796
        comisd(xmm - 1, xmm);
653
        comisd(xmm - 1, xmm);
797
        cc := setne
654
        cc := setne
798
 
655
 
799
    |IL.opLTF:
656
    |IL.opLTF:
800
        comisd(xmm - 1, xmm);
657
        comisd(xmm - 1, xmm);
801
        cc := setc
658
        cc := setc
802
 
659
 
803
    |IL.opGTF:
660
    |IL.opGTF:
804
        comisd(xmm, xmm - 1);
661
        comisd(xmm, xmm - 1);
805
        cc := setc
662
        cc := setc
806
 
663
 
807
    |IL.opLEF:
664
    |IL.opLEF:
808
        comisd(xmm, xmm - 1);
665
        comisd(xmm, xmm - 1);
809
        cc := setnc
666
        cc := setnc
810
 
667
 
811
    |IL.opGEF:
668
    |IL.opGEF:
812
        comisd(xmm - 1, xmm);
669
        comisd(xmm - 1, xmm);
813
        cc := setnc
670
        cc := setnc
814
    END;
671
    END;
815
    OutByte2(7AH, 3 + reg DIV 8); (* jp L *)
672
    OutByte2(7AH, 3 + reg DIV 8); (* jp L *)
816
    X86.setcc(cc, reg)
673
    X86.setcc(cc, reg)
817
    (* L: *)
674
    (* L: *)
818
END fcmp;
675
END fcmp;
819
 
676
 
820
 
677
 
821
PROCEDURE translate (commands: LISTS.LIST; stroffs: INTEGER);
678
PROCEDURE translate (commands: LISTS.LIST; stroffs: INTEGER);
822
VAR
679
VAR
823
    cmd, next: COMMAND;
680
    cmd, next: COMMAND;
824
 
681
 
825
    opcode, param1, param2, param3, a, b, c, n, label, L, i, cc: INTEGER;
682
    opcode, param1, param2, param3, a, b, c, n, label, L, i, cc: INTEGER;
826
 
683
 
827
    reg1, reg2, xmm: INTEGER;
684
    reg1, reg2, xmm: INTEGER;
828
 
685
 
829
    float: REAL;
686
    float: REAL;
830
 
-
 
831
    regVar: BOOLEAN;
-
 
832
 
687
 
833
BEGIN
688
BEGIN
834
    xmm := -1;
689
    xmm := -1;
835
    cmd := commands.first(COMMAND);
690
    cmd := commands.first(COMMAND);
836
    WHILE cmd # NIL DO
691
    WHILE cmd # NIL DO
837
 
692
 
838
        param1 := cmd.param1;
693
        param1 := cmd.param1;
839
        param2 := cmd.param2;
694
        param2 := cmd.param2;
840
 
695
 
841
        opcode := cmd.opcode;
696
        opcode := cmd.opcode;
842
 
697
 
843
        CASE opcode OF
698
        CASE opcode OF
844
 
699
 
845
        |IL.opJMP:
700
        |IL.opJMP:
846
            X86.jmp(param1)
701
            X86.jmp(param1)
847
 
702
 
848
        |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL:
703
        |IL.opCALL, IL.opWIN64CALL, IL.opSYSVCALL:
849
            REG.Store(R);
-
 
850
            CASE opcode OF
704
            CASE opcode OF
851
            |IL.opCALL:
705
            |IL.opCALL:
852
            |IL.opWIN64CALL: Win64Passing(param2)
706
            |IL.opWIN64CALL: Win64Passing(param2)
853
            |IL.opSYSVCALL:  SysVPassing(param2)
707
            |IL.opSYSVCALL:  SysVPassing(param2)
854
            END;
708
            END;
855
            X86.call(param1);
709
            X86.call(param1)
856
            REG.Restore(R)
-
 
857
 
710
 
858
        |IL.opCALLP, IL.opWIN64CALLP, IL.opSYSVCALLP:
711
        |IL.opCALLP, IL.opWIN64CALLP, IL.opSYSVCALLP:
859
            UnOp(reg1);
712
            UnOp(reg1);
860
            IF reg1 # rax THEN
713
            IF reg1 # rax THEN
861
                GetRegA;
714
                mov(rax, reg1)
862
                ASSERT(REG.Exchange(R, reg1, rax));
-
 
863
                drop
-
 
864
            END;
715
            END;
865
            drop;
716
            drop;
866
            REG.Store(R);
-
 
867
            CASE opcode OF
717
            CASE opcode OF
868
            |IL.opCALLP:
718
            |IL.opCALLP:
869
            |IL.opWIN64CALLP: Win64Passing(param2)
719
            |IL.opWIN64CALLP: Win64Passing(param2)
870
            |IL.opSYSVCALLP:  SysVPassing(param2)
720
            |IL.opSYSVCALLP:  SysVPassing(param2)
871
            END;
721
            END;
872
            OutByte2(0FFH, 0D0H); (* call rax *)
722
            OutByte2(0FFH, 0D0H); (* call rax *)
873
            REG.Restore(R);
-
 
874
            ASSERT(R.top = -1)
723
            ASSERT(R.top = -1)
875
 
724
 
876
        |IL.opCALLI, IL.opWIN64CALLI, IL.opSYSVCALLI:
725
        |IL.opCALLI, IL.opWIN64CALLI, IL.opSYSVCALLI:
877
            REG.Store(R);
-
 
878
            CASE opcode OF
726
            CASE opcode OF
879
            |IL.opCALLI:
727
            |IL.opCALLI:
880
            |IL.opWIN64CALLI: Win64Passing(param2)
728
            |IL.opWIN64CALLI: Win64Passing(param2)
881
            |IL.opSYSVCALLI:  SysVPassing(param2)
729
            |IL.opSYSVCALLI:  SysVPassing(param2)
882
            END;
730
            END;
883
            callimp(param1);
731
            callimp(param1)
884
            REG.Restore(R)
-
 
885
 
732
 
886
        |IL.opLABEL:
733
        |IL.opLABEL:
887
            X86.SetLabel(param1)
734
            X86.SetLabel(param1)
888
 
735
 
889
        |IL.opERR:
736
        |IL.opERR:
890
            CallRTL(IL._error)
737
            CallRTL(IL._error)
891
 
738
 
892
        |IL.opONERR:
739
        |IL.opONERR:
893
            pushc(param2);
740
            pushc(param2);
894
            X86.jmp(param1)
741
            X86.jmp(param1)
895
 
742
 
896
        |IL.opPUSHC:
743
        |IL.opPUSHC:
897
            pushc(param2)
744
            pushc(param2)
898
 
745
 
899
        |IL.opPRECALL:
746
        |IL.opPRECALL:
900
            PushAll(0);
747
            PushAll(0);
901
            IF (param2 # 0) & (xmm >= 0) THEN
748
            IF (param2 # 0) & (xmm >= 0) THEN
902
                subrc(rsp, 8)
749
                subrc(rsp, 8)
903
            END;
750
            END;
904
            INC(Xmm[0]);
751
            INC(Xmm[0]);
905
            Xmm[Xmm[0]] := xmm + 1;
752
            Xmm[Xmm[0]] := xmm + 1;
906
            WHILE xmm >= 0 DO
753
            WHILE xmm >= 0 DO
907
                subrc(rsp, 8);
754
                subrc(rsp, 8);
908
                movsdmr(rsp, 0, xmm);
755
                movsdmr(rsp, 0, xmm);
909
                DEC(xmm)
756
                DEC(xmm)
910
            END;
757
            END;
911
            ASSERT(xmm = -1)
758
            ASSERT(xmm = -1)
912
 
759
 
913
        |IL.opWIN64ALIGN16:
760
        |IL.opWIN64ALIGN16:
914
            ASSERT(rax IN R.regs);
761
            ASSERT(rax IN R.regs);
915
            mov(rax, rsp);
762
            mov(rax, rsp);
916
            andrc(rsp, -16);
763
            andrc(rsp, -16);
917
            push(rax);
764
            push(rax);
918
            subrc(rsp, (MAX(param2 - 4, 0) MOD 2 + MAX(4 - param2, 0) + 1) * 8)
765
            subrc(rsp, (MAX(param2 - 4, 0) MOD 2 + MAX(4 - param2, 0) + 1) * 8)
919
 
766
 
920
        |IL.opSYSVALIGN16:
767
        |IL.opSYSVALIGN16:
921
            ASSERT(rax IN R.regs);
768
            ASSERT(rax IN R.regs);
922
            mov(rax, rsp);
769
            mov(rax, rsp);
923
            andrc(rsp, -16);
770
            andrc(rsp, -16);
924
            push(rax);
771
            push(rax);
925
            IF ~ODD(param2) THEN
772
            IF ~ODD(param2) THEN
926
                push(rax)
773
                push(rax)
927
            END
774
            END
928
 
775
 
929
        |IL.opRESF, IL.opRES:
776
        |IL.opRESF, IL.opRES:
930
            ASSERT(R.top = -1);
777
            ASSERT(R.top = -1);
931
            ASSERT(xmm = -1);
778
            ASSERT(xmm = -1);
932
            n := Xmm[Xmm[0]]; DEC(Xmm[0]);
779
            n := Xmm[Xmm[0]]; DEC(Xmm[0]);
933
 
780
 
934
            IF opcode = IL.opRESF THEN
781
            IF opcode = IL.opRESF THEN
935
                INC(xmm);
782
                INC(xmm);
936
                IF n > 0 THEN
783
                IF n > 0 THEN
937
                    movsdmr(rsp, n * 8, 0);
784
                    movsdmr(rsp, n * 8, 0);
938
                    DEC(xmm);
785
                    DEC(xmm);
939
                    INC(n)
786
                    INC(n)
940
                END;
787
                END;
941
 
788
 
942
                IF xmm + n > MAX_XMM THEN
789
                IF xmm + n > MAX_XMM THEN
943
                    ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
790
                    ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
944
                END
791
                END
945
            ELSE
792
            ELSE
946
                GetRegA
793
                GetRegA
947
            END;
794
            END;
948
 
795
 
949
            WHILE n > 0 DO
796
            WHILE n > 0 DO
950
                INC(xmm);
797
                INC(xmm);
951
                movsdrm(xmm, rsp, 0);
798
                movsdrm(xmm, rsp, 0);
952
                addrc(rsp, 8);
799
                addrc(rsp, 8);
953
                DEC(n)
800
                DEC(n)
954
            END
801
            END
955
 
802
 
956
        |IL.opENTER:
803
        |IL.opENTER:
957
            ASSERT(R.top = -1);
804
            ASSERT(R.top = -1);
958
 
805
 
959
            X86.SetLabel(param1);
806
            X86.SetLabel(param1);
960
 
807
 
961
            param3 := cmd.param3;
808
            param3 := cmd.param3;
962
 
809
 
963
            IF param3 > 0 THEN
810
            IF param3 > 0 THEN
964
                push(rbp);
811
                push(rbp);
965
                mov(rbp, rsp);
812
                mov(rbp, rsp);
966
 
813
 
967
                n := param3 MOD 32;
814
                n := param3 MOD 32;
968
                param3 := param3 DIV 32;
815
                param3 := param3 DIV 32;
969
 
816
 
970
                FOR i := 0 TO n - 1 DO
817
                FOR i := 0 TO n - 1 DO
971
                    IF i IN BITS(param3) THEN
818
                    IF i IN BITS(param3) THEN
972
                        movsdmr(rbp, i * 8 + 16, i)
819
                        movsdmr(rbp, i * 8 + 16, i)
973
                    ELSE
820
                    ELSE
974
                        movmr(rbp, i * 8 + 16, Win64RegPar[i])
821
                        movmr(rbp, i * 8 + 16, Win64RegPar[i])
975
                    END
822
                    END
976
                END
823
                END
977
            ELSIF param3 < 0 THEN
824
            ELSIF param3 < 0 THEN
978
                param3 := -param3;
825
                param3 := -param3;
979
                n := (param3 MOD 32) * 8;
826
                n := (param3 MOD 32) * 8;
980
                param3 := param3 DIV 32;
827
                param3 := param3 DIV 32;
981
                pop(r10);
828
                pop(r11);
982
                subrc(rsp, n);
829
                subrc(rsp, n);
983
                push(r10);
830
                push(r11);
984
                push(rbp);
831
                push(rbp);
985
                mov(rbp, rsp);
832
                mov(rbp, rsp);
986
 
833
 
987
                a := 0;
834
                a := 0;
988
                b := 0;
835
                b := 0;
989
                c := 0;
836
                c := 0;
990
 
837
 
991
                INC(n, 16);
838
                INC(n, 16);
992
 
839
 
993
                FOR i := 16 TO n - 8 BY 8 DO
840
                FOR i := 16 TO n - 8 BY 8 DO
994
                    IF ODD(param3) THEN
841
                    IF ODD(param3) THEN
995
                        IF b <= 7 THEN
842
                        IF b <= 7 THEN
996
                            movsdmr(rbp, i, b);
843
                            movsdmr(rbp, i, b);
997
                            INC(b)
844
                            INC(b)
998
                        ELSE
845
                        ELSE
999
                            movrm(r10, rbp, n + c);
846
                            movrm(r11, rbp, n + c);
1000
                            movmr(rbp, i, r10);
847
                            movmr(rbp, i, r11);
1001
                            INC(c, 8)
848
                            INC(c, 8)
1002
                        END
849
                        END
1003
                    ELSE
850
                    ELSE
1004
                        IF a <= 5 THEN
851
                        IF a <= 5 THEN
1005
                            movmr(rbp, i, SystemVRegPar[a]);
852
                            movmr(rbp, i, SystemVRegPar[a]);
1006
                            INC(a)
853
                            INC(a)
1007
                        ELSE
854
                        ELSE
1008
                            movrm(r10, rbp, n + c);
855
                            movrm(r11, rbp, n + c);
1009
                            movmr(rbp, i, r10);
856
                            movmr(rbp, i, r11);
1010
                            INC(c, 8)
857
                            INC(c, 8)
1011
                        END
858
                        END
1012
                    END;
859
                    END;
1013
                    param3 := param3 DIV 2
860
                    param3 := param3 DIV 2
1014
                END
861
                END
1015
            ELSE
862
            ELSE
1016
                push(rbp);
863
                push(rbp);
1017
                mov(rbp, rsp)
864
                mov(rbp, rsp)
1018
            END;
865
            END;
1019
 
866
 
1020
            n := param2;
867
            n := param2;
1021
            IF n > 4 THEN
868
            IF n > 4 THEN
1022
                movrc(rcx, n);
869
                movrc(rcx, n);
1023
                                     (* L: *)
870
                                     (* L: *)
1024
                pushc(0);
871
                pushc(0);
1025
                OutByte2(0E2H, 0FCH) (* loop L *)
872
                OutByte2(0E2H, 0FCH) (* loop L *)
1026
            ELSE
873
            ELSE
1027
                WHILE n > 0 DO
874
                WHILE n > 0 DO
1028
                    pushc(0);
875
                    pushc(0);
1029
                    DEC(n)
876
                    DEC(n)
1030
                END
877
                END
1031
            END;
-
 
1032
 
-
 
1033
            IF cmd.allocReg THEN
-
 
1034
                allocReg(cmd)
-
 
1035
            END
878
            END
1036
 
879
 
1037
        |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
880
        |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
1038
            IF opcode = IL.opLEAVER THEN
881
            IF opcode = IL.opLEAVER THEN
1039
                UnOp(reg1);
882
                UnOp(reg1);
1040
                IF reg1 # rax THEN
883
                IF reg1 # rax THEN
1041
                    GetRegA;
884
                    mov(rax, reg1)
1042
                    ASSERT(REG.Exchange(R, reg1, rax));
-
 
1043
                    drop
-
 
1044
                END;
885
                END;
1045
                drop
886
                drop
1046
            END;
887
            END;
1047
 
888
 
1048
            ASSERT(R.top = -1);
889
            ASSERT(R.top = -1);
1049
 
890
 
1050
            IF opcode = IL.opLEAVEF THEN
891
            IF opcode = IL.opLEAVEF THEN
1051
                DEC(xmm)
892
                DEC(xmm)
1052
            END;
893
            END;
1053
 
894
 
1054
            ASSERT(xmm = -1);
895
            ASSERT(xmm = -1);
1055
 
896
 
1056
            IF param1 > 0 THEN
897
            IF param1 > 0 THEN
1057
                mov(rsp, rbp)
898
                mov(rsp, rbp)
1058
            END;
899
            END;
1059
 
900
 
1060
            pop(rbp);
901
            pop(rbp);
1061
            IF param2 > 0 THEN
902
            IF param2 > 0 THEN
1062
                OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2 *)
903
                OutByte3(0C2H, (param2 * 8) MOD 256, (param2 * 8) DIV 256) (* ret param2*8 *)
1063
            ELSE
904
            ELSE
1064
                X86.ret
905
                X86.ret
1065
            END;
906
            END
1066
            REG.Reset(R)
-
 
1067
 
907
 
1068
        |IL.opSAVES:
908
        |IL.opSAVES:
1069
            UnOp(reg1);
909
            UnOp(reg1);
1070
            REG.PushAll_1(R);
910
            REG.PushAll_1(R);
1071
            pushDA(stroffs + param2);
911
            pushDA(stroffs + param2);
1072
            push(reg1);
912
            push(reg1);
1073
            drop;
913
            drop;
1074
            pushc(param1);
914
            pushc(param1);
1075
            CallRTL(IL._move)
915
            CallRTL(IL._move)
1076
 
916
 
1077
        |IL.opSADR:
917
        |IL.opSADR:
1078
            lea(GetAnyReg(), stroffs + param2, sDATA)
918
            lea(GetAnyReg(), stroffs + param2, sDATA)
1079
 
919
 
1080
        |IL.opLOAD8:
920
        |IL.opLOAD8:
1081
            UnOp(reg1);
921
            UnOp(reg1);
1082
            movzx(reg1, reg1, 0, FALSE)
922
            movzx(reg1, reg1, 0, FALSE)
1083
 
923
 
1084
        |IL.opLOAD16:
924
        |IL.opLOAD16:
1085
            UnOp(reg1);
925
            UnOp(reg1);
1086
            movzx(reg1, reg1, 0, TRUE)
926
            movzx(reg1, reg1, 0, TRUE)
1087
 
927
 
1088
        |IL.opLOAD32:
928
        |IL.opLOAD32:
1089
            UnOp(reg1);
929
            UnOp(reg1);
1090
            movrm32(reg1, reg1, 0);
930
            movrm32(reg1, reg1, 0);
1091
            shiftrc(shl, reg1, 32);
931
            shiftrc(shl, reg1, 32);
1092
            shiftrc(shr, reg1, 32)
932
            shiftrc(shr, reg1, 32)
1093
 
933
 
1094
        |IL.opLOAD64:
934
        |IL.opLOAD64:
1095
            UnOp(reg1);
935
            UnOp(reg1);
1096
            movrm(reg1, reg1, 0)
936
            movrm(reg1, reg1, 0)
1097
 
937
 
1098
        |IL.opLLOAD64:
938
        |IL.opLLOAD64:
1099
            reg1 := GetAnyReg();
939
            reg1 := GetAnyReg();
1100
            reg2 := GetVarReg(param2);
-
 
1101
            IF reg2 # -1 THEN
-
 
1102
                mov(reg1, reg2)
-
 
1103
            ELSE
-
 
1104
                movrm(reg1, rbp, param2 * 8)
940
            movrm(reg1, rbp, param2 * 8)
1105
            END
-
 
1106
 
941
 
1107
        |IL.opLLOAD8,
942
        |IL.opLLOAD8,
1108
         IL.opLLOAD16:
943
         IL.opLLOAD16:
1109
            reg1 := GetAnyReg();
944
            reg1 := GetAnyReg();
1110
            reg2 := GetVarReg(param2);
-
 
1111
            IF reg2 # -1 THEN
-
 
1112
                mov(reg1, reg2)
-
 
1113
            ELSE
-
 
1114
                movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16)
945
            movzx(reg1, rbp, param2 * 8, opcode = IL.opLLOAD16)
1115
            END
-
 
1116
 
946
 
1117
        |IL.opLLOAD32:
947
        |IL.opLLOAD32:
1118
            reg1 := GetAnyReg();
948
            reg1 := GetAnyReg();
1119
            reg2 := GetVarReg(param2);
-
 
1120
            IF reg2 # -1 THEN
-
 
1121
                mov(reg1, reg2)
-
 
1122
            ELSE
-
 
1123
                movrm32(reg1, rbp, param2 * 8)
949
            movrm32(reg1, rbp, param2 * 8);
1124
            END;
-
 
1125
            shiftrc(shl, reg1, 32);
950
            shiftrc(shl, reg1, 32);
1126
            shiftrc(shr, reg1, 32)
951
            shiftrc(shr, reg1, 32)
1127
 
952
 
1128
        |IL.opGLOAD64:
953
        |IL.opGLOAD64:
1129
            reg1 := GetAnyReg();
954
            reg1 := GetAnyReg();
1130
            Rex(0, reg1);  (* mov reg1, qword[rip + param2 + BSS] *)
955
            Rex(0, reg1);  (* mov reg1, qword[rip + param2 + BSS] *)
1131
            OutByte2(8BH, 05H + 8 * (reg1 MOD 8));
956
            OutByte2(8BH, 05H + 8 * (reg1 MOD 8));
1132
            X86.Reloc(sBSS, param2)
957
            X86.Reloc(sBSS, param2)
1133
 
958
 
1134
        |IL.opGLOAD8, IL.opGLOAD16:
959
        |IL.opGLOAD8, IL.opGLOAD16:
1135
            reg1 := GetAnyReg();
960
            reg1 := GetAnyReg();
1136
            Rex(0, reg1);  (* movzx reg1, byte/word[rip + param2 + BSS] *)
961
            Rex(0, reg1);  (* movzx reg1, byte/word[rip + param2 + BSS] *)
1137
            OutByte3(0FH, 0B6H + ORD(opcode = IL.opGLOAD16), 05H + 8 * (reg1 MOD 8));
962
            OutByte3(0FH, 0B6H + ORD(opcode = IL.opGLOAD16), 05H + 8 * (reg1 MOD 8));
1138
            X86.Reloc(sBSS, param2)
963
            X86.Reloc(sBSS, param2)
1139
 
964
 
1140
        |IL.opGLOAD32:
965
        |IL.opGLOAD32:
1141
            reg1 := GetAnyReg();
966
            reg1 := GetAnyReg();
1142
            lea(reg1, param2, sBSS);
967
            lea(reg1, param2, sBSS);
1143
            movrm32(reg1, reg1, 0);
968
            movrm32(reg1, reg1, 0);
1144
            shiftrc(shl, reg1, 32);
969
            shiftrc(shl, reg1, 32);
1145
            shiftrc(shr, reg1, 32)
970
            shiftrc(shr, reg1, 32)
1146
 
971
 
1147
        |IL.opVLOAD64:
972
        |IL.opVLOAD64:
1148
            reg1 := GetAnyReg();
973
            reg1 := GetAnyReg();
1149
            movrm(reg1, rbp, param2 * 8);
974
            movrm(reg1, rbp, param2 * 8);
1150
            movrm(reg1, reg1, 0)
975
            movrm(reg1, reg1, 0)
1151
 
976
 
1152
        |IL.opVLOAD8,
977
        |IL.opVLOAD8,
1153
         IL.opVLOAD16:
978
         IL.opVLOAD16:
1154
            reg1 := GetAnyReg();
979
            reg1 := GetAnyReg();
1155
            movrm(reg1, rbp, param2 * 8);
980
            movrm(reg1, rbp, param2 * 8);
1156
            movzx(reg1, reg1, 0, opcode = IL.opVLOAD16)
981
            movzx(reg1, reg1, 0, opcode = IL.opVLOAD16)
1157
 
982
 
1158
        |IL.opVLOAD32:
983
        |IL.opVLOAD32:
1159
            reg1 := GetAnyReg();
984
            reg1 := GetAnyReg();
1160
            reg2 := GetAnyReg();
985
            reg2 := GetAnyReg();
1161
            movrm(reg2, rbp, param2 * 8);
986
            movrm(reg2, rbp, param2 * 8);
1162
            movrm32(reg1, reg2, 0);
987
            movrm32(reg1, reg2, 0);
1163
            shiftrc(shl, reg1, 32);
988
            shiftrc(shl, reg1, 32);
1164
            shiftrc(shr, reg1, 32);
989
            shiftrc(shr, reg1, 32);
1165
            drop
990
            drop
1166
 
991
 
1167
        |IL.opLADR:
992
        |IL.opLADR:
1168
            n := param2 * 8;
993
            n := param2 * 8;
1169
            next := cmd.next(COMMAND);
994
            next := cmd.next(COMMAND);
1170
            IF (next.opcode = IL.opSAVEF) OR (next.opcode = IL.opSAVEFI) THEN
995
            IF (next.opcode = IL.opSAVEF) OR (next.opcode = IL.opSAVEFI) THEN
1171
                ASSERT(xmm >= 0);
996
                ASSERT(xmm >= 0);
1172
                movsdmr(rbp, n, xmm);
997
                movsdmr(rbp, n, xmm);
1173
                DEC(xmm);
998
                DEC(xmm);
1174
                cmd := next
999
                cmd := next
1175
            ELSIF next.opcode = IL.opLOADF THEN
1000
            ELSIF next.opcode = IL.opLOADF THEN
1176
                INC(xmm);
1001
                INC(xmm);
1177
                IF xmm > MAX_XMM THEN
1002
                IF xmm > MAX_XMM THEN
1178
                    ERRORS.ErrorMsg(fname, next.param1, next.param2, FPR_ERR)
1003
                    ERRORS.ErrorMsg(fname, next.param1, next.param2, FPR_ERR)
1179
                END;
1004
                END;
1180
                movsdrm(xmm, rbp, n);
1005
                movsdrm(xmm, rbp, n);
1181
                cmd := next
1006
                cmd := next
1182
            ELSE
1007
            ELSE
1183
                IF (next.opcode = IL.opADDC) & ~isLong(n + next.param2) THEN
1008
                IF (next.opcode = IL.opADDC) & ~isLong(n + next.param2) THEN
1184
                    INC(n, next.param2);
1009
                    INC(n, next.param2);
1185
                    cmd := next
1010
                    cmd := next
1186
                END;
1011
                END;
1187
                reg1 := GetAnyReg();
1012
                reg1 := GetAnyReg();
1188
                Rex(0, reg1);
1013
                Rex(0, reg1);
1189
                OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); (* lea reg1, qword[rbp+n] *)
1014
                OutByte2(8DH, 45H + long(n) + (reg1 MOD 8) * 8); (* lea reg1, qword[rbp+n] *)
1190
                OutIntByte(n)
1015
                OutIntByte(n)
1191
            END
1016
            END
1192
 
1017
 
1193
        |IL.opGADR:
1018
        |IL.opGADR:
1194
            next := cmd.next(COMMAND);
1019
            next := cmd.next(COMMAND);
1195
            IF (next.opcode = IL.opADDC) & ~isLong(param2 + next.param2) THEN
1020
            IF (next.opcode = IL.opADDC) & ~isLong(param2 + next.param2) THEN
1196
                INC(param2, next.param2);
1021
                INC(param2, next.param2);
1197
                cmd := next
1022
                cmd := next
1198
            END;
1023
            END;
1199
            lea(GetAnyReg(), param2, sBSS)
1024
            lea(GetAnyReg(), param2, sBSS)
1200
 
1025
 
1201
        |IL.opVADR:
1026
        |IL.opVADR:
1202
            movrm(GetAnyReg(), rbp, param2 * 8)
1027
            movrm(GetAnyReg(), rbp, param2 * 8)
1203
 
1028
 
1204
        |IL.opSAVE8C:
1029
        |IL.opSAVE8C:
1205
            UnOp(reg1);
1030
            UnOp(reg1);
1206
            IF reg1 >= 8 THEN
1031
            IF reg1 >= 8 THEN
1207
                OutByte(41H)
1032
                OutByte(41H)
1208
            END;
1033
            END;
1209
            OutByte3(0C6H, reg1 MOD 8, param2); (* mov byte[reg1], param2 *)
1034
            OutByte3(0C6H, reg1 MOD 8, param2); (* mov byte[reg1], param2 *)
1210
            drop
1035
            drop
1211
 
1036
 
1212
        |IL.opSAVE16C:
1037
        |IL.opSAVE16C:
1213
            UnOp(reg1);
1038
            UnOp(reg1);
1214
            OutByte(66H);
1039
            OutByte(66H);
1215
            IF reg1 >= 8 THEN
1040
            IF reg1 >= 8 THEN
1216
                OutByte(41H)
1041
                OutByte(41H)
1217
            END;
1042
            END;
1218
            OutByte2(0C7H, reg1 MOD 8);
1043
            OutByte2(0C7H, reg1 MOD 8);
1219
            OutByte2(param2 MOD 256, param2 DIV 256); (* mov word[reg1], param2 *)
1044
            OutByte2(param2 MOD 256, param2 DIV 256); (* mov word[reg1], param2 *)
1220
            drop
1045
            drop
1221
 
1046
 
1222
        |IL.opSAVEC:
1047
        |IL.opSAVEC:
1223
            UnOp(reg1);
1048
            UnOp(reg1);
1224
            IF isLong(param2) THEN
1049
            IF isLong(param2) THEN
1225
                reg2 := GetAnyReg();
1050
                reg2 := GetAnyReg();
1226
                movrc(reg2, param2);
1051
                movrc(reg2, param2);
1227
                movmr(reg1, 0, reg2);
1052
                movmr(reg1, 0, reg2);
1228
                drop
1053
                drop
1229
            ELSE
1054
            ELSE
1230
                Rex(reg1, 0);
1055
                Rex(reg1, 0);
1231
                OutByte2(0C7H, reg1 MOD 8); (* mov qword[reg1], param2 *)
1056
                OutByte2(0C7H, reg1 MOD 8); (* mov qword[reg1], param2 *)
1232
                OutInt(param2)
1057
                OutInt(param2)
1233
            END;
1058
            END;
1234
            drop
1059
            drop
1235
 
1060
 
1236
        |IL.opRSET:
1061
        |IL.opRSET:
1237
            PushAll(2);
1062
            PushAll(2);
1238
            CallRTL(IL._set);
1063
            CallRTL(IL._set);
1239
            GetRegA
1064
            GetRegA
1240
 
1065
 
1241
        |IL.opRSETR:
1066
        |IL.opRSETR:
1242
            PushAll(1);
1067
            PushAll(1);
1243
            pushc(param2);
1068
            pushc(param2);
1244
            CallRTL(IL._set);
1069
            CallRTL(IL._set);
1245
            GetRegA
1070
            GetRegA
1246
 
1071
 
1247
        |IL.opRSETL:
1072
        |IL.opRSETL:
1248
            UnOp(reg1);
1073
            UnOp(reg1);
1249
            REG.PushAll_1(R);
1074
            REG.PushAll_1(R);
1250
            pushc(param2);
1075
            pushc(param2);
1251
            push(reg1);
1076
            push(reg1);
1252
            drop;
1077
            drop;
1253
            CallRTL(IL._set);
1078
            CallRTL(IL._set);
1254
            GetRegA
1079
            GetRegA
1255
 
1080
 
1256
        |IL.opRSET1:
1081
        |IL.opRSET1:
1257
            PushAll(1);
1082
            PushAll(1);
1258
            CallRTL(IL._set1);
1083
            CallRTL(IL._set1);
1259
            GetRegA
1084
            GetRegA
1260
 
1085
 
1261
        |IL.opINCL, IL.opEXCL:
1086
        |IL.opINCL, IL.opEXCL:
1262
            BinOp(reg1, reg2);
1087
            BinOp(reg1, reg2);
1263
            cmprc(reg1, 64);
1088
            cmprc(reg1, 64);
1264
            OutByte2(73H, 04H); (* jnb L *)
1089
            OutByte2(73H, 04H); (* jnb L *)
1265
            Rex(reg2, reg1);
1090
            Rex(reg2, reg1);
1266
            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); (* bts/btr qword[reg2], reg1 *)
1091
            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opEXCL), 8 * (reg1 MOD 8) + reg2 MOD 8); (* bts/btr qword[reg2], reg1 *)
1267
            (* L: *)
1092
            (* L: *)
1268
            drop;
1093
            drop;
1269
            drop
1094
            drop
1270
 
1095
 
1271
        |IL.opINCLC, IL.opEXCLC:
1096
        |IL.opINCLC, IL.opEXCLC:
1272
            UnOp(reg1);
1097
            UnOp(reg1);
1273
            Rex(reg1, 0);
1098
            Rex(reg1, 0);
1274
            OutByte2(0FH, 0BAH); (* bts/btr qword[reg1], param2 *)
1099
            OutByte2(0FH, 0BAH); (* bts/btr qword[reg1], param2 *)
1275
            OutByte2(28H + 8 * ORD(opcode = IL.opEXCLC) + reg1 MOD 8, param2);
1100
            OutByte2(28H + 8 * ORD(opcode = IL.opEXCLC) + reg1 MOD 8, param2);
1276
            drop
1101
            drop
1277
 
1102
 
1278
        |IL.opEQS .. IL.opGES:
1103
        |IL.opEQS .. IL.opGES:
1279
            PushAll(4);
1104
            PushAll(4);
1280
            pushc(opcode - IL.opEQS);
1105
            pushc(opcode - IL.opEQS);
1281
            CallRTL(IL._strcmp);
1106
            CallRTL(IL._strcmp);
1282
            GetRegA
1107
            GetRegA
1283
 
1108
 
1284
        |IL.opEQSW .. IL.opGESW:
1109
        |IL.opEQSW .. IL.opGESW:
1285
            PushAll(4);
1110
            PushAll(4);
1286
            pushc(opcode - IL.opEQSW);
1111
            pushc(opcode - IL.opEQSW);
1287
            CallRTL(IL._strcmpw);
1112
            CallRTL(IL._strcmpw);
1288
            GetRegA
1113
            GetRegA
1289
 
1114
 
1290
        |IL.opCONST:
1115
        |IL.opCONST:
1291
            movrc(GetAnyReg(), param2)
1116
            movrc(GetAnyReg(), param2)
1292
 
1117
 
1293
        |IL.opEQ..IL.opGE,
1118
        |IL.opEQ..IL.opGE,
1294
         IL.opEQC..IL.opGEC:
1119
         IL.opEQC..IL.opGEC:
1295
 
1120
 
1296
            IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
1121
            IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
1297
                BinOp(reg1, reg2);
1122
                BinOp(reg1, reg2);
1298
                cmprr(reg1, reg2);
1123
                cmprr(reg1, reg2);
1299
                drop
1124
                drop
1300
            ELSE
1125
            ELSE
1301
                UnOp(reg1);
1126
                UnOp(reg1);
1302
                cmprc(reg1, param2)
1127
                cmprc(reg1, param2)
1303
            END;
1128
            END;
1304
 
1129
 
1305
            drop;
1130
            drop;
1306
            cc := X86.cond(opcode);
1131
            cc := X86.cond(opcode);
1307
 
1132
 
1308
            next := cmd.next(COMMAND);
1133
            next := cmd.next(COMMAND);
1309
            IF next.opcode = IL.opJNZ THEN
1134
            IF next.opcode = IL.opJNZ THEN
1310
                jcc(cc, next.param1);
1135
                jcc(cc, next.param1);
1311
                cmd := next
1136
                cmd := next
1312
            ELSIF next.opcode = IL.opJZ THEN
1137
            ELSIF next.opcode = IL.opJZ THEN
1313
                jcc(X86.inv0(cc), next.param1);
1138
                jcc(X86.inv0(cc), next.param1);
1314
                cmd := next
1139
                cmd := next
1315
            ELSE
1140
            ELSE
1316
                reg1 := GetAnyReg();
1141
                reg1 := GetAnyReg();
1317
                X86.setcc(cc + 16, reg1);
1142
                X86.setcc(cc + 16, reg1);
1318
                andrc(reg1, 1)
1143
                andrc(reg1, 1)
1319
            END
1144
            END
1320
 
1145
 
1321
        |IL.opCODE:
1146
        |IL.opCODE:
1322
            OutByte(param2)
1147
            OutByte(param2)
1323
 
1148
 
1324
        |IL.opPUSHIP:
1149
        |IL.opPUSHIP:
1325
            reg1 := GetAnyReg();
1150
            reg1 := GetAnyReg();
1326
            lea(reg1, param2, sIMP);
1151
            lea(reg1, param2, sIMP);
1327
            movrm(reg1, reg1, 0)
1152
            movrm(reg1, reg1, 0)
1328
 
1153
 
1329
        |IL.opPARAM:
1154
        |IL.opPARAM:
1330
            n := param2;
1155
            n := param2;
1331
            IF n = 1 THEN
1156
            IF n = 1 THEN
1332
                UnOp(reg1);
1157
                UnOp(reg1);
1333
                push(reg1);
1158
                push(reg1);
1334
                drop
1159
                drop
1335
            ELSE
1160
            ELSE
1336
                ASSERT(R.top + 1 <= n);
1161
                ASSERT(R.top + 1 <= n);
1337
                PushAll(n)
1162
                PushAll(n)
1338
            END
1163
            END
1339
 
1164
 
1340
        |IL.opJNZ1:
1165
        |IL.opJNZ1:
1341
            UnOp(reg1);
1166
            UnOp(reg1);
1342
            test(reg1);
1167
            test(reg1);
1343
            jcc(jne, param1)
1168
            jcc(jne, param1)
1344
 
1169
 
1345
        |IL.opJG:
1170
        |IL.opJG:
1346
            UnOp(reg1);
1171
            UnOp(reg1);
1347
            test(reg1);
1172
            test(reg1);
1348
            jcc(jg, param1)
1173
            jcc(jg, param1)
1349
 
1174
 
1350
        |IL.opJNZ:
1175
        |IL.opJNZ:
1351
            UnOp(reg1);
1176
            UnOp(reg1);
1352
            test(reg1);
1177
            test(reg1);
1353
            jcc(jne, param1);
1178
            jcc(jne, param1);
1354
            drop
1179
            drop
1355
 
1180
 
1356
        |IL.opJZ:
1181
        |IL.opJZ:
1357
            UnOp(reg1);
1182
            UnOp(reg1);
1358
            test(reg1);
1183
            test(reg1);
1359
            jcc(je, param1);
1184
            jcc(je, param1);
1360
            drop
1185
            drop
1361
 
1186
 
1362
        |IL.opIN, IL.opINR:
1187
        |IL.opIN, IL.opINR:
1363
            IF opcode = IL.opINR THEN
1188
            IF opcode = IL.opINR THEN
1364
                reg2 := GetAnyReg();
1189
                reg2 := GetAnyReg();
1365
                movrc(reg2, param2)
1190
                movrc(reg2, param2)
1366
            END;
1191
            END;
1367
            label := NewLabel();
1192
            label := NewLabel();
1368
            L := NewLabel();
1193
            L := NewLabel();
1369
            BinOp(reg1, reg2);
1194
            BinOp(reg1, reg2);
1370
            cmprc(reg1, 64);
1195
            cmprc(reg1, 64);
1371
            jcc(jb, L);
1196
            jcc(jb, L);
1372
            xor(reg1, reg1);
1197
            xor(reg1, reg1);
1373
            X86.jmp(label);
1198
            X86.jmp(label);
1374
            X86.SetLabel(L);
1199
            X86.SetLabel(L);
1375
            Rex(reg2, reg1);
1200
            Rex(reg2, reg1);
1376
            OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); (* bt reg2, reg1 *)
1201
            OutByte3(0FH, 0A3H, 0C0H + 8 * (reg1 MOD 8) + reg2 MOD 8); (* bt reg2, reg1 *)
1377
            X86.setcc(setc, reg1);
1202
            X86.setcc(setc, reg1);
1378
            andrc(reg1, 1);
1203
            andrc(reg1, 1);
1379
            X86.SetLabel(label);
1204
            X86.SetLabel(label);
1380
            drop
1205
            drop
1381
 
1206
 
1382
        |IL.opINL:
1207
        |IL.opINL:
1383
            UnOp(reg1);
1208
            UnOp(reg1);
1384
            Rex(reg1, 0);
1209
            Rex(reg1, 0);
1385
            OutByte2(0FH, 0BAH); (* bt reg1, param2 *)
1210
            OutByte2(0FH, 0BAH); (* bt reg1, param2 *)
1386
            OutByte2(0E0H + reg1 MOD 8, param2);
1211
            OutByte2(0E0H + reg1 MOD 8, param2);
1387
            X86.setcc(setc, reg1);
1212
            X86.setcc(setc, reg1);
1388
            andrc(reg1, 1)
1213
            andrc(reg1, 1)
1389
 
1214
 
1390
        |IL.opNOT:
1215
        |IL.opNOT:
1391
            UnOp(reg1);
1216
            UnOp(reg1);
1392
            test(reg1);
1217
            test(reg1);
1393
            X86.setcc(sete, reg1);
1218
            X86.setcc(sete, reg1);
1394
            andrc(reg1, 1)
1219
            andrc(reg1, 1)
1395
 
1220
 
1396
        |IL.opORD:
1221
        |IL.opORD:
1397
            UnOp(reg1);
1222
            UnOp(reg1);
1398
            test(reg1);
1223
            test(reg1);
1399
            X86.setcc(setne, reg1);
1224
            X86.setcc(setne, reg1);
1400
            andrc(reg1, 1)
1225
            andrc(reg1, 1)
1401
 
1226
 
1402
        |IL.opABS:
1227
        |IL.opABS:
1403
            UnOp(reg1);
1228
            UnOp(reg1);
1404
            test(reg1);
1229
            test(reg1);
1405
            OutByte2(7DH, 03H); (* jge L *)
1230
            OutByte2(7DH, 03H); (* jge L *)
1406
            neg(reg1)
1231
            neg(reg1)
1407
            (* L: *)
1232
            (* L: *)
1408
 
1233
 
1409
        |IL.opEQB, IL.opNEB:
1234
        |IL.opEQB, IL.opNEB:
1410
            BinOp(reg1, reg2);
1235
            BinOp(reg1, reg2);
1411
            drop;
1236
            drop;
1412
            test(reg1);
1237
            test(reg1);
1413
            label := NewLabel();
1238
            label := NewLabel();
1414
            jcc(je, label);
1239
            jcc(je, label);
1415
            movrc(reg1, 1);
1240
            movrc(reg1, 1);
1416
            X86.SetLabel(label);
1241
            X86.SetLabel(label);
1417
            test(reg2);
1242
            test(reg2);
1418
            label := NewLabel();
1243
            label := NewLabel();
1419
            jcc(je, label);
1244
            jcc(je, label);
1420
            movrc(reg2, 1);
1245
            movrc(reg2, 1);
1421
            X86.SetLabel(label);
1246
            X86.SetLabel(label);
1422
            cmprr(reg1, reg2);
1247
            cmprr(reg1, reg2);
1423
            IF opcode = IL.opEQB THEN
1248
            IF opcode = IL.opEQB THEN
1424
                X86.setcc(sete, reg1)
1249
                X86.setcc(sete, reg1)
1425
            ELSE
1250
            ELSE
1426
                X86.setcc(setne, reg1)
1251
                X86.setcc(setne, reg1)
1427
            END;
1252
            END;
1428
            andrc(reg1, 1)
1253
            andrc(reg1, 1)
1429
 
1254
 
1430
        |IL.opMULSC:
1255
        |IL.opMULSC:
1431
            UnOp(reg1);
1256
            UnOp(reg1);
1432
            andrc(reg1, param2)
1257
            andrc(reg1, param2)
1433
 
1258
 
1434
        |IL.opDIVSC:
1259
        |IL.opDIVSC:
1435
            UnOp(reg1);
1260
            UnOp(reg1);
1436
            xorrc(reg1, param2)
1261
            xorrc(reg1, param2)
1437
 
1262
 
1438
        |IL.opADDSC:
1263
        |IL.opADDSC:
1439
            UnOp(reg1);
1264
            UnOp(reg1);
1440
            orrc(reg1, param2)
1265
            orrc(reg1, param2)
1441
 
1266
 
1442
        |IL.opSUBSL:
1267
        |IL.opSUBSL:
1443
            UnOp(reg1);
1268
            UnOp(reg1);
1444
            not(reg1);
1269
            not(reg1);
1445
            andrc(reg1, param2)
1270
            andrc(reg1, param2)
1446
 
1271
 
1447
        |IL.opSUBSR:
1272
        |IL.opSUBSR:
1448
            UnOp(reg1);
1273
            UnOp(reg1);
1449
            andrc(reg1, ORD(-BITS(param2)))
1274
            andrc(reg1, ORD(-BITS(param2)))
1450
 
1275
 
1451
        |IL.opMULS:
1276
        |IL.opMULS:
1452
            BinOp(reg1, reg2);
1277
            BinOp(reg1, reg2);
1453
            and(reg1, reg2);
1278
            and(reg1, reg2);
1454
            drop
1279
            drop
1455
 
1280
 
1456
        |IL.opDIVS:
1281
        |IL.opDIVS:
1457
            BinOp(reg1, reg2);
1282
            BinOp(reg1, reg2);
1458
            xor(reg1, reg2);
1283
            xor(reg1, reg2);
1459
            drop
1284
            drop
1460
 
1285
 
1461
        |IL.opUMINS:
1286
        |IL.opUMINS:
1462
            UnOp(reg1);
1287
            UnOp(reg1);
1463
            not(reg1)
1288
            not(reg1)
1464
 
1289
 
1465
        |IL.opCOPY:
1290
        |IL.opCOPY:
1466
            PushAll(2);
1291
            PushAll(2);
1467
            pushc(param2);
1292
            pushc(param2);
1468
            CallRTL(IL._move)
1293
            CallRTL(IL._move)
1469
 
1294
 
1470
        |IL.opMOVE:
1295
        |IL.opMOVE:
1471
            PushAll(3);
1296
            PushAll(3);
1472
            CallRTL(IL._move)
1297
            CallRTL(IL._move)
1473
 
1298
 
1474
        |IL.opCOPYA:
1299
        |IL.opCOPYA:
1475
            PushAll(4);
1300
            PushAll(4);
1476
            pushc(param2);
1301
            pushc(param2);
1477
            CallRTL(IL._arrcpy);
1302
            CallRTL(IL._arrcpy);
1478
            GetRegA
1303
            GetRegA
1479
 
1304
 
1480
        |IL.opCOPYS:
1305
        |IL.opCOPYS:
1481
            PushAll(4);
1306
            PushAll(4);
1482
            pushc(param2);
1307
            pushc(param2);
1483
            CallRTL(IL._strcpy)
1308
            CallRTL(IL._strcpy)
1484
 
1309
 
1485
        |IL.opROT:
1310
        |IL.opROT:
1486
            PushAll(0);
1311
            PushAll(0);
1487
            push(rsp);
1312
            push(rsp);
1488
            pushc(param2);
1313
            pushc(param2);
1489
            CallRTL(IL._rot)
1314
            CallRTL(IL._rot)
1490
 
1315
 
1491
        |IL.opNEW:
1316
        |IL.opNEW:
1492
            PushAll(1);
1317
            PushAll(1);
1493
            n := param2 + 16;
1318
            n := param2 + 8;
1494
            ASSERT(UTILS.Align(n, 64));
1319
            ASSERT(UTILS.Align(n, 8));
1495
            pushc(n);
1320
            pushc(n);
1496
            pushc(param1);
1321
            pushc(param1);
1497
            CallRTL(IL._new)
1322
            CallRTL(IL._new)
1498
 
1323
 
1499
        |IL.opDISP:
1324
        |IL.opDISP:
1500
            PushAll(1);
1325
            PushAll(1);
1501
            CallRTL(IL._dispose)
1326
            CallRTL(IL._dispose)
1502
 
1327
 
1503
        |IL.opPUSHT:
1328
        |IL.opPUSHT:
1504
            UnOp(reg1);
1329
            UnOp(reg1);
1505
            reg2 := GetAnyReg();
-
 
1506
            movrm(reg2, reg1, -8)
1330
            movrm(GetAnyReg(), reg1, -8)
1507
 
1331
 
1508
        |IL.opISREC:
1332
        |IL.opISREC:
1509
            PushAll(2);
1333
            PushAll(2);
1510
            pushc(param2 * tcount);
1334
            pushc(param2 * tcount);
1511
            CallRTL(IL._isrec);
1335
            CallRTL(IL._isrec);
1512
            GetRegA
1336
            GetRegA
1513
 
1337
 
1514
        |IL.opIS:
1338
        |IL.opIS:
1515
            PushAll(1);
1339
            PushAll(1);
1516
            pushc(param2 * tcount);
1340
            pushc(param2 * tcount);
1517
            CallRTL(IL._is);
1341
            CallRTL(IL._is);
1518
            GetRegA
1342
            GetRegA
1519
 
1343
 
1520
        |IL.opTYPEGR:
1344
        |IL.opTYPEGR:
1521
            PushAll(1);
1345
            PushAll(1);
1522
            pushc(param2 * tcount);
1346
            pushc(param2 * tcount);
1523
            CallRTL(IL._guardrec);
1347
            CallRTL(IL._guardrec);
1524
            GetRegA
1348
            GetRegA
1525
 
1349
 
1526
        |IL.opTYPEGP:
1350
        |IL.opTYPEGP:
1527
            UnOp(reg1);
1351
            UnOp(reg1);
1528
            PushAll(0);
1352
            PushAll(0);
1529
            push(reg1);
1353
            push(reg1);
1530
            pushc(param2 * tcount);
1354
            pushc(param2 * tcount);
1531
            CallRTL(IL._guard);
1355
            CallRTL(IL._guard);
1532
            GetRegA
1356
            GetRegA
1533
 
1357
 
1534
        |IL.opTYPEGD:
1358
        |IL.opTYPEGD:
1535
            UnOp(reg1);
1359
            UnOp(reg1);
1536
            PushAll(0);
1360
            PushAll(0);
1537
            X86.pushm(reg1, -8);
1361
            X86.pushm(reg1, -8);
1538
            pushc(param2 * tcount);
1362
            pushc(param2 * tcount);
1539
            CallRTL(IL._guardrec);
1363
            CallRTL(IL._guardrec);
1540
            GetRegA
1364
            GetRegA
1541
 
1365
 
1542
        |IL.opCASET:
1366
        |IL.opCASET:
1543
            push(r10);
1367
            push(rcx);
1544
            push(r10);
1368
            push(rcx);
1545
            pushc(param2 * tcount);
1369
            pushc(param2 * tcount);
1546
            CallRTL(IL._guardrec);
1370
            CallRTL(IL._guardrec);
1547
            pop(r10);
1371
            pop(rcx);
1548
            test(rax);
1372
            test(rax);
1549
            jcc(jne, param1)
1373
            jcc(jne, param1)
1550
 
1374
 
1551
        |IL.opSAVEP:
1375
        |IL.opSAVEP:
1552
            UnOp(reg1);
1376
            UnOp(reg1);
1553
            reg2 := GetAnyReg();
1377
            reg2 := GetAnyReg();
1554
            lea(reg2, param2, sCODE);
1378
            lea(reg2, param2, sCODE);
1555
            movmr(reg1, 0, reg2);
1379
            movmr(reg1, 0, reg2);
1556
            drop;
1380
            drop;
1557
            drop
1381
            drop
1558
 
1382
 
1559
        |IL.opPUSHP:
1383
        |IL.opPUSHP:
1560
            lea(GetAnyReg(), param2, sCODE)
1384
            lea(GetAnyReg(), param2, sCODE)
1561
 
1385
 
1562
        |IL.opINC, IL.opDEC:
1386
        |IL.opINC, IL.opDEC:
1563
            BinOp(reg1, reg2);
1387
            BinOp(reg1, reg2);
1564
            (* add/sub qword[reg2], reg1 *)
1388
            (* add/sub qword[reg2], reg1 *)
1565
            Rex(reg2, reg1);
1389
            Rex(reg2, reg1);
1566
            OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8);
1390
            OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8);
1567
            drop;
1391
            drop;
1568
            drop
1392
            drop
1569
 
1393
 
1570
        |IL.opINCC:
1394
        |IL.opINCC:
1571
            UnOp(reg1);
1395
            UnOp(reg1);
1572
            IF isLong(param2) THEN
1396
            IF isLong(param2) THEN
1573
                reg2 := GetAnyReg();
1397
                reg2 := GetAnyReg();
1574
                movrc(reg2, param2);
1398
                movrc(reg2, param2);
1575
                (* add qword[reg1], reg2 *)
1399
                (* add qword[reg1], reg2 *)
1576
                Rex(reg1, reg2);
1400
                Rex(reg1, reg2);
1577
                OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8);
1401
                OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8);
1578
                drop
1402
                drop
1579
            ELSIF ABS(param2) = 1 THEN
1403
            ELSIF ABS(param2) = 1 THEN
1580
                Rex(reg1, 0);
1404
                Rex(reg1, 0);
1581
                OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) (* inc/dec qword[reg1] *)
1405
                OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) (* inc/dec qword[reg1] *)
1582
            ELSE
1406
            ELSE
1583
                (* add qword[reg1], param2 *)
1407
                (* add qword[reg1], param2 *)
1584
                Rex(reg1, 0);
1408
                Rex(reg1, 0);
1585
                OutByte2(81H + short(param2), reg1 MOD 8);
1409
                OutByte2(81H + short(param2), reg1 MOD 8);
1586
                OutIntByte(param2)
1410
                OutIntByte(param2)
1587
            END;
1411
            END;
1588
            drop
1412
            drop
1589
 
1413
 
1590
        |IL.opDROP:
1414
        |IL.opDROP:
1591
            UnOp(reg1);
1415
            UnOp(reg1);
1592
            drop
1416
            drop
1593
 
1417
 
1594
        |IL.opSAVE, IL.opSAVE64:
1418
        |IL.opSAVE, IL.opSAVE64:
1595
            BinOp(reg2, reg1);
1419
            BinOp(reg2, reg1);
1596
            movmr(reg1, 0, reg2);
1420
            movmr(reg1, 0, reg2);
1597
            drop;
1421
            drop;
1598
            drop
1422
            drop
1599
 
1423
 
1600
        |IL.opSAVE8:
1424
        |IL.opSAVE8:
1601
            BinOp(reg2, reg1);
1425
            BinOp(reg2, reg1);
1602
            X86.movmr8(reg1, 0, reg2);
1426
            X86.movmr8(reg1, 0, reg2);
1603
            drop;
1427
            drop;
1604
            drop
1428
            drop
1605
 
1429
 
1606
        |IL.opSAVE16:
1430
        |IL.opSAVE16:
1607
            BinOp(reg2, reg1);
1431
            BinOp(reg2, reg1);
1608
            X86.movmr16(reg1, 0, reg2);
1432
            X86.movmr16(reg1, 0, reg2);
1609
            drop;
1433
            drop;
1610
            drop
1434
            drop
1611
 
1435
 
1612
        |IL.opSAVE32:
1436
        |IL.opSAVE32:
1613
            BinOp(reg2, reg1);
1437
            BinOp(reg2, reg1);
1614
            movmr32(reg1, 0, reg2);
1438
            movmr32(reg1, 0, reg2);
1615
            drop;
1439
            drop;
1616
            drop
1440
            drop
1617
 
1441
 
1618
        |IL.opMAX, IL.opMIN:
1442
        |IL.opMAX, IL.opMIN:
1619
            BinOp(reg1, reg2);
1443
            BinOp(reg1, reg2);
1620
            cmprr(reg1, reg2);
1444
            cmprr(reg1, reg2);
1621
            OutByte2(7DH + ORD(opcode = IL.opMIN), 3); (* jge/jle L *)
1445
            OutByte2(7DH + ORD(opcode = IL.opMIN), 3); (* jge/jle L *)
1622
            mov(reg1, reg2);
1446
            mov(reg1, reg2);
1623
            (* L: *)
1447
            (* L: *)
1624
            drop
1448
            drop
1625
 
1449
 
1626
        |IL.opMAXC, IL.opMINC:
1450
        |IL.opMAXC, IL.opMINC:
1627
            UnOp(reg1);
1451
            UnOp(reg1);
1628
            cmprc(reg1, param2);
1452
            cmprc(reg1, param2);
1629
            label := NewLabel();
1453
            label := NewLabel();
1630
            IF opcode = IL.opMINC THEN
1454
            IF opcode = IL.opMINC THEN
1631
                cc := jle
1455
                cc := jle
1632
            ELSE
1456
            ELSE
1633
                cc := jge
1457
                cc := jge
1634
            END;
1458
            END;
1635
            jcc(cc, label);
1459
            jcc(cc, label);
1636
            movrc(reg1, param2);
1460
            movrc(reg1, param2);
1637
            X86.SetLabel(label)
1461
            X86.SetLabel(label)
1638
 
1462
 
1639
        |IL.opSBOOL:
1463
        |IL.opSBOOL:
1640
            BinOp(reg2, reg1);
1464
            BinOp(reg2, reg1);
1641
            test(reg2);
1465
            test(reg2);
1642
            IF reg1 >= 8 THEN
1466
            IF reg1 >= 8 THEN
1643
                OutByte(41H)
1467
                OutByte(41H)
1644
            END;
1468
            END;
1645
            OutByte3(0FH, 95H, reg1 MOD 8); (* setne byte[reg1] *)
1469
            OutByte3(0FH, 95H, reg1 MOD 8); (* setne byte[reg1] *)
1646
            drop;
1470
            drop;
1647
            drop
1471
            drop
1648
 
1472
 
1649
        |IL.opSBOOLC:
1473
        |IL.opSBOOLC:
1650
            UnOp(reg1);
1474
            UnOp(reg1);
1651
            IF reg1 >= 8 THEN
1475
            IF reg1 >= 8 THEN
1652
                OutByte(41H)
1476
                OutByte(41H)
1653
            END;
1477
            END;
1654
            OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *)
1478
            OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *)
1655
            drop
1479
            drop
1656
 
1480
 
1657
        |IL.opUMINUS:
1481
        |IL.opUMINUS:
1658
            UnOp(reg1);
1482
            UnOp(reg1);
1659
            neg(reg1)
1483
            neg(reg1)
1660
 
1484
 
1661
        |IL.opADD:
1485
        |IL.opADD:
1662
            BinOp(reg1, reg2);
1486
            BinOp(reg1, reg2);
1663
            add(reg1, reg2);
1487
            add(reg1, reg2);
1664
            drop
1488
            drop
1665
 
1489
 
1666
        |IL.opSUB:
1490
        |IL.opSUB:
1667
            BinOp(reg1, reg2);
1491
            BinOp(reg1, reg2);
1668
            sub(reg1, reg2);
1492
            sub(reg1, reg2);
1669
            drop
1493
            drop
1670
 
1494
 
1671
        |IL.opSUBR, IL.opSUBL:
1495
        |IL.opSUBR, IL.opSUBL:
1672
            UnOp(reg1);
1496
            UnOp(reg1);
1673
            IF param2 = 1 THEN
1497
            IF param2 = 1 THEN
1674
                decr(reg1)
1498
                decr(reg1)
1675
            ELSIF param2 = -1 THEN
1499
            ELSIF param2 = -1 THEN
1676
                incr(reg1)
1500
                incr(reg1)
1677
            ELSIF param2 # 0 THEN
1501
            ELSIF param2 # 0 THEN
1678
                subrc(reg1, param2)
1502
                subrc(reg1, param2)
1679
            END;
1503
            END;
1680
            IF opcode = IL.opSUBL THEN
1504
            IF opcode = IL.opSUBL THEN
1681
                neg(reg1)
1505
                neg(reg1)
1682
            END
1506
            END
1683
 
1507
 
1684
        |IL.opADDC:
1508
        |IL.opADDC:
1685
            IF (param2 # 0) & ~isLong(param2) THEN
1509
            IF (param2 # 0) & ~isLong(param2) THEN
1686
                UnOp(reg1);
1510
                UnOp(reg1);
1687
                next := cmd.next(COMMAND);
1511
                next := cmd.next(COMMAND);
1688
                CASE next.opcode OF
1512
                CASE next.opcode OF
1689
                |IL.opLOAD64:
1513
                |IL.opLOAD64:
1690
                    movrm(reg1, reg1, param2);
1514
                    movrm(reg1, reg1, param2);
1691
                    cmd := next
1515
                    cmd := next
1692
                |IL.opLOAD32:
1516
                |IL.opLOAD32:
1693
                    movrm32(reg1, reg1, param2);
1517
                    movrm32(reg1, reg1, param2);
1694
                    shiftrc(shl, reg1, 32);
1518
                    shiftrc(shl, reg1, 32);
1695
                    shiftrc(shr, reg1, 32);
1519
                    shiftrc(shr, reg1, 32);
1696
                    cmd := next
1520
                    cmd := next
1697
                |IL.opLOAD16:
1521
                |IL.opLOAD16:
1698
                    movzx(reg1, reg1, param2, TRUE);
1522
                    movzx(reg1, reg1, param2, TRUE);
1699
                    cmd := next
1523
                    cmd := next
1700
                |IL.opLOAD8:
1524
                |IL.opLOAD8:
1701
                    movzx(reg1, reg1, param2, FALSE);
1525
                    movzx(reg1, reg1, param2, FALSE);
1702
                    cmd := next
1526
                    cmd := next
1703
                |IL.opLOAD64_PARAM:
1527
                |IL.opLOAD64_PARAM:
1704
                    X86.pushm(reg1, param2);
1528
                    X86.pushm(reg1, param2);
1705
                    drop;
1529
                    drop;
1706
                    cmd := next
1530
                    cmd := next
1707
                ELSE
1531
                ELSE
1708
                    IF param2 = 1 THEN
1532
                    IF param2 = 1 THEN
1709
                        incr(reg1)
1533
                        incr(reg1)
1710
                    ELSIF param2 = -1 THEN
1534
                    ELSIF param2 = -1 THEN
1711
                        decr(reg1)
1535
                        decr(reg1)
1712
                    ELSE
1536
                    ELSE
1713
                        addrc(reg1, param2)
1537
                        addrc(reg1, param2)
1714
                    END
1538
                    END
1715
                END
1539
                END
1716
            ELSIF isLong(param2) THEN
1540
            ELSIF isLong(param2) THEN
-
 
1541
                UnOp(reg1);
1717
                addrc(reg1, param2)
1542
                addrc(reg1, param2)
1718
            END
1543
            END
1719
 
1544
 
1720
        |IL.opDIV:
1545
        |IL.opDIV:
1721
            PushAll(2);
1546
            PushAll(2);
1722
            CallRTL(IL._divmod);
1547
            CallRTL(IL._divmod);
1723
            GetRegA
1548
            GetRegA
1724
 
1549
 
1725
        |IL.opDIVR:
1550
        |IL.opDIVR:
1726
            n := UTILS.Log2(param2);
1551
            n := UTILS.Log2(param2);
1727
            IF n > 0 THEN
1552
            IF n > 0 THEN
1728
                UnOp(reg1);
1553
                UnOp(reg1);
1729
                shiftrc(sar, reg1, n)
1554
                shiftrc(sar, reg1, n)
1730
            ELSIF n < 0 THEN
1555
            ELSIF n < 0 THEN
1731
                PushAll(1);
1556
                PushAll(1);
1732
                pushc(param2);
1557
                pushc(param2);
1733
                CallRTL(IL._divmod);
1558
                CallRTL(IL._divmod);
1734
                GetRegA
1559
                GetRegA
1735
            END
1560
            END
1736
 
1561
 
1737
        |IL.opDIVL:
1562
        |IL.opDIVL:
1738
            UnOp(reg1);
1563
            UnOp(reg1);
1739
            REG.PushAll_1(R);
1564
            REG.PushAll_1(R);
1740
            pushc(param2);
1565
            pushc(param2);
1741
            push(reg1);
1566
            push(reg1);
1742
            drop;
1567
            drop;
1743
            CallRTL(IL._divmod);
1568
            CallRTL(IL._divmod);
1744
            GetRegA
1569
            GetRegA
1745
 
1570
 
1746
        |IL.opMOD:
1571
        |IL.opMOD:
1747
            PushAll(2);
1572
            PushAll(2);
1748
            CallRTL(IL._divmod);
1573
            CallRTL(IL._divmod);
1749
            mov(rax, rdx);
1574
            mov(rax, rdx);
1750
            GetRegA
1575
            GetRegA
1751
 
1576
 
1752
        |IL.opMODR:
1577
        |IL.opMODR:
1753
            n := UTILS.Log2(param2);
1578
            n := UTILS.Log2(param2);
1754
            IF n > 0 THEN
1579
            IF n > 0 THEN
1755
                UnOp(reg1);
1580
                UnOp(reg1);
1756
                andrc(reg1, param2 - 1);
1581
                andrc(reg1, param2 - 1);
1757
            ELSIF n < 0 THEN
1582
            ELSIF n < 0 THEN
1758
                PushAll(1);
1583
                PushAll(1);
1759
                pushc(param2);
1584
                pushc(param2);
1760
                CallRTL(IL._divmod);
1585
                CallRTL(IL._divmod);
1761
                mov(rax, rdx);
1586
                mov(rax, rdx);
1762
                GetRegA
1587
                GetRegA
1763
            ELSE
1588
            ELSE
1764
                UnOp(reg1);
1589
                UnOp(reg1);
1765
                xor(reg1, reg1)
1590
                xor(reg1, reg1)
1766
            END
1591
            END
1767
 
1592
 
1768
        |IL.opMODL:
1593
        |IL.opMODL:
1769
            UnOp(reg1);
1594
            UnOp(reg1);
1770
            REG.PushAll_1(R);
1595
            REG.PushAll_1(R);
1771
            pushc(param2);
1596
            pushc(param2);
1772
            push(reg1);
1597
            push(reg1);
1773
            drop;
1598
            drop;
1774
            CallRTL(IL._divmod);
1599
            CallRTL(IL._divmod);
1775
            mov(rax, rdx);
1600
            mov(rax, rdx);
1776
            GetRegA
1601
            GetRegA
1777
 
1602
 
1778
        |IL.opMUL:
1603
        |IL.opMUL:
1779
            BinOp(reg1, reg2);
1604
            BinOp(reg1, reg2);
1780
            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
1605
            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
1781
            drop
1606
            drop
1782
 
1607
 
1783
        |IL.opMULC:
1608
        |IL.opMULC:
1784
            IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN
1609
            IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN
1785
                BinOp(reg1, reg2);
1610
                BinOp(reg1, reg2);
1786
                OutByte2(48H + 5 * (reg1 DIV 8) + 2 * (reg2 DIV 8), 8DH); (* lea reg1, [reg1 + reg2 * param2] *)
1611
                OutByte2(48H + 5 * (reg1 DIV 8) + 2 * (reg2 DIV 8), 8DH); (* lea reg1, [reg1 + reg2 * param2] *)
1787
                reg1 := reg1 MOD 8;
1612
                reg1 := reg1 MOD 8;
1788
                reg2 := reg2 MOD 8;
1613
                reg2 := reg2 MOD 8;
1789
                OutByte2(04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2));
1614
                OutByte2(04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2));
1790
                drop;
1615
                drop;
1791
                cmd := cmd.next(COMMAND)
1616
                cmd := cmd.next(COMMAND)
1792
            ELSE
1617
            ELSE
1793
                UnOp(reg1);
1618
                UnOp(reg1);
1794
 
1619
 
1795
                a := param2;
1620
                a := param2;
1796
                IF a > 1 THEN
1621
                IF a > 1 THEN
1797
                    n := UTILS.Log2(a)
1622
                    n := UTILS.Log2(a)
1798
                ELSIF a < -1 THEN
1623
                ELSIF a < -1 THEN
1799
                    n := UTILS.Log2(-a)
1624
                    n := UTILS.Log2(-a)
1800
                ELSE
1625
                ELSE
1801
                    n := -1
1626
                    n := -1
1802
                END;
1627
                END;
1803
 
1628
 
1804
                IF a = 1 THEN
1629
                IF a = 1 THEN
1805
 
1630
 
1806
                ELSIF a = -1 THEN
1631
                ELSIF a = -1 THEN
1807
                    neg(reg1)
1632
                    neg(reg1)
1808
                ELSIF a = 0 THEN
1633
                ELSIF a = 0 THEN
1809
                    xor(reg1, reg1)
1634
                    xor(reg1, reg1)
1810
                ELSE
1635
                ELSE
1811
                    IF n > 0 THEN
1636
                    IF n > 0 THEN
1812
                        IF a < 0 THEN
1637
                        IF a < 0 THEN
1813
                            neg(reg1)
1638
                            neg(reg1)
1814
                        END;
1639
                        END;
1815
                        shiftrc(shl, reg1, n)
1640
                        shiftrc(shl, reg1, n)
1816
                    ELSE
1641
                    ELSE
1817
                        IF isLong(a) THEN
1642
                        IF isLong(a) THEN
1818
                            reg2 := GetAnyReg();
1643
                            reg2 := GetAnyReg();
1819
                            movabs(reg2, a);
1644
                            movabs(reg2, a);
1820
                            ASSERT(reg1 # reg2);
1645
                            ASSERT(reg1 # reg2);
1821
                            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
1646
                            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
1822
                            drop
1647
                            drop
1823
                        ELSE
1648
                        ELSE
1824
                            (* imul reg1, a *)
1649
                            (* imul reg1, a *)
1825
                            Rex(reg1, reg1);
1650
                            Rex(reg1, reg1);
1826
                            OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9);
1651
                            OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9);
1827
                            OutIntByte(a)
1652
                            OutIntByte(a)
1828
                        END
1653
                        END
1829
                    END
1654
                    END
1830
                END
1655
                END
1831
            END
1656
            END
1832
 
1657
 
1833
        |IL.opADDS:
1658
        |IL.opADDS:
1834
            BinOp(reg1, reg2);
1659
            BinOp(reg1, reg2);
1835
            _or(reg1, reg2);
1660
            _or(reg1, reg2);
1836
            drop
1661
            drop
1837
 
1662
 
1838
        |IL.opSUBS:
1663
        |IL.opSUBS:
1839
            BinOp(reg1, reg2);
1664
            BinOp(reg1, reg2);
1840
            not(reg2);
1665
            not(reg2);
1841
            and(reg1, reg2);
1666
            and(reg1, reg2);
1842
            drop
1667
            drop
1843
 
1668
 
1844
        |IL.opNOP, IL.opAND, IL.opOR:
1669
        |IL.opNOP, IL.opAND, IL.opOR:
1845
 
1670
 
1846
        |IL.opSWITCH:
1671
        |IL.opSWITCH:
1847
            UnOp(reg1);
1672
            UnOp(reg1);
1848
            IF param2 = 0 THEN
1673
            IF param2 = 0 THEN
1849
                reg2 := rax
1674
                reg2 := rax
1850
            ELSE
1675
            ELSE
1851
                reg2 := r10
1676
                reg2 := rcx
1852
            END;
1677
            END;
1853
            IF reg1 # reg2 THEN
1678
            IF reg1 # reg2 THEN
1854
                ASSERT(REG.GetReg(R, reg2));
1679
                ASSERT(REG.GetReg(R, reg2));
1855
                ASSERT(REG.Exchange(R, reg1, reg2));
1680
                ASSERT(REG.Exchange(R, reg1, reg2));
1856
                drop
1681
                drop
1857
            END;
1682
            END;
1858
            drop
1683
            drop
1859
 
1684
 
1860
        |IL.opENDSW:
1685
        |IL.opENDSW:
1861
 
1686
 
1862
        |IL.opCASEL:
1687
        |IL.opCASEL:
1863
            GetRegA;
1688
            GetRegA;
1864
            cmprc(rax, param1);
1689
            cmprc(rax, param1);
1865
            jcc(jl, param2);
1690
            jcc(jl, param2);
1866
            drop
1691
            drop
1867
 
1692
 
1868
        |IL.opCASER:
1693
        |IL.opCASER:
1869
            GetRegA;
1694
            GetRegA;
1870
            cmprc(rax, param1);
1695
            cmprc(rax, param1);
1871
            jcc(jg, param2);
1696
            jcc(jg, param2);
1872
            drop
1697
            drop
1873
 
1698
 
1874
        |IL.opCASELR:
1699
        |IL.opCASELR:
1875
            GetRegA;
1700
            GetRegA;
1876
            cmprc(rax, param1);
1701
            cmprc(rax, param1);
-
 
1702
            IF param2 = cmd.param3 THEN
-
 
1703
                jcc(jne, param2)
-
 
1704
            ELSE
1877
            jcc(jl, param2);
1705
                jcc(jl, param2);
1878
            jcc(jg, cmd.param3);
1706
                jcc(jg, cmd.param3)
-
 
1707
            END;
1879
            drop
1708
            drop
1880
 
1709
 
1881
        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
1710
        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
-
 
1711
            UnOp(reg1);
-
 
1712
            IF reg1 # rcx THEN
-
 
1713
                ASSERT(REG.GetReg(R, rcx));
-
 
1714
                ASSERT(REG.Exchange(R, reg1, rcx));
-
 
1715
                drop
-
 
1716
            END;
-
 
1717
 
1882
            BinOp(reg1, reg2);
1718
            BinOp(reg1, reg2);
1883
            xchg(reg2, rcx);
1719
            ASSERT(reg2 = rcx);
1884
            Rex(reg1, 0);
1720
            Rex(reg1, 0);
1885
            OutByte(0D3H);
1721
            OutByte(0D3H);
1886
            X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *)
1722
            X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *)
1887
            xchg(reg2, rcx);
-
 
1888
            drop
1723
            drop
1889
 
1724
 
1890
        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
1725
        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
-
 
1726
            UnOp(reg1);
-
 
1727
            IF reg1 # rcx THEN
-
 
1728
                ASSERT(REG.GetReg(R, rcx));
-
 
1729
                ASSERT(REG.Exchange(R, reg1, rcx));
-
 
1730
                drop
-
 
1731
            END;
-
 
1732
 
1891
            reg1 := GetAnyReg();
1733
            reg1 := GetAnyReg();
1892
            movrc(reg1, param2);
1734
            movrc(reg1, param2);
1893
            BinOp(reg1, reg2);
1735
            BinOp(reg1, reg2);
1894
            xchg(reg1, rcx);
1736
            ASSERT(reg1 = rcx);
1895
            Rex(reg2, 0);
1737
            Rex(reg2, 0);
1896
            OutByte(0D3H);
1738
            OutByte(0D3H);
1897
            X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *)
1739
            X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *)
1898
            xchg(reg1, rcx);
-
 
1899
            drop;
1740
            drop;
1900
            drop;
1741
            drop;
1901
            ASSERT(REG.GetReg(R, reg2))
1742
            ASSERT(REG.GetReg(R, reg2))
1902
 
1743
 
1903
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
1744
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
1904
            UnOp(reg1);
1745
            UnOp(reg1);
1905
            shiftrc(opcode, reg1, param2 MOD 64)
1746
            shiftrc(opcode, reg1, param2 MOD 64)
1906
 
1747
 
1907
        |IL.opGET, IL.opGETC:
1748
        |IL.opGET, IL.opGETC:
1908
            IF opcode = IL.opGET THEN
1749
            IF opcode = IL.opGET THEN
1909
                BinOp(reg1, reg2)
1750
                BinOp(reg1, reg2)
1910
            ELSIF opcode = IL.opGETC THEN
1751
            ELSIF opcode = IL.opGETC THEN
1911
                UnOp(reg2);
1752
                UnOp(reg2);
1912
                reg1 := GetAnyReg();
1753
                reg1 := GetAnyReg();
1913
                movrc(reg1, param1)
1754
                movrc(reg1, param1)
1914
            END;
1755
            END;
1915
            drop;
1756
            drop;
1916
            drop;
1757
            drop;
1917
            X86._movrm(reg1, reg1, 0, param2 * 8, FALSE);
1758
            X86._movrm(reg1, reg1, 0, param2 * 8, FALSE);
1918
            X86._movrm(reg1, reg2, 0, param2 * 8, TRUE)
1759
            X86._movrm(reg1, reg2, 0, param2 * 8, TRUE)
1919
 
1760
 
1920
        |IL.opCHKBYTE:
1761
        |IL.opCHKBYTE:
1921
            BinOp(reg1, reg2);
1762
            BinOp(reg1, reg2);
1922
            cmprc(reg1, 256);
1763
            cmprc(reg1, 256);
1923
            jcc(jb, param1)
1764
            jcc(jb, param1)
1924
 
1765
 
1925
        |IL.opCHKIDX:
1766
        |IL.opCHKIDX:
1926
            UnOp(reg1);
1767
            UnOp(reg1);
1927
            cmprc(reg1, param2);
1768
            cmprc(reg1, param2);
1928
            jcc(jb, param1)
1769
            jcc(jb, param1)
1929
 
1770
 
1930
        |IL.opCHKIDX2:
1771
        |IL.opCHKIDX2:
1931
            BinOp(reg1, reg2);
1772
            BinOp(reg1, reg2);
1932
            IF param2 # -1 THEN
1773
            IF param2 # -1 THEN
1933
                cmprr(reg2, reg1);
1774
                cmprr(reg2, reg1);
1934
                jcc(jb, param1);
1775
                jcc(jb, param1);
1935
            END;
1776
            END;
1936
            INCL(R.regs, reg1);
1777
            INCL(R.regs, reg1);
1937
            DEC(R.top);
1778
            DEC(R.top);
1938
            R.stk[R.top] := reg2
1779
            R.stk[R.top] := reg2
1939
 
1780
 
1940
        |IL.opLENGTH:
1781
        |IL.opLENGTH:
1941
            PushAll(2);
1782
            PushAll(2);
1942
            CallRTL(IL._length);
1783
            CallRTL(IL._length);
1943
            GetRegA
1784
            GetRegA
1944
 
1785
 
1945
        |IL.opLENGTHW:
1786
        |IL.opLENGTHW:
1946
            PushAll(2);
1787
            PushAll(2);
1947
            CallRTL(IL._lengthw);
1788
            CallRTL(IL._lengthw);
1948
            GetRegA
1789
            GetRegA
1949
 
1790
 
1950
        |IL.opLEN:
1791
        |IL.opLEN:
1951
            n := param2;
1792
            n := param2;
1952
            UnOp(reg1);
1793
            UnOp(reg1);
1953
            drop;
1794
            drop;
1954
            EXCL(R.regs, reg1);
1795
            EXCL(R.regs, reg1);
1955
 
1796
 
1956
            WHILE n > 0 DO
1797
            WHILE n > 0 DO
1957
                UnOp(reg2);
1798
                UnOp(reg2);
1958
                drop;
1799
                drop;
1959
                DEC(n)
1800
                DEC(n)
1960
            END;
1801
            END;
1961
 
1802
 
1962
            INCL(R.regs, reg1);
1803
            INCL(R.regs, reg1);
1963
            ASSERT(REG.GetReg(R, reg1))
1804
            ASSERT(REG.GetReg(R, reg1))
1964
 
1805
 
1965
        |IL.opCHR:
1806
        |IL.opCHR:
1966
            UnOp(reg1);
1807
            UnOp(reg1);
1967
            andrc(reg1, 255)
1808
            andrc(reg1, 255)
1968
 
1809
 
1969
        |IL.opWCHR:
1810
        |IL.opWCHR:
1970
            UnOp(reg1);
1811
            UnOp(reg1);
1971
            andrc(reg1, 65535)
1812
            andrc(reg1, 65535)
1972
 
1813
 
1973
        |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
1814
        |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
1974
            UnOp(reg1);
1815
            UnOp(reg1);
1975
            reg2 := GetAnyReg();
1816
            reg2 := GetAnyReg();
1976
 
1817
 
1977
            CASE opcode OF
1818
            CASE opcode OF
1978
            |IL.opEQP, IL.opNEP:
1819
            |IL.opEQP, IL.opNEP:
1979
                lea(reg2, param1, sCODE)
1820
                lea(reg2, param1, sCODE)
1980
 
1821
 
1981
            |IL.opEQIP, IL.opNEIP:
1822
            |IL.opEQIP, IL.opNEIP:
1982
                lea(reg2, param1, sIMP);
1823
                lea(reg2, param1, sIMP);
1983
                movrm(reg2, reg2, 0)
1824
                movrm(reg2, reg2, 0)
1984
            END;
1825
            END;
1985
 
1826
 
1986
            cmprr(reg1, reg2);
1827
            cmprr(reg1, reg2);
1987
            drop;
1828
            drop;
1988
            drop;
1829
            drop;
1989
            reg1 := GetAnyReg();
1830
            reg1 := GetAnyReg();
1990
 
1831
 
1991
            CASE opcode OF
1832
            CASE opcode OF
1992
            |IL.opEQP, IL.opEQIP: X86.setcc(sete,  reg1)
1833
            |IL.opEQP, IL.opEQIP: X86.setcc(sete,  reg1)
1993
            |IL.opNEP, IL.opNEIP: X86.setcc(setne, reg1)
1834
            |IL.opNEP, IL.opNEIP: X86.setcc(setne, reg1)
1994
            END;
1835
            END;
1995
 
1836
 
1996
            andrc(reg1, 1)
1837
            andrc(reg1, 1)
1997
 
1838
 
1998
        |IL.opINCCB, IL.opDECCB:
1839
        |IL.opINCCB, IL.opDECCB:
1999
            UnOp(reg1);
1840
            UnOp(reg1);
2000
            IF reg1 >= 8 THEN
1841
            IF reg1 >= 8 THEN
2001
                OutByte(41H)
1842
                OutByte(41H)
2002
            END;
1843
            END;
2003
            OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); (* add/sub byte[reg1], param2 MOD 256 *)
1844
            OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); (* add/sub byte[reg1], param2 MOD 256 *)
2004
            drop
1845
            drop
2005
 
1846
 
2006
        |IL.opINCB, IL.opDECB:
1847
        |IL.opINCB, IL.opDECB:
2007
            BinOp(reg1, reg2);
1848
            BinOp(reg1, reg2);
2008
            IF (reg1 >= 8) OR (reg2 >= 8) THEN
1849
            IF (reg1 >= 8) OR (reg2 >= 8) THEN
2009
                OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8))
1850
                OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8))
2010
            END;
1851
            END;
2011
            OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); (* add/sub byte[reg2], reg1_8 *)
1852
            OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); (* add/sub byte[reg2], reg1_8 *)
2012
            drop;
1853
            drop;
2013
            drop
1854
            drop
2014
 
1855
 
2015
        |IL.opSAVEIP:
1856
        |IL.opSAVEIP:
2016
            UnOp(reg1);
1857
            UnOp(reg1);
2017
            reg2 := GetAnyReg();
1858
            reg2 := GetAnyReg();
2018
            lea(reg2, param2, sIMP);
1859
            lea(reg2, param2, sIMP);
2019
            movrm(reg2, reg2, 0);
1860
            movrm(reg2, reg2, 0);
2020
            push(reg2);
1861
            push(reg2);
2021
            drop;
1862
            drop;
2022
            IF reg1 >= 8 THEN
1863
            IF reg1 >= 8 THEN
2023
                OutByte(41H)
1864
                OutByte(41H)
2024
            END;
1865
            END;
2025
            OutByte2(8FH, reg1 MOD 8); (* pop qword[reg1] *)
1866
            OutByte2(8FH, reg1 MOD 8); (* pop qword[reg1] *)
2026
            drop
1867
            drop
2027
 
1868
 
2028
        |IL.opCLEANUP:
1869
        |IL.opCLEANUP:
2029
            IF param2 # 0 THEN
1870
            IF param2 # 0 THEN
2030
                addrc(rsp, param2 * 8)
1871
                addrc(rsp, param2 * 8)
2031
            END
1872
            END
2032
 
1873
 
2033
        |IL.opPOPSP:
1874
        |IL.opPOPSP:
2034
            pop(rsp)
1875
            pop(rsp)
2035
 
1876
 
2036
        |IL.opLOADF:
1877
        |IL.opLOADF:
2037
            UnOp(reg1);
1878
            UnOp(reg1);
2038
            INC(xmm);
1879
            INC(xmm);
2039
            IF xmm > MAX_XMM THEN
1880
            IF xmm > MAX_XMM THEN
2040
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1881
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
2041
            END;
1882
            END;
2042
            movsdrm(xmm, reg1, 0);
1883
            movsdrm(xmm, reg1, 0);
2043
            drop
1884
            drop
2044
 
1885
 
2045
        |IL.opPUSHF:
1886
        |IL.opPUSHF:
2046
            ASSERT(xmm >= 0);
1887
            ASSERT(xmm >= 0);
2047
            subrc(rsp, 8);
1888
            subrc(rsp, 8);
2048
            movsdmr(rsp, 0, xmm);
1889
            movsdmr(rsp, 0, xmm);
2049
            DEC(xmm)
1890
            DEC(xmm)
2050
 
1891
 
2051
        |IL.opCONSTF:
1892
        |IL.opCONSTF:
2052
            float := cmd.float;
1893
            float := cmd.float;
2053
            INC(xmm);
1894
            INC(xmm);
2054
            IF xmm > MAX_XMM THEN
1895
            IF xmm > MAX_XMM THEN
2055
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1896
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
2056
            END;
1897
            END;
2057
            (* movsd xmm, qword ptr [rip + Numbers_Offs + Numbers_Count * 8 + DATA] *)
1898
            (* movsd xmm, qword ptr [rip + Numbers_Offs + Numbers_Count * 8 + DATA] *)
2058
            OutByte(0F2H);
1899
            OutByte(0F2H);
2059
            IF xmm >= 8 THEN
1900
            IF xmm >= 8 THEN
2060
                OutByte(44H)
1901
                OutByte(44H)
2061
            END;
1902
            END;
2062
            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
1903
            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
2063
            X86.Reloc(sDATA, Numbers_Offs + Numbers_Count * 8);
1904
            X86.Reloc(sDATA, Numbers_Offs + Numbers_Count * 8);
2064
            NewNumber(UTILS.splitf(float, a, b))
1905
            NewNumber(UTILS.splitf(float, a, b))
2065
 
1906
 
2066
        |IL.opSAVEF, IL.opSAVEFI:
1907
        |IL.opSAVEF, IL.opSAVEFI:
2067
            ASSERT(xmm >= 0);
1908
            ASSERT(xmm >= 0);
2068
            UnOp(reg1);
1909
            UnOp(reg1);
2069
            movsdmr(reg1, 0, xmm);
1910
            movsdmr(reg1, 0, xmm);
2070
            DEC(xmm);
1911
            DEC(xmm);
2071
            drop
1912
            drop
2072
 
1913
 
2073
        |IL.opADDF:
1914
        |IL.opADDF:
2074
            ASSERT(xmm >= 1);
1915
            ASSERT(xmm >= 1);
2075
            opxx(58H, xmm - 1, xmm);
1916
            opxx(58H, xmm - 1, xmm);
2076
            DEC(xmm)
1917
            DEC(xmm)
2077
 
1918
 
2078
        |IL.opSUBF:
1919
        |IL.opSUBF:
2079
            ASSERT(xmm >= 1);
1920
            ASSERT(xmm >= 1);
2080
            opxx(5CH, xmm - 1, xmm);
1921
            opxx(5CH, xmm - 1, xmm);
2081
            DEC(xmm)
1922
            DEC(xmm)
2082
 
1923
 
2083
        |IL.opSUBFI:
1924
        |IL.opSUBFI:
2084
            ASSERT(xmm >= 1);
1925
            ASSERT(xmm >= 1);
2085
            opxx(5CH, xmm, xmm - 1);
1926
            opxx(5CH, xmm, xmm - 1);
2086
            opxx(10H, xmm - 1, xmm);
1927
            opxx(10H, xmm - 1, xmm);
2087
            DEC(xmm)
1928
            DEC(xmm)
2088
 
1929
 
2089
        |IL.opMULF:
1930
        |IL.opMULF:
2090
            ASSERT(xmm >= 1);
1931
            ASSERT(xmm >= 1);
2091
            opxx(59H, xmm - 1, xmm);
1932
            opxx(59H, xmm - 1, xmm);
2092
            DEC(xmm)
1933
            DEC(xmm)
2093
 
1934
 
2094
        |IL.opDIVF:
1935
        |IL.opDIVF:
2095
            ASSERT(xmm >= 1);
1936
            ASSERT(xmm >= 1);
2096
            opxx(5EH, xmm - 1, xmm);
1937
            opxx(5EH, xmm - 1, xmm);
2097
            DEC(xmm)
1938
            DEC(xmm)
2098
 
1939
 
2099
        |IL.opDIVFI:
1940
        |IL.opDIVFI:
2100
            ASSERT(xmm >= 1);
1941
            ASSERT(xmm >= 1);
2101
            opxx(5EH, xmm, xmm - 1);
1942
            opxx(5EH, xmm, xmm - 1);
2102
            opxx(10H, xmm - 1, xmm);
1943
            opxx(10H, xmm - 1, xmm);
2103
            DEC(xmm)
1944
            DEC(xmm)
2104
 
1945
 
2105
        |IL.opFABS, IL.opUMINF: (* andpd/xorpd xmm, xmmword[rip + Numbers_Offs + (16) + DATA] *)
1946
        |IL.opFABS, IL.opUMINF: (* andpd/xorpd xmm, xmmword[rip + Numbers_Offs + (16) + DATA] *)
2106
            ASSERT(xmm >= 0);
1947
            ASSERT(xmm >= 0);
2107
            OutByte(66H);
1948
            OutByte(66H);
2108
            IF xmm >= 8 THEN
1949
            IF xmm >= 8 THEN
2109
                OutByte(44H)
1950
                OutByte(44H)
2110
            END;
1951
            END;
2111
            OutByte3(0FH, 54H + 3 * ORD(opcode = IL.opUMINF), 05H + (xmm MOD 8) * 8);
1952
            OutByte3(0FH, 54H + 3 * ORD(opcode = IL.opUMINF), 05H + (xmm MOD 8) * 8);
2112
            X86.Reloc(sDATA, Numbers_Offs + 16 * ORD(opcode = IL.opFABS))
1953
            X86.Reloc(sDATA, Numbers_Offs + 16 * ORD(opcode = IL.opFABS))
2113
 
1954
 
2114
        |IL.opFLT:
1955
        |IL.opFLT:
2115
            UnOp(reg1);
1956
            UnOp(reg1);
2116
            INC(xmm);
1957
            INC(xmm);
2117
            IF xmm > MAX_XMM THEN
1958
            IF xmm > MAX_XMM THEN
2118
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1959
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
2119
            END;
1960
            END;
2120
            OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *)
1961
            OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *)
2121
            OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8);
1962
            OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8);
2122
            drop
1963
            drop
2123
 
1964
 
2124
        |IL.opFLOOR:
1965
        |IL.opFLOOR:
2125
            ASSERT(xmm >= 0);
1966
            ASSERT(xmm >= 0);
2126
            reg1 := GetAnyReg();
1967
            reg1 := GetAnyReg();
2127
            subrc(rsp, 8);
1968
            subrc(rsp, 8);
2128
            OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H);                       (* stmxcsr dword[rsp+4];                              *)
1969
            OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H);                       (* stmxcsr dword[rsp+4];                              *)
2129
            OutByte2(00FH, 0AEH); OutByte2(01CH, 024H);                             (* stmxcsr dword[rsp];                                *)
1970
            OutByte2(00FH, 0AEH); OutByte2(01CH, 024H);                             (* stmxcsr dword[rsp];                                *)
2130
            OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); (* and dword[rsp],11111111111111111001111111111111b;  *)
1971
            OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); (* and dword[rsp],11111111111111111001111111111111b;  *)
2131
            OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); (* or dword[rsp],00000000000000000010000000000000b;   *)
1972
            OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); (* or dword[rsp],00000000000000000010000000000000b;   *)
2132
            OutByte2(00FH, 0AEH); OutByte2(014H, 024H);                             (* ldmxcsr dword[rsp];                                *)
1973
            OutByte2(00FH, 0AEH); OutByte2(014H, 024H);                             (* ldmxcsr dword[rsp];                                *)
2133
            OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH);                            (* cvtsd2si reg1, xmm                                 *)
1974
            OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH);                            (* cvtsd2si reg1, xmm                                 *)
2134
            OutByte2(2DH, 0C0H + xmm MOD 8 + (reg1 MOD 8) * 8);
1975
            OutByte2(2DH, 0C0H + xmm MOD 8 + (reg1 MOD 8) * 8);
2135
            OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H);                       (* ldmxcsr dword[rsp+4];                              *)
1976
            OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H);                       (* ldmxcsr dword[rsp+4];                              *)
2136
            addrc(rsp, 8);
1977
            addrc(rsp, 8);
2137
            DEC(xmm)
1978
            DEC(xmm)
2138
 
1979
 
2139
        |IL.opEQF .. IL.opGEF:
1980
        |IL.opEQF .. IL.opGEF:
2140
            ASSERT(xmm >= 1);
1981
            ASSERT(xmm >= 1);
2141
            fcmp(opcode, xmm);
1982
            fcmp(opcode, xmm);
2142
            DEC(xmm, 2)
1983
            DEC(xmm, 2)
2143
 
1984
 
2144
        |IL.opINF:
1985
        |IL.opINF:
2145
            INC(xmm);
1986
            INC(xmm);
2146
            IF xmm > MAX_XMM THEN
1987
            IF xmm > MAX_XMM THEN
2147
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1988
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
2148
            END;
1989
            END;
2149
            (* movsd xmm, qword ptr [rip + Numbers_Offs + 32 + DATA] *)
1990
            (* movsd xmm, qword ptr [rip + Numbers_Offs + 32 + DATA] *)
2150
            OutByte(0F2H);
1991
            OutByte(0F2H);
2151
            IF xmm >= 8 THEN
1992
            IF xmm >= 8 THEN
2152
                OutByte(44H)
1993
                OutByte(44H)
2153
            END;
1994
            END;
2154
            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
1995
            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
2155
            X86.Reloc(sDATA, Numbers_Offs + 32)
1996
            X86.Reloc(sDATA, Numbers_Offs + 32)
2156
 
1997
 
2157
        |IL.opPACK, IL.opPACKC:
1998
        |IL.opPACK, IL.opPACKC:
2158
            IF opcode = IL.opPACK THEN
1999
            IF opcode = IL.opPACK THEN
2159
                BinOp(reg1, reg2)
2000
                BinOp(reg1, reg2)
2160
            ELSE
2001
            ELSE
2161
                UnOp(reg1);
2002
                UnOp(reg1);
2162
                reg2 := GetAnyReg();
2003
                reg2 := GetAnyReg();
2163
                movrc(reg2, param2)
2004
                movrc(reg2, param2)
2164
            END;
2005
            END;
2165
            push(reg1);
2006
            push(reg1);
2166
            movrm(reg1, reg1, 0);
2007
            movrm(reg1, reg1, 0);
2167
            shiftrc(shl, reg1, 1);
2008
            shiftrc(shl, reg1, 1);
2168
            shiftrc(shr, reg1, 53);
2009
            shiftrc(shr, reg1, 53);
2169
            add(reg1, reg2);
2010
            add(reg1, reg2);
2170
            andrc(reg1, ORD({0..10}));
2011
            andrc(reg1, ORD({0..10}));
2171
            shiftrc(shl, reg1, 52);
2012
            shiftrc(shl, reg1, 52);
2172
            movrm(reg2, rsp, 0);
2013
            movrm(reg2, rsp, 0);
2173
            movrm(reg2, reg2, 0);
2014
            movrm(reg2, reg2, 0);
2174
 
2015
 
2175
            push(reg1);
2016
            push(reg1);
2176
            lea(reg1, Numbers_Offs + 40, sDATA); (* {0..51, 63} *)
2017
            lea(reg1, Numbers_Offs + 40, sDATA); (* {0..51, 63} *)
2177
            movrm(reg1, reg1, 0);
2018
            movrm(reg1, reg1, 0);
2178
            and(reg2, reg1);
2019
            and(reg2, reg1);
2179
            pop(reg1);
2020
            pop(reg1);
2180
 
2021
 
2181
            _or(reg2, reg1);
2022
            _or(reg2, reg1);
2182
            pop(reg1);
2023
            pop(reg1);
2183
            movmr(reg1, 0, reg2);
2024
            movmr(reg1, 0, reg2);
2184
            drop;
2025
            drop;
2185
            drop
2026
            drop
2186
 
2027
 
2187
        |IL.opUNPK, IL.opLADR_UNPK:
2028
        |IL.opUNPK, IL.opLADR_UNPK:
2188
 
2029
 
2189
            IF opcode = IL.opLADR_UNPK THEN
2030
            IF opcode = IL.opLADR_UNPK THEN
2190
                n := param2 * 8;
2031
                n := param2 * 8;
2191
                UnOp(reg1);
2032
                UnOp(reg1);
2192
                reg2 := GetVarReg(param2);
-
 
2193
                regVar := reg2 # -1;
-
 
2194
                IF ~regVar THEN
-
 
2195
                    reg2 := GetAnyReg();
2033
                reg2 := GetAnyReg();
2196
                    Rex(0, reg2);
2034
                Rex(0, reg2);
2197
                    OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *)
2035
                OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *)
2198
                    OutIntByte(n)
2036
                OutIntByte(n)
2199
                END
-
 
2200
            ELSE
2037
            ELSE
2201
                BinOp(reg1, reg2);
2038
                BinOp(reg1, reg2)
2202
                regVar := FALSE
-
 
2203
            END;
2039
            END;
2204
 
2040
 
2205
            push(reg1);
2041
            push(reg1);
2206
            movrm(reg1, reg1, 0);
2042
            movrm(reg1, reg1, 0);
2207
            shiftrc(shl, reg1, 1);
2043
            shiftrc(shl, reg1, 1);
2208
            shiftrc(shr, reg1, 53);
2044
            shiftrc(shr, reg1, 53);
2209
            subrc(reg1, 1023);
2045
            subrc(reg1, 1023);
2210
 
-
 
2211
            IF regVar THEN
-
 
2212
                mov(reg2, reg1);
-
 
2213
                reg2 := GetAnyReg()
-
 
2214
            ELSE
2046
 
2215
                movmr(reg2, 0, reg1)
-
 
2216
            END;
2047
            movmr(reg2, 0, reg1);
2217
 
2048
 
2218
            pop(reg2);
2049
            pop(reg2);
2219
            movrm(reg1, reg2, 0);
2050
            movrm(reg1, reg2, 0);
2220
 
2051
 
2221
            push(reg2);
2052
            push(reg2);
2222
            lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *)
2053
            lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *)
2223
            movrm(reg2, reg2, 0);
2054
            movrm(reg2, reg2, 0);
2224
            _or(reg1, reg2);
2055
            _or(reg1, reg2);
2225
            pop(reg2);
2056
            pop(reg2);
2226
 
2057
 
2227
            Rex(reg1, 0);
2058
            Rex(reg1, 0);
2228
            OutByte2(0FH, 0BAH);
2059
            OutByte2(0FH, 0BAH);
2229
            OutByte2(0F0H + reg1 MOD 8, 3EH); (* btr reg1, 62 *)
2060
            OutByte2(0F0H + reg1 MOD 8, 3EH); (* btr reg1, 62 *)
2230
            movmr(reg2, 0, reg1);
2061
            movmr(reg2, 0, reg1);
2231
            drop;
2062
            drop;
2232
            drop
2063
            drop
2233
 
2064
 
2234
        |IL.opSADR_PARAM:
2065
        |IL.opSADR_PARAM:
2235
            pushDA(stroffs + param2)
2066
            pushDA(stroffs + param2)
2236
 
2067
 
2237
        |IL.opVADR_PARAM:
2068
        |IL.opVADR_PARAM:
2238
            X86.pushm(rbp, param2 * 8)
2069
            X86.pushm(rbp, param2 * 8)
2239
 
2070
 
2240
        |IL.opLOAD64_PARAM:
2071
        |IL.opLOAD64_PARAM:
2241
            UnOp(reg1);
2072
            UnOp(reg1);
2242
            X86.pushm(reg1, 0);
2073
            X86.pushm(reg1, 0);
2243
            drop
2074
            drop
2244
 
2075
 
2245
        |IL.opLLOAD64_PARAM:
2076
        |IL.opLLOAD64_PARAM:
2246
            reg1 := GetVarReg(param2);
-
 
2247
            IF reg1 # -1 THEN
-
 
2248
                push(reg1)
-
 
2249
            ELSE
-
 
2250
                X86.pushm(rbp, param2 * 8)
2077
            X86.pushm(rbp, param2 * 8)
2251
            END
-
 
2252
 
2078
 
2253
        |IL.opGLOAD64_PARAM:
2079
        |IL.opGLOAD64_PARAM:
2254
            OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *)
2080
            OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *)
2255
            X86.Reloc(sBSS, param2)
2081
            X86.Reloc(sBSS, param2)
2256
 
2082
 
2257
        |IL.opCONST_PARAM:
2083
        |IL.opCONST_PARAM:
2258
            pushc(param2)
2084
            pushc(param2)
2259
 
2085
 
2260
        |IL.opGLOAD32_PARAM, IL.opLOAD32_PARAM:
2086
        |IL.opGLOAD32_PARAM, IL.opLOAD32_PARAM:
2261
            IF opcode = IL.opGLOAD32_PARAM THEN
2087
            IF opcode = IL.opGLOAD32_PARAM THEN
2262
                reg1 := GetAnyReg();
2088
                reg1 := GetAnyReg();
2263
                lea(reg1, param2, sBSS)
2089
                lea(reg1, param2, sBSS)
2264
            ELSE
2090
            ELSE
2265
                UnOp(reg1)
2091
                UnOp(reg1)
2266
            END;
2092
            END;
2267
            movrm32(reg1, reg1, 0);
2093
            movrm32(reg1, reg1, 0);
2268
            shiftrc(shl, reg1, 32);
2094
            shiftrc(shl, reg1, 32);
2269
            shiftrc(shr, reg1, 32);
2095
            shiftrc(shr, reg1, 32);
2270
            push(reg1);
2096
            push(reg1);
2271
            drop
2097
            drop
2272
 
2098
 
2273
        |IL.opLLOAD32_PARAM:
2099
        |IL.opLLOAD32_PARAM:
2274
            reg1 := GetAnyReg();
2100
            reg1 := GetAnyReg();
2275
            reg2 := GetVarReg(param2);
-
 
2276
            IF reg2 # -1 THEN
-
 
2277
                mov(reg1, reg2)
-
 
2278
            ELSE
-
 
2279
                movrm32(reg1, rbp, param2 * 8)
2101
            movrm32(reg1, rbp, param2 * 8);
2280
            END;
-
 
2281
            shiftrc(shl, reg1, 32);
2102
            shiftrc(shl, reg1, 32);
2282
            shiftrc(shr, reg1, 32);
2103
            shiftrc(shr, reg1, 32);
2283
            push(reg1);
2104
            push(reg1);
2284
            drop
2105
            drop
2285
 
2106
 
2286
        |IL.opLADR_SAVEC:
2107
        |IL.opLADR_SAVEC:
2287
            n := param1 * 8;
2108
            n := param1 * 8;
2288
            reg1 := GetVarReg(param1);
-
 
2289
            IF reg1 # -1 THEN
-
 
2290
                movrc(reg1, param2)
-
 
2291
            ELSE
-
 
2292
                IF isLong(param2) THEN
2109
            IF isLong(param2) THEN
2293
                    reg2 := GetAnyReg();
2110
                reg2 := GetAnyReg();
2294
                    movrc(reg2, param2);
2111
                movrc(reg2, param2);
2295
                    movmr(rbp, n, reg2);
2112
                movmr(rbp, n, reg2);
2296
                    drop
2113
                drop
2297
                ELSE
2114
            ELSE
2298
                    OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *)
2115
                OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *)
2299
                    OutIntByte(n);
2116
                OutIntByte(n);
2300
                    OutInt(param2)
2117
                OutInt(param2)
2301
                END
2118
            END
2302
            END
-
 
2303
 
2119
 
2304
        |IL.opGADR_SAVEC:
2120
        |IL.opGADR_SAVEC:
2305
            IF isLong(param2) THEN
2121
            IF isLong(param2) THEN
2306
                reg1 := GetAnyReg();
2122
                reg1 := GetAnyReg();
2307
                movrc(reg1, param2);
2123
                movrc(reg1, param2);
2308
                reg2 := GetAnyReg();
2124
                reg2 := GetAnyReg();
2309
                lea(reg2, param1, sBSS);
2125
                lea(reg2, param1, sBSS);
2310
                movmr(reg2, 0, reg1);
2126
                movmr(reg2, 0, reg1);
2311
                drop;
2127
                drop;
2312
                drop
2128
                drop
2313
            ELSE
2129
            ELSE
2314
                (* mov qword[rip + param1 - 4 + BSS], param2 *)
2130
                (* mov qword[rip + param1 - 4 + BSS], param2 *)
2315
                OutByte3(48H, 0C7H, 05H);
2131
                OutByte3(48H, 0C7H, 05H);
2316
                X86.Reloc(sBSS, param1 - 4);
2132
                X86.Reloc(sBSS, param1 - 4);
2317
                OutInt(param2)
2133
                OutInt(param2)
2318
            END
2134
            END
2319
 
2135
 
2320
        |IL.opLADR_SAVE:
2136
        |IL.opLADR_SAVE:
2321
            UnOp(reg1);
2137
            UnOp(reg1);
2322
            reg2 := GetVarReg(param2);
-
 
2323
            IF reg2 # -1 THEN
-
 
2324
                mov(reg2, reg1)
-
 
2325
            ELSE
-
 
2326
                movmr(rbp, param2 * 8, reg1)
2138
            movmr(rbp, param2 * 8, reg1);
2327
            END;
-
 
2328
            drop
2139
            drop
2329
 
2140
 
2330
        |IL.opLADR_INCC:
2141
        |IL.opLADR_INCC:
2331
            reg1 := GetVarReg(param1);
-
 
2332
            IF isLong(param2) THEN
2142
            IF isLong(param2) THEN
2333
                reg2 := GetAnyReg();
2143
                reg2 := GetAnyReg();
2334
                movrc(reg2, param2);
2144
                movrc(reg2, param2);
2335
                IF reg1 # -1 THEN
-
 
2336
                    add(reg1, reg2)
-
 
2337
                ELSE
-
 
2338
                    n := param1 * 8;
2145
                n := param1 * 8;
2339
                    Rex(0, reg2);
2146
                Rex(0, reg2);
2340
                    OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8);
2147
                OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8);
2341
                    OutIntByte(n) (* add qword[rbp+n], reg2 *)
2148
                OutIntByte(n); (* add qword[rbp+n], reg2 *)
2342
                END;
-
 
2343
                drop
2149
                drop
2344
            ELSIF ABS(param2) = 1 THEN
2150
            ELSIF ABS(param2) = 1 THEN
2345
                IF reg1 # -1 THEN
-
 
2346
                    IF param2 = 1 THEN
-
 
2347
                        incr(reg1)
-
 
2348
                    ELSE
-
 
2349
                        decr(reg1)
-
 
2350
                    END
-
 
2351
                ELSE
-
 
2352
                    n := param1 * 8;
2151
                n := param1 * 8;
2353
                    OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *)
2152
                OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *)
2354
                    OutIntByte(n)
2153
                OutIntByte(n)
2355
                END
-
 
2356
            ELSE
-
 
2357
                IF reg1 # -1 THEN
-
 
2358
                    addrc(reg1, param2)
-
 
2359
                ELSE
2154
            ELSE
2360
                    n := param1 * 8;
2155
                n := param1 * 8;
2361
                    OutByte3(48H, 81H + short(param2), 45H + long(n));
2156
                OutByte3(48H, 81H + short(param2), 45H + long(n));
2362
                    OutIntByte(n);
2157
                OutIntByte(n);
2363
                    OutIntByte(param2) (* add qword[rbp+n], param2 *)
2158
                OutIntByte(param2) (* add qword[rbp+n], param2 *)
2364
                END
2159
            END
2365
            END
-
 
2366
 
2160
 
2367
        |IL.opLADR_INCCB, IL.opLADR_DECCB:
-
 
2368
            reg1 := GetVarReg(param1);
2161
        |IL.opLADR_INCCB, IL.opLADR_DECCB:
2369
            param2 := param2 MOD 256;
-
 
2370
            IF reg1 # -1 THEN
-
 
2371
                IF opcode = IL.opLADR_DECCB THEN
-
 
2372
                    subrc(reg1, param2)
-
 
2373
                ELSE
-
 
2374
                    addrc(reg1, param2)
-
 
2375
                END;
-
 
2376
                andrc(reg1, 255)
-
 
2377
            ELSE
2162
            param2 := param2 MOD 256;
2378
                n := param1 * 8;
2163
            n := param1 * 8;
2379
                OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB));
2164
            OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB));
2380
                OutIntByte(n);
2165
            OutIntByte(n);
2381
                OutByte(param2) (* add/sub byte[rbp+n], param2 *)
2166
            OutByte(param2) (* add/sub byte[rbp+n], param2 *)
2382
            END
-
 
2383
 
2167
 
2384
        |IL.opLADR_INC, IL.opLADR_DEC:
2168
        |IL.opLADR_INC, IL.opLADR_DEC:
2385
            UnOp(reg1);
2169
            UnOp(reg1);
2386
            reg2 := GetVarReg(param2);
-
 
2387
            IF reg2 # -1 THEN
-
 
2388
                IF opcode = IL.opLADR_DEC THEN
-
 
2389
                    sub(reg2, reg1)
-
 
2390
                ELSE
-
 
2391
                    add(reg2, reg1)
-
 
2392
                END
-
 
2393
            ELSE
-
 
2394
                n := param2 * 8;
2170
            n := param2 * 8;
2395
                Rex(0, reg1);
2171
            Rex(0, reg1);
2396
                OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8);
2172
            OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8);
2397
                OutIntByte(n) (* add/sub qword[rbp+n], reg1 *)
2173
            OutIntByte(n); (* add/sub qword[rbp+n], reg1 *)
2398
            END;
-
 
2399
            drop
2174
            drop
2400
 
2175
 
2401
        |IL.opLADR_INCB, IL.opLADR_DECB:
2176
        |IL.opLADR_INCB, IL.opLADR_DECB:
2402
            UnOp(reg1);
2177
            UnOp(reg1);
2403
            reg2 := GetVarReg(param2);
-
 
2404
            IF reg2 # -1 THEN
-
 
2405
                IF opcode = IL.opLADR_DECB THEN
-
 
2406
                    sub(reg2, reg1)
-
 
2407
                ELSE
-
 
2408
                    add(reg2, reg1)
-
 
2409
                END;
-
 
2410
                andrc(reg2, 255)
-
 
2411
            ELSE
-
 
2412
                n := param2 * 8;
2178
            n := param2 * 8;
2413
                IF reg1 >= 8 THEN
2179
            IF reg1 >= 8 THEN
2414
                    OutByte(44H)
2180
                OutByte(44H)
2415
                END;
2181
            END;
2416
                OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8));
2182
            OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8));
2417
                OutIntByte(n) (* add/sub byte[rbp+n], reg1_8 *)
2183
            OutIntByte(n); (* add/sub byte[rbp+n], reg1_8 *)
2418
            END;
-
 
2419
            drop
2184
            drop
2420
 
2185
 
2421
        |IL.opLADR_INCL, IL.opLADR_EXCL:
2186
        |IL.opLADR_INCL, IL.opLADR_EXCL:
2422
            UnOp(reg1);
2187
            UnOp(reg1);
2423
            cmprc(reg1, 64);
2188
            cmprc(reg1, 64);
2424
            reg2 := GetVarReg(param2);
-
 
2425
            IF reg2 # -1 THEN
-
 
2426
                OutByte2(73H, 4); (* jnb L *)
-
 
2427
                oprr2(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), reg2, reg1) (* bts/btr reg2, reg1 *)
-
 
2428
            ELSE
-
 
2429
                n := param2 * 8;
2189
            n := param2 * 8;
2430
                OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *)
2190
            OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *)
2431
                Rex(0, reg1);
2191
            Rex(0, reg1);
2432
                OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8));
2192
            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8));
2433
                OutIntByte(n) (* bts/btr qword[rbp+n], reg1 *)
2193
            OutIntByte(n); (* bts/btr qword[rbp+n], reg1 *)
2434
            END;
-
 
2435
            (* L: *)
2194
            (* L: *)
2436
            drop
2195
            drop
2437
 
2196
 
2438
        |IL.opLADR_INCLC, IL.opLADR_EXCLC:
2197
        |IL.opLADR_INCLC, IL.opLADR_EXCLC:
2439
            reg1 := GetVarReg(param1);
-
 
2440
            IF reg1 # -1 THEN
-
 
2441
                Rex(reg1, 0);
-
 
2442
                OutByte3(0FH, 0BAH, 0E8H); (* bts/btr reg1, param2 *)
-
 
2443
                OutByte2(reg1 MOD 8 + 8 * ORD(opcode = IL.opLADR_EXCLC), param2)
-
 
2444
            ELSE
-
 
2445
                n := param1 * 8;
2198
            n := param1 * 8;
2446
                OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *)
2199
            OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *)
2447
                OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC));
2200
            OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC));
2448
                OutIntByte(n);
2201
            OutIntByte(n);
2449
                OutByte(param2)
2202
            OutByte(param2)
2450
            END
-
 
2451
 
2203
 
2452
        |IL.opFNAME:
2204
        |IL.opFNAME:
2453
            fname := cmd(IL.FNAMECMD).fname
2205
            fname := cmd(IL.FNAMECMD).fname
2454
 
-
 
2455
        |IL.opLOOP, IL.opENDLOOP:
-
 
2456
 
2206
 
2457
        END;
2207
        END;
2458
 
2208
 
2459
        cmd := cmd.next(COMMAND)
2209
        cmd := cmd.next(COMMAND)
2460
    END;
2210
    END;
2461
 
2211
 
2462
    ASSERT(R.pushed = 0);
2212
    ASSERT(R.pushed = 0);
2463
    ASSERT(R.top = -1);
2213
    ASSERT(R.top = -1);
2464
    ASSERT(xmm = -1)
2214
    ASSERT(xmm = -1)
2465
END translate;
2215
END translate;
2466
 
2216
 
2467
 
2217
 
2468
PROCEDURE prolog (modname: ARRAY OF CHAR; target, stack_size: INTEGER);
2218
PROCEDURE prolog (modname: ARRAY OF CHAR; target, stack_size: INTEGER);
2469
VAR
2219
VAR
2470
    ModName_Offs, entry, L: INTEGER;
2220
    ModName_Offs, entry, L: INTEGER;
2471
 
2221
 
2472
BEGIN
2222
BEGIN
2473
    ModName_Offs := tcount * 8 + CHL.Length(IL.codes.data);
2223
    ModName_Offs := tcount * 8 + CHL.Length(IL.codes.data);
2474
    Numbers_Offs := ModName_Offs + LENGTH(modname) + 1;
2224
    Numbers_Offs := ModName_Offs + LENGTH(modname) + 1;
2475
    ASSERT(UTILS.Align(Numbers_Offs, 16));
2225
    ASSERT(UTILS.Align(Numbers_Offs, 16));
2476
 
2226
 
2477
    entry := NewLabel();
2227
    entry := NewLabel();
2478
    X86.SetLabel(entry);
2228
    X86.SetLabel(entry);
2479
 
2229
 
2480
    IF target = TARGETS.Win64DLL THEN
2230
    IF target = TARGETS.Win64DLL THEN
2481
        dllret := NewLabel();
2231
        dllret := NewLabel();
2482
        push(r8);
2232
        push(r8);
2483
        push(rdx);
2233
        push(rdx);
2484
        push(rcx);
2234
        push(rcx);
2485
        CallRTL(IL._dllentry);
2235
        CallRTL(IL._dllentry);
2486
        test(rax);
2236
        test(rax);
2487
        jcc(je, dllret);
2237
        jcc(je, dllret);
2488
        pushc(0)
2238
        pushc(0)
2489
    ELSIF target = TARGETS.Linux64 THEN
2239
    ELSIF target = TARGETS.Linux64 THEN
2490
        push(rsp)
2240
        push(rsp)
2491
    ELSE
2241
    ELSE
2492
        pushc(0)
2242
        pushc(0)
2493
    END;
2243
    END;
2494
 
2244
 
2495
    lea(rax, entry, sCODE);
2245
    lea(rax, entry, sCODE);
2496
    push(rax);
2246
    push(rax);
2497
    pushDA(0); (* TYPES *)
2247
    pushDA(0); (* TYPES *)
2498
    pushc(tcount);
2248
    pushc(tcount);
2499
    pushDA(ModName_Offs); (* MODNAME *)
2249
    pushDA(ModName_Offs); (* MODNAME *)
2500
    CallRTL(IL._init);
2250
    CallRTL(IL._init);
2501
 
2251
 
2502
    IF target IN {TARGETS.Win64C, TARGETS.Win64GUI, TARGETS.Linux64} THEN
2252
    IF target IN {TARGETS.Win64C, TARGETS.Win64GUI, TARGETS.Linux64} THEN
2503
        L := NewLabel();
2253
        L := NewLabel();
2504
        pushc(0);
2254
        pushc(0);
2505
        push(rsp);
2255
        push(rsp);
2506
        pushc(1024 * 1024 * stack_size);
2256
        pushc(1024 * 1024 * stack_size);
2507
        pushc(0);
2257
        pushc(0);
2508
        CallRTL(IL._new);
2258
        CallRTL(IL._new);
2509
        pop(rax);
2259
        pop(rax);
2510
        test(rax);
2260
        test(rax);
2511
        jcc(je, L);
2261
        jcc(je, L);
2512
        GetRegA;
2262
        GetRegA;
2513
        addrc(rax, 1024 * 1024 * stack_size - 8);
2263
        addrc(rax, 1024 * 1024 * stack_size - 8);
2514
        drop;
2264
        drop;
2515
        mov(rsp, rax);
2265
        mov(rsp, rax);
2516
        X86.SetLabel(L)
2266
        X86.SetLabel(L)
2517
    END
2267
    END
2518
END prolog;
2268
END prolog;
2519
 
2269
 
2520
 
2270
 
2521
PROCEDURE epilog (modname: ARRAY OF CHAR; target: INTEGER);
2271
PROCEDURE epilog (modname: ARRAY OF CHAR; target: INTEGER);
2522
VAR
2272
VAR
2523
    i, n: INTEGER;
2273
    i, n: INTEGER;
2524
    number: Number;
2274
    number: Number;
2525
    exp: IL.EXPORT_PROC;
2275
    exp: IL.EXPORT_PROC;
2526
 
2276
 
2527
 
2277
 
2528
    PROCEDURE _import (imp: LISTS.LIST);
2278
    PROCEDURE _import (imp: LISTS.LIST);
2529
    VAR
2279
    VAR
2530
        lib:  IL.IMPORT_LIB;
2280
        lib:  IL.IMPORT_LIB;
2531
        proc: IL.IMPORT_PROC;
2281
        proc: IL.IMPORT_PROC;
2532
 
2282
 
2533
    BEGIN
2283
    BEGIN
2534
 
2284
 
2535
        lib := imp.first(IL.IMPORT_LIB);
2285
        lib := imp.first(IL.IMPORT_LIB);
2536
        WHILE lib # NIL DO
2286
        WHILE lib # NIL DO
2537
            BIN.Import(prog, lib.name, 0);
2287
            BIN.Import(prog, lib.name, 0);
2538
            proc := lib.procs.first(IL.IMPORT_PROC);
2288
            proc := lib.procs.first(IL.IMPORT_PROC);
2539
            WHILE proc # NIL DO
2289
            WHILE proc # NIL DO
2540
                BIN.Import(prog, proc.name, proc.label);
2290
                BIN.Import(prog, proc.name, proc.label);
2541
                proc := proc.next(IL.IMPORT_PROC)
2291
                proc := proc.next(IL.IMPORT_PROC)
2542
            END;
2292
            END;
2543
            lib := lib.next(IL.IMPORT_LIB)
2293
            lib := lib.next(IL.IMPORT_LIB)
2544
        END
2294
        END
2545
 
2295
 
2546
    END _import;
2296
    END _import;
2547
 
2297
 
2548
 
2298
 
2549
BEGIN
2299
BEGIN
2550
    IF target = TARGETS.Win64DLL THEN
2300
    IF target = TARGETS.Win64DLL THEN
2551
        X86.SetLabel(dllret);
2301
        X86.SetLabel(dllret);
2552
        X86.ret
2302
        X86.ret
2553
    ELSIF target = TARGETS.Linux64SO THEN
2303
    ELSIF target = TARGETS.Linux64SO THEN
2554
        sofinit := NewLabel();
2304
        sofinit := NewLabel();
2555
        X86.ret;
2305
        X86.ret;
2556
        X86.SetLabel(sofinit);
2306
        X86.SetLabel(sofinit);
2557
        CallRTL(IL._sofinit);
2307
        CallRTL(IL._sofinit);
2558
        X86.ret
2308
        X86.ret
2559
    ELSE
2309
    ELSE
2560
        pushc(0);
2310
        pushc(0);
2561
        CallRTL(IL._exit)
2311
        CallRTL(IL._exit)
2562
    END;
2312
    END;
2563
 
2313
 
2564
    X86.fixup;
2314
    X86.fixup;
2565
 
2315
 
2566
    i := 0;
2316
    i := 0;
2567
    WHILE i < tcount DO
2317
    WHILE i < tcount DO
2568
        BIN.PutData64LE(prog, CHL.GetInt(IL.codes.types, i));
2318
        BIN.PutData64LE(prog, CHL.GetInt(IL.codes.types, i));
2569
        INC(i)
2319
        INC(i)
2570
    END;
2320
    END;
2571
 
2321
 
2572
    i := 0;
2322
    i := 0;
2573
    WHILE i < CHL.Length(IL.codes.data) DO
2323
    WHILE i < CHL.Length(IL.codes.data) DO
2574
        BIN.PutData(prog, CHL.GetByte(IL.codes.data, i));
2324
        BIN.PutData(prog, CHL.GetByte(IL.codes.data, i));
2575
        INC(i)
2325
        INC(i)
2576
    END;
2326
    END;
2577
 
2327
 
2578
    BIN.PutDataStr(prog, modname);
2328
    BIN.PutDataStr(prog, modname);
2579
    BIN.PutData(prog, 0);
2329
    BIN.PutData(prog, 0);
2580
    n := CHL.Length(prog.data);
2330
    n := CHL.Length(prog.data);
2581
    ASSERT(UTILS.Align(n, 16));
2331
    ASSERT(UTILS.Align(n, 16));
2582
    i := n - CHL.Length(prog.data);
2332
    i := n - CHL.Length(prog.data);
2583
    WHILE i > 0 DO
2333
    WHILE i > 0 DO
2584
        BIN.PutData(prog, 0);
2334
        BIN.PutData(prog, 0);
2585
        DEC(i)
2335
        DEC(i)
2586
    END;
2336
    END;
2587
    number := Numbers.first(Number);
2337
    number := Numbers.first(Number);
2588
    FOR i := 0 TO Numbers_Count - 1 DO
2338
    FOR i := 0 TO Numbers_Count - 1 DO
2589
        BIN.PutData64LE(prog, number.value);
2339
        BIN.PutData64LE(prog, number.value);
2590
        number := number.next(Number)
2340
        number := number.next(Number)
2591
    END;
2341
    END;
2592
 
2342
 
2593
    exp := IL.codes.export.first(IL.EXPORT_PROC);
2343
    exp := IL.codes.export.first(IL.EXPORT_PROC);
2594
    WHILE exp # NIL DO
2344
    WHILE exp # NIL DO
2595
        BIN.Export(prog, exp.name, exp.label);
2345
        BIN.Export(prog, exp.name, exp.label);
2596
        exp := exp.next(IL.EXPORT_PROC)
2346
        exp := exp.next(IL.EXPORT_PROC)
2597
    END;
2347
    END;
2598
 
2348
 
2599
    _import(IL.codes._import)
2349
    _import(IL.codes._import)
2600
END epilog;
2350
END epilog;
2601
 
2351
 
2602
 
-
 
2603
PROCEDURE rload (reg, offs, size: INTEGER);
-
 
2604
BEGIN
-
 
2605
    offs := offs * 8;
-
 
2606
    CASE size OF
-
 
2607
    |1: movzx(reg, rbp, offs, FALSE)
-
 
2608
    |2: movzx(reg, rbp, offs, TRUE)
-
 
2609
    |4: xor(reg, reg); movrm32(reg, rbp, offs)
-
 
2610
    |8: movrm(reg, rbp, offs)
-
 
2611
    END
-
 
2612
END rload;
-
 
2613
 
-
 
2614
 
-
 
2615
PROCEDURE rsave (reg, offs, size: INTEGER);
-
 
2616
BEGIN
-
 
2617
    offs := offs * 8;
-
 
2618
    CASE size OF
-
 
2619
    |1: X86.movmr8(rbp, offs, reg)
-
 
2620
    |2: X86.movmr16(rbp, offs, reg)
-
 
2621
    |4: movmr32(rbp, offs, reg)
-
 
2622
    |8: movmr(rbp, offs, reg)
-
 
2623
    END
-
 
2624
END rsave;
-
 
2625
 
-
 
2626
 
2352
 
2627
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
2353
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
2628
VAR
2354
VAR
2629
    path, modname, ext: PATHS.PATH;
2355
    path, modname, ext: PATHS.PATH;
2630
 
2356
 
2631
BEGIN
2357
BEGIN
2632
    Xmm[0] := 0;
2358
    Xmm[0] := 0;
2633
    tcount := CHL.Length(IL.codes.types);
2359
    tcount := CHL.Length(IL.codes.types);
2634
 
2360
 
2635
    Win64RegPar[0] := rcx;
2361
    Win64RegPar[0] := rcx;
2636
    Win64RegPar[1] := rdx;
2362
    Win64RegPar[1] := rdx;
2637
    Win64RegPar[2] := r8;
2363
    Win64RegPar[2] := r8;
2638
    Win64RegPar[3] := r9;
2364
    Win64RegPar[3] := r9;
2639
 
2365
 
2640
    SystemVRegPar[0] := rdi;
2366
    SystemVRegPar[0] := rdi;
2641
    SystemVRegPar[1] := rsi;
2367
    SystemVRegPar[1] := rsi;
2642
    SystemVRegPar[2] := rdx;
2368
    SystemVRegPar[2] := rdx;
2643
    SystemVRegPar[3] := rcx;
2369
    SystemVRegPar[3] := rcx;
2644
    SystemVRegPar[4] := r8;
2370
    SystemVRegPar[4] := r8;
2645
    SystemVRegPar[5] := r9;
2371
    SystemVRegPar[5] := r9;
2646
 
2372
 
2647
    PATHS.split(outname, path, modname, ext);
2373
    PATHS.split(outname, path, modname, ext);
2648
    S.append(modname, ext);
2374
    S.append(modname, ext);
2649
 
2375
 
2650
    REG.Init(R, push, pop, mov, xchg, rload, rsave, {rax, r10, r11}, {rcx, rdx, r8, r9});
2376
    REG.Init(R, push, pop, mov, xchg, {rax, rcx, rdx, r8, r9, r10, r11});
2651
 
2377
 
2652
    IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 8)));
2378
    IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 8)));
2653
 
2379
 
2654
    Numbers := LISTS.create(NIL);
2380
    Numbers := LISTS.create(NIL);
2655
    Numbers_Count := 0;
2381
    Numbers_Count := 0;
2656
    NewNumber(ROR(1, 1));      (* 8000000000000000H *)
2382
    NewNumber(ROR(1, 1));      (* 8000000000000000H *)
2657
    NewNumber(0);
2383
    NewNumber(0);
2658
    NewNumber(ROR(-2, 1));     (* 7FFFFFFFFFFFFFFFH *)
2384
    NewNumber(ROR(-2, 1));     (* 7FFFFFFFFFFFFFFFH *)
2659
    NewNumber(-1);
2385
    NewNumber(-1);
2660
    NewNumber(ROR(7FFH, 12));  (* +Infinity *)
2386
    NewNumber(ROR(7FFH, 12));  (* +Infinity *)
2661
    NewNumber(ORD(-BITS(LSR(ASR(ROR(1, 1), 10), 1))));  (* {0..51, 63} *)
2387
    NewNumber(ORD(-BITS(LSR(ASR(ROR(1, 1), 10), 1))));  (* {0..51, 63} *)
2662
    NewNumber(LSR(ASR(ROR(1, 1), 9), 2));  (* {52..61} *)
2388
    NewNumber(LSR(ASR(ROR(1, 1), 9), 2));  (* {52..61} *)
2663
 
2389
 
2664
    prog := BIN.create(IL.codes.lcount);
2390
    prog := BIN.create(IL.codes.lcount);
2665
    BIN.SetParams(prog, IL.codes.bss, 1, WCHR(1), WCHR(0));
2391
    BIN.SetParams(prog, IL.codes.bss, 1, WCHR(1), WCHR(0));
2666
 
2392
 
2667
    X86.SetProgram(prog);
2393
    X86.SetProgram(prog);
2668
 
2394
 
2669
    prolog(modname, target, options.stack);
2395
    prolog(modname, target, options.stack);
2670
    translate(IL.codes.commands, tcount * 8);
2396
    translate(IL.codes.commands, tcount * 8);
2671
    epilog(modname, target);
2397
    epilog(modname, target);
2672
 
2398
 
2673
    BIN.fixup(prog);
2399
    BIN.fixup(prog);
2674
    IF TARGETS.OS = TARGETS.osWIN64 THEN
2400
    IF TARGETS.OS = TARGETS.osWIN64 THEN
2675
        PE32.write(prog, outname, target = TARGETS.Win64C, target = TARGETS.Win64DLL, TRUE)
2401
        PE32.write(prog, outname, target = TARGETS.Win64C, target = TARGETS.Win64DLL, TRUE)
2676
    ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN
2402
    ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN
2677
        ELF.write(prog, outname, sofinit, target = TARGETS.Linux64SO, TRUE)
2403
        ELF.write(prog, outname, sofinit, target = TARGETS.Linux64SO, TRUE)
2678
    END
2404
    END
2679
END CodeGen;
2405
END CodeGen;
2680
 
2406
 
2681
 
2407
 
2682
END AMD64.
2408
END AMD64.