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