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