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