]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 | 1 | # Copyright (C) 2012 Apple Inc. All rights reserved. |
93a37866 | 2 | # Copyright (C) 2013 Digia Plc. and/or its subsidiary(-ies) |
6fe7ccc8 A |
3 | # |
4 | # Redistribution and use in source and binary forms, with or without | |
5 | # modification, are permitted provided that the following conditions | |
6 | # are met: | |
7 | # 1. Redistributions of source code must retain the above copyright | |
8 | # notice, this list of conditions and the following disclaimer. | |
9 | # 2. Redistributions in binary form must reproduce the above copyright | |
10 | # notice, this list of conditions and the following disclaimer in the | |
11 | # documentation and/or other materials provided with the distribution. | |
12 | # | |
13 | # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | |
14 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
15 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
19 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
20 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
21 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
22 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
23 | # THE POSSIBILITY OF SUCH DAMAGE. | |
24 | ||
93a37866 A |
25 | require "config" |
26 | ||
6fe7ccc8 A |
27 | def isX64 |
28 | case $activeBackend | |
29 | when "X86" | |
30 | false | |
31 | when "X86_64" | |
32 | true | |
33 | else | |
34 | raise "bad value for $activeBackend: #{$activeBackend}" | |
35 | end | |
36 | end | |
37 | ||
93a37866 A |
38 | def useX87 |
39 | case $activeBackend | |
40 | when "X86" | |
41 | true | |
42 | when "X86_64" | |
43 | false | |
44 | else | |
45 | raise "bad value for $activeBackend: #{$activeBackend}" | |
46 | end | |
47 | end | |
48 | ||
49 | class SpecialRegister | |
6fe7ccc8 A |
50 | def x86Operand(kind) |
51 | raise unless @name =~ /^r/ | |
52 | raise unless isX64 | |
53 | case kind | |
54 | when :half | |
55 | "%" + @name + "w" | |
56 | when :int | |
57 | "%" + @name + "d" | |
58 | when :ptr | |
59 | "%" + @name | |
93a37866 A |
60 | when :quad |
61 | "%" + @name | |
6fe7ccc8 A |
62 | else |
63 | raise | |
64 | end | |
65 | end | |
66 | def x86CallOperand(kind) | |
93a37866 A |
67 | # Call operands are not allowed to be partial registers. |
68 | "*#{x86Operand(:quad)}" | |
6fe7ccc8 A |
69 | end |
70 | end | |
71 | ||
72 | X64_SCRATCH_REGISTER = SpecialRegister.new("r11") | |
73 | ||
74 | class RegisterID | |
75 | def supports8BitOnX86 | |
76 | case name | |
77 | when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3" | |
78 | true | |
79 | when "cfr", "ttnr", "tmr" | |
80 | false | |
81 | when "t4", "t5" | |
82 | isX64 | |
83 | else | |
84 | raise | |
85 | end | |
86 | end | |
87 | ||
88 | def x86Operand(kind) | |
89 | case name | |
90 | when "t0", "a0", "r0" | |
91 | case kind | |
92 | when :byte | |
93 | "%al" | |
94 | when :half | |
95 | "%ax" | |
96 | when :int | |
97 | "%eax" | |
98 | when :ptr | |
99 | isX64 ? "%rax" : "%eax" | |
93a37866 A |
100 | when :quad |
101 | isX64 ? "%rax" : raise | |
6fe7ccc8 A |
102 | else |
103 | raise | |
104 | end | |
105 | when "t1", "a1", "r1" | |
106 | case kind | |
107 | when :byte | |
108 | "%dl" | |
109 | when :half | |
110 | "%dx" | |
111 | when :int | |
112 | "%edx" | |
113 | when :ptr | |
114 | isX64 ? "%rdx" : "%edx" | |
93a37866 A |
115 | when :quad |
116 | isX64 ? "%rdx" : raise | |
6fe7ccc8 A |
117 | else |
118 | raise | |
119 | end | |
120 | when "t2" | |
121 | case kind | |
122 | when :byte | |
123 | "%cl" | |
124 | when :half | |
125 | "%cx" | |
126 | when :int | |
127 | "%ecx" | |
128 | when :ptr | |
129 | isX64 ? "%rcx" : "%ecx" | |
93a37866 A |
130 | when :quad |
131 | isX64 ? "%rcx" : raise | |
6fe7ccc8 A |
132 | else |
133 | raise | |
134 | end | |
135 | when "t3" | |
136 | case kind | |
137 | when :byte | |
138 | "%bl" | |
139 | when :half | |
140 | "%bx" | |
141 | when :int | |
142 | "%ebx" | |
143 | when :ptr | |
144 | isX64 ? "%rbx" : "%ebx" | |
93a37866 A |
145 | when :quad |
146 | isX64 ? "%rbx" : raise | |
6fe7ccc8 A |
147 | else |
148 | raise | |
149 | end | |
150 | when "t4" | |
151 | case kind | |
152 | when :byte | |
153 | "%sil" | |
154 | when :half | |
155 | "%si" | |
156 | when :int | |
157 | "%esi" | |
158 | when :ptr | |
159 | isX64 ? "%rsi" : "%esi" | |
93a37866 A |
160 | when :quad |
161 | isX64 ? "%rsi" : raise | |
6fe7ccc8 A |
162 | else |
163 | raise | |
164 | end | |
165 | when "cfr" | |
166 | if isX64 | |
167 | case kind | |
168 | when :half | |
169 | "%r13w" | |
170 | when :int | |
171 | "%r13d" | |
172 | when :ptr | |
173 | "%r13" | |
93a37866 A |
174 | when :quad |
175 | "%r13" | |
6fe7ccc8 A |
176 | else |
177 | raise | |
178 | end | |
179 | else | |
180 | case kind | |
181 | when :byte | |
182 | "%dil" | |
183 | when :half | |
184 | "%di" | |
185 | when :int | |
186 | "%edi" | |
187 | when :ptr | |
188 | "%edi" | |
189 | else | |
190 | raise | |
191 | end | |
192 | end | |
193 | when "sp" | |
194 | case kind | |
195 | when :byte | |
196 | "%spl" | |
197 | when :half | |
198 | "%sp" | |
199 | when :int | |
200 | "%esp" | |
201 | when :ptr | |
202 | isX64 ? "%rsp" : "%esp" | |
93a37866 A |
203 | when :quad |
204 | isX64 ? "%rsp" : raise | |
6fe7ccc8 A |
205 | else |
206 | raise | |
207 | end | |
208 | when "t5" | |
209 | raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 | |
210 | case kind | |
211 | when :byte | |
212 | "%dil" | |
213 | when :half | |
214 | "%di" | |
215 | when :int | |
216 | "%edi" | |
217 | when :ptr | |
218 | "%rdi" | |
93a37866 A |
219 | when :quad |
220 | "%rdi" | |
6fe7ccc8 A |
221 | end |
222 | when "t6" | |
223 | raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 | |
224 | case kind | |
225 | when :half | |
226 | "%r10w" | |
227 | when :int | |
228 | "%r10d" | |
229 | when :ptr | |
230 | "%r10" | |
93a37866 A |
231 | when :quad |
232 | "%r10" | |
6fe7ccc8 A |
233 | end |
234 | when "csr1" | |
235 | raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 | |
236 | case kind | |
237 | when :half | |
238 | "%r14w" | |
239 | when :int | |
240 | "%r14d" | |
241 | when :ptr | |
242 | "%r14" | |
93a37866 A |
243 | when :quad |
244 | "%r14" | |
6fe7ccc8 A |
245 | end |
246 | when "csr2" | |
247 | raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64 | |
248 | case kind | |
249 | when :half | |
250 | "%r15w" | |
251 | when :int | |
252 | "%r15d" | |
253 | when :ptr | |
254 | "%r15" | |
93a37866 A |
255 | when :quad |
256 | "%r15" | |
6fe7ccc8 A |
257 | end |
258 | else | |
259 | raise "Bad register #{name} for X86 at #{codeOriginString}" | |
260 | end | |
261 | end | |
262 | def x86CallOperand(kind) | |
93a37866 | 263 | isX64 ? "*#{x86Operand(:quad)}" : "*#{x86Operand(:ptr)}" |
6fe7ccc8 A |
264 | end |
265 | end | |
266 | ||
267 | class FPRegisterID | |
268 | def x86Operand(kind) | |
269 | raise unless kind == :double | |
93a37866 | 270 | raise if useX87 |
6fe7ccc8 A |
271 | case name |
272 | when "ft0", "fa0", "fr" | |
273 | "%xmm0" | |
274 | when "ft1", "fa1" | |
275 | "%xmm1" | |
276 | when "ft2", "fa2" | |
277 | "%xmm2" | |
278 | when "ft3", "fa3" | |
279 | "%xmm3" | |
280 | when "ft4" | |
281 | "%xmm4" | |
282 | when "ft5" | |
283 | "%xmm5" | |
284 | else | |
285 | raise "Bad register #{name} for X86 at #{codeOriginString}" | |
286 | end | |
287 | end | |
93a37866 A |
288 | def x87DefaultStackPosition |
289 | case name | |
290 | when "ft0", "fr" | |
291 | 0 | |
292 | when "ft1" | |
293 | 1 | |
294 | when "ft2", "ft3", "ft4", "ft5" | |
295 | raise "Unimplemented register #{name} for X86 at #{codeOriginString}" | |
296 | else | |
297 | raise "Bad register #{name} for X86 at #{codeOriginString}" | |
298 | end | |
299 | end | |
300 | def x87Operand(offset) | |
301 | raise unless useX87 | |
302 | raise unless offset == 0 or offset == 1 | |
303 | "%st(#{x87DefaultStackPosition + offset})" | |
304 | end | |
6fe7ccc8 A |
305 | def x86CallOperand(kind) |
306 | "*#{x86Operand(kind)}" | |
307 | end | |
308 | end | |
309 | ||
310 | class Immediate | |
311 | def validX86Immediate? | |
312 | if isX64 | |
313 | value >= -0x80000000 and value <= 0x7fffffff | |
314 | else | |
315 | true | |
316 | end | |
317 | end | |
318 | def x86Operand(kind) | |
319 | "$#{value}" | |
320 | end | |
321 | def x86CallOperand(kind) | |
322 | "#{value}" | |
323 | end | |
324 | end | |
325 | ||
326 | class Address | |
327 | def supports8BitOnX86 | |
328 | true | |
329 | end | |
330 | ||
331 | def x86AddressOperand(addressKind) | |
332 | "#{offset.value}(#{base.x86Operand(addressKind)})" | |
333 | end | |
334 | def x86Operand(kind) | |
335 | x86AddressOperand(:ptr) | |
336 | end | |
337 | def x86CallOperand(kind) | |
338 | "*#{x86Operand(kind)}" | |
339 | end | |
340 | end | |
341 | ||
342 | class BaseIndex | |
343 | def supports8BitOnX86 | |
344 | true | |
345 | end | |
346 | ||
347 | def x86AddressOperand(addressKind) | |
348 | "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})" | |
349 | end | |
350 | ||
351 | def x86Operand(kind) | |
352 | x86AddressOperand(:ptr) | |
353 | end | |
354 | ||
355 | def x86CallOperand(kind) | |
356 | "*#{x86Operand(kind)}" | |
357 | end | |
358 | end | |
359 | ||
360 | class AbsoluteAddress | |
361 | def supports8BitOnX86 | |
362 | true | |
363 | end | |
364 | ||
365 | def x86AddressOperand(addressKind) | |
366 | "#{address.value}" | |
367 | end | |
368 | ||
369 | def x86Operand(kind) | |
370 | "#{address.value}" | |
371 | end | |
372 | ||
373 | def x86CallOperand(kind) | |
374 | "*#{address.value}" | |
375 | end | |
376 | end | |
377 | ||
378 | class LabelReference | |
379 | def x86CallOperand(kind) | |
380 | asmLabel | |
381 | end | |
382 | end | |
383 | ||
384 | class LocalLabelReference | |
385 | def x86CallOperand(kind) | |
386 | asmLabel | |
387 | end | |
388 | end | |
389 | ||
390 | class Sequence | |
391 | def getModifiedListX86_64 | |
392 | newList = [] | |
393 | ||
394 | @list.each { | |
395 | | node | | |
396 | newNode = node | |
397 | if node.is_a? Instruction | |
398 | unless node.opcode == "move" | |
399 | usedScratch = false | |
400 | newOperands = node.operands.map { | |
401 | | operand | | |
402 | if operand.immediate? and not operand.validX86Immediate? | |
403 | if usedScratch | |
404 | raise "Attempt to use scratch register twice at #{operand.codeOriginString}" | |
405 | end | |
406 | newList << Instruction.new(operand.codeOrigin, "move", [operand, X64_SCRATCH_REGISTER]) | |
407 | usedScratch = true | |
408 | X64_SCRATCH_REGISTER | |
409 | else | |
410 | operand | |
411 | end | |
412 | } | |
93a37866 | 413 | newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation) |
6fe7ccc8 A |
414 | end |
415 | else | |
416 | unless node.is_a? Label or | |
417 | node.is_a? LocalLabel or | |
418 | node.is_a? Skip | |
419 | raise "Unexpected #{node.inspect} at #{node.codeOrigin}" | |
420 | end | |
421 | end | |
422 | if newNode | |
423 | newList << newNode | |
424 | end | |
425 | } | |
426 | ||
427 | return newList | |
428 | end | |
429 | end | |
430 | ||
431 | class Instruction | |
432 | def x86Operands(*kinds) | |
433 | raise unless kinds.size == operands.size | |
434 | result = [] | |
435 | kinds.size.times { | |
436 | | idx | | |
437 | result << operands[idx].x86Operand(kinds[idx]) | |
438 | } | |
439 | result.join(", ") | |
440 | end | |
441 | ||
442 | def x86Suffix(kind) | |
443 | case kind | |
444 | when :byte | |
445 | "b" | |
446 | when :half | |
447 | "w" | |
448 | when :int | |
449 | "l" | |
450 | when :ptr | |
451 | isX64 ? "q" : "l" | |
93a37866 A |
452 | when :quad |
453 | isX64 ? "q" : raise | |
6fe7ccc8 | 454 | when :double |
93a37866 | 455 | not useX87 ? "sd" : raise |
6fe7ccc8 A |
456 | else |
457 | raise | |
458 | end | |
459 | end | |
460 | ||
461 | def x86Bytes(kind) | |
462 | case kind | |
463 | when :byte | |
464 | 1 | |
465 | when :half | |
466 | 2 | |
467 | when :int | |
468 | 4 | |
469 | when :ptr | |
470 | isX64 ? 8 : 4 | |
93a37866 A |
471 | when :quad |
472 | isX64 ? 8 : raise | |
6fe7ccc8 A |
473 | when :double |
474 | 8 | |
475 | else | |
476 | raise | |
477 | end | |
478 | end | |
479 | ||
480 | def handleX86OpWithNumOperands(opcode, kind, numOperands) | |
481 | if numOperands == 3 | |
482 | if operands[0] == operands[2] | |
483 | $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
484 | elsif operands[1] == operands[2] | |
485 | $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
486 | else | |
487 | $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
488 | $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
489 | end | |
490 | else | |
491 | $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}" | |
492 | end | |
493 | end | |
494 | ||
495 | def handleX86Op(opcode, kind) | |
496 | handleX86OpWithNumOperands(opcode, kind, operands.size) | |
497 | end | |
498 | ||
499 | def handleX86Shift(opcode, kind) | |
500 | if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2") | |
501 | $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}" | |
502 | else | |
503 | cx = RegisterID.forName(nil, "t2") | |
504 | $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}" | |
505 | $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}" | |
506 | $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}" | |
507 | end | |
508 | end | |
509 | ||
510 | def handleX86DoubleBranch(branchOpcode, mode) | |
93a37866 A |
511 | if useX87 |
512 | handleX87Compare(mode) | |
6fe7ccc8 | 513 | else |
93a37866 A |
514 | case mode |
515 | when :normal | |
516 | $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}" | |
517 | when :reverse | |
518 | $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}" | |
519 | else | |
520 | raise mode.inspect | |
521 | end | |
6fe7ccc8 A |
522 | end |
523 | $asm.puts "#{branchOpcode} #{operands[2].asmLabel}" | |
524 | end | |
525 | ||
526 | def handleX86IntCompare(opcodeSuffix, kind) | |
527 | if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne") | |
528 | $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}" | |
529 | elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne") | |
530 | $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}" | |
531 | else | |
532 | $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}" | |
533 | end | |
534 | end | |
535 | ||
536 | def handleX86IntBranch(branchOpcode, kind) | |
537 | handleX86IntCompare(branchOpcode[1..-1], kind) | |
538 | $asm.puts "#{branchOpcode} #{operands[2].asmLabel}" | |
539 | end | |
540 | ||
541 | def handleX86Set(setOpcode, operand) | |
542 | if operand.supports8BitOnX86 | |
543 | $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}" | |
544 | $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}" | |
545 | else | |
546 | ax = RegisterID.new(nil, "t0") | |
547 | $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}" | |
548 | $asm.puts "#{setOpcode} %al" | |
549 | $asm.puts "movzbl %al, %eax" | |
550 | $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}" | |
551 | end | |
552 | end | |
553 | ||
554 | def handleX86IntCompareSet(setOpcode, kind) | |
555 | handleX86IntCompare(setOpcode[3..-1], kind) | |
556 | handleX86Set(setOpcode, operands[2]) | |
557 | end | |
558 | ||
559 | def handleX86Test(kind) | |
560 | value = operands[0] | |
561 | case operands.size | |
562 | when 2 | |
563 | mask = Immediate.new(codeOrigin, -1) | |
564 | when 3 | |
565 | mask = operands[1] | |
566 | else | |
567 | raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}" | |
568 | end | |
569 | ||
570 | if mask.is_a? Immediate and mask.value == -1 | |
571 | if value.is_a? RegisterID | |
572 | $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}" | |
573 | else | |
574 | $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}" | |
575 | end | |
576 | else | |
577 | $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}" | |
578 | end | |
579 | end | |
580 | ||
581 | def handleX86BranchTest(branchOpcode, kind) | |
582 | handleX86Test(kind) | |
583 | $asm.puts "#{branchOpcode} #{operands.last.asmLabel}" | |
584 | end | |
585 | ||
586 | def handleX86SetTest(setOpcode, kind) | |
587 | handleX86Test(kind) | |
588 | handleX86Set(setOpcode, operands.last) | |
589 | end | |
590 | ||
591 | def handleX86OpBranch(opcode, branchOpcode, kind) | |
592 | handleX86OpWithNumOperands(opcode, kind, operands.size - 1) | |
593 | case operands.size | |
594 | when 4 | |
595 | jumpTarget = operands[3] | |
596 | when 3 | |
597 | jumpTarget = operands[2] | |
598 | else | |
599 | raise self.inspect | |
600 | end | |
601 | $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}" | |
602 | end | |
603 | ||
604 | def handleX86SubBranch(branchOpcode, kind) | |
605 | if operands.size == 4 and operands[1] == operands[2] | |
606 | $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}" | |
607 | $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
608 | else | |
609 | handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1) | |
610 | end | |
611 | case operands.size | |
612 | when 4 | |
613 | jumpTarget = operands[3] | |
614 | when 3 | |
615 | jumpTarget = operands[2] | |
616 | else | |
617 | raise self.inspect | |
618 | end | |
619 | $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}" | |
620 | end | |
93a37866 | 621 | |
6fe7ccc8 | 622 | def handleX86Add(kind) |
93a37866 A |
623 | if operands.size == 3 and operands[1] == operands[2] |
624 | unless Immediate.new(nil, 0) == operands[0] | |
625 | $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
626 | end | |
627 | elsif operands.size == 3 and operands[0].is_a? Immediate | |
6fe7ccc8 A |
628 | raise unless operands[1].is_a? RegisterID |
629 | raise unless operands[2].is_a? RegisterID | |
630 | if operands[0].value == 0 | |
631 | unless operands[1] == operands[2] | |
632 | $asm.puts "mov#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
633 | end | |
634 | else | |
635 | $asm.puts "lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}" | |
636 | end | |
637 | elsif operands.size == 3 and operands[0].is_a? RegisterID | |
638 | raise unless operands[1].is_a? RegisterID | |
639 | raise unless operands[2].is_a? RegisterID | |
93a37866 A |
640 | if operands[0] == operands[2] |
641 | $asm.puts "add#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
642 | else | |
643 | $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}" | |
644 | end | |
6fe7ccc8 A |
645 | else |
646 | unless Immediate.new(nil, 0) == operands[0] | |
647 | $asm.puts "add#{x86Suffix(kind)} #{x86Operands(kind, kind)}" | |
648 | end | |
649 | end | |
650 | end | |
651 | ||
652 | def handleX86Sub(kind) | |
653 | if operands.size == 3 and operands[1] == operands[2] | |
654 | $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}" | |
655 | $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}" | |
656 | else | |
657 | handleX86Op("sub#{x86Suffix(kind)}", kind) | |
658 | end | |
659 | end | |
660 | ||
661 | def handleX86Mul(kind) | |
662 | if operands.size == 3 and operands[0].is_a? Immediate | |
663 | $asm.puts "imul#{x86Suffix(kind)} #{x86Operands(kind, kind, kind)}" | |
664 | else | |
665 | # FIXME: could do some peephole in case the left operand is immediate and it's | |
666 | # a power of two. | |
667 | handleX86Op("imul#{x86Suffix(kind)}", kind) | |
668 | end | |
669 | end | |
670 | ||
671 | def handleMove | |
672 | if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID | |
93a37866 A |
673 | if isX64 |
674 | $asm.puts "xor#{x86Suffix(:quad)} #{operands[1].x86Operand(:quad)}, #{operands[1].x86Operand(:quad)}" | |
675 | else | |
676 | $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}" | |
677 | end | |
6fe7ccc8 | 678 | elsif operands[0] != operands[1] |
93a37866 A |
679 | if isX64 |
680 | $asm.puts "mov#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}" | |
681 | else | |
682 | $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}" | |
683 | end | |
6fe7ccc8 A |
684 | end |
685 | end | |
686 | ||
93a37866 A |
687 | def handleX87Compare(mode) |
688 | case mode | |
689 | when :normal | |
690 | if (operands[0].x87DefaultStackPosition == 0) | |
691 | $asm.puts "fucomi #{operands[1].x87Operand(0)}" | |
692 | else | |
693 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
694 | $asm.puts "fucomip #{operands[1].x87Operand(1)}" | |
695 | end | |
696 | when :reverse | |
697 | if (operands[1].x87DefaultStackPosition == 0) | |
698 | $asm.puts "fucomi #{operands[0].x87Operand(0)}" | |
699 | else | |
700 | $asm.puts "fld #{operands[1].x87Operand(0)}" | |
701 | $asm.puts "fucomip #{operands[0].x87Operand(1)}" | |
702 | end | |
703 | else | |
704 | raise mode.inspect | |
705 | end | |
706 | end | |
707 | ||
708 | def handleX87BinOp(opcode, opcodereverse) | |
709 | if (operands[1].x87DefaultStackPosition == 0) | |
710 | $asm.puts "#{opcode} #{operands[0].x87Operand(0)}, %st" | |
711 | elsif (operands[0].x87DefaultStackPosition == 0) | |
712 | $asm.puts "#{opcodereverse} %st, #{operands[1].x87Operand(0)}" | |
713 | else | |
714 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
715 | $asm.puts "#{opcodereverse}p %st, #{operands[1].x87Operand(1)}" | |
716 | end | |
717 | end | |
718 | ||
6fe7ccc8 A |
719 | def lowerX86 |
720 | raise unless $activeBackend == "X86" | |
721 | lowerX86Common | |
722 | end | |
723 | ||
724 | def lowerX86_64 | |
725 | raise unless $activeBackend == "X86_64" | |
726 | lowerX86Common | |
727 | end | |
728 | ||
729 | def lowerX86Common | |
93a37866 A |
730 | $asm.codeOrigin codeOriginString if $enableCodeOriginComments |
731 | $asm.annotation annotation if $enableInstrAnnotations | |
732 | ||
6fe7ccc8 A |
733 | case opcode |
734 | when "addi" | |
735 | handleX86Add(:int) | |
736 | when "addp" | |
737 | handleX86Add(:ptr) | |
93a37866 A |
738 | when "addq" |
739 | handleX86Add(:quad) | |
6fe7ccc8 A |
740 | when "andi" |
741 | handleX86Op("andl", :int) | |
742 | when "andp" | |
743 | handleX86Op("and#{x86Suffix(:ptr)}", :ptr) | |
93a37866 A |
744 | when "andq" |
745 | handleX86Op("and#{x86Suffix(:quad)}", :quad) | |
6fe7ccc8 A |
746 | when "lshifti" |
747 | handleX86Shift("sall", :int) | |
748 | when "lshiftp" | |
749 | handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr) | |
93a37866 A |
750 | when "lshiftq" |
751 | handleX86Shift("sal#{x86Suffix(:quad)}", :quad) | |
6fe7ccc8 A |
752 | when "muli" |
753 | handleX86Mul(:int) | |
754 | when "mulp" | |
755 | handleX86Mul(:ptr) | |
93a37866 A |
756 | when "mulq" |
757 | handleX86Mul(:quad) | |
6fe7ccc8 A |
758 | when "negi" |
759 | $asm.puts "negl #{x86Operands(:int)}" | |
760 | when "negp" | |
761 | $asm.puts "neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}" | |
93a37866 A |
762 | when "negq" |
763 | $asm.puts "neg#{x86Suffix(:quad)} #{x86Operands(:quad)}" | |
6fe7ccc8 A |
764 | when "noti" |
765 | $asm.puts "notl #{x86Operands(:int)}" | |
766 | when "ori" | |
767 | handleX86Op("orl", :int) | |
768 | when "orp" | |
769 | handleX86Op("or#{x86Suffix(:ptr)}", :ptr) | |
93a37866 A |
770 | when "orq" |
771 | handleX86Op("or#{x86Suffix(:quad)}", :quad) | |
6fe7ccc8 A |
772 | when "rshifti" |
773 | handleX86Shift("sarl", :int) | |
774 | when "rshiftp" | |
775 | handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr) | |
93a37866 A |
776 | when "rshiftq" |
777 | handleX86Shift("sar#{x86Suffix(:quad)}", :quad) | |
6fe7ccc8 A |
778 | when "urshifti" |
779 | handleX86Shift("shrl", :int) | |
780 | when "urshiftp" | |
781 | handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr) | |
93a37866 A |
782 | when "urshiftq" |
783 | handleX86Shift("shr#{x86Suffix(:quad)}", :quad) | |
6fe7ccc8 A |
784 | when "subi" |
785 | handleX86Sub(:int) | |
786 | when "subp" | |
787 | handleX86Sub(:ptr) | |
93a37866 A |
788 | when "subq" |
789 | handleX86Sub(:quad) | |
6fe7ccc8 A |
790 | when "xori" |
791 | handleX86Op("xorl", :int) | |
792 | when "xorp" | |
793 | handleX86Op("xor#{x86Suffix(:ptr)}", :ptr) | |
93a37866 A |
794 | when "xorq" |
795 | handleX86Op("xor#{x86Suffix(:quad)}", :quad) | |
6fe7ccc8 A |
796 | when "loadi", "storei" |
797 | $asm.puts "movl #{x86Operands(:int, :int)}" | |
798 | when "loadis" | |
799 | if isX64 | |
93a37866 | 800 | $asm.puts "movslq #{x86Operands(:int, :quad)}" |
6fe7ccc8 A |
801 | else |
802 | $asm.puts "movl #{x86Operands(:int, :int)}" | |
803 | end | |
804 | when "loadp", "storep" | |
805 | $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}" | |
93a37866 A |
806 | when "loadq", "storeq" |
807 | $asm.puts "mov#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}" | |
6fe7ccc8 A |
808 | when "loadb" |
809 | $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}" | |
810 | when "loadbs" | |
811 | $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}" | |
812 | when "loadh" | |
813 | $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}" | |
814 | when "loadhs" | |
815 | $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}" | |
816 | when "storeb" | |
817 | $asm.puts "movb #{x86Operands(:byte, :byte)}" | |
93a37866 A |
818 | when "loadd" |
819 | if useX87 | |
820 | $asm.puts "fldl #{operands[0].x86Operand(:double)}" | |
821 | $asm.puts "fstp #{operands[1].x87Operand(1)}" | |
822 | else | |
823 | $asm.puts "movsd #{x86Operands(:double, :double)}" | |
824 | end | |
825 | when "moved" | |
826 | if useX87 | |
827 | if (operands[0].x87DefaultStackPosition == 0) | |
828 | $asm.puts "fst #{operands[1].x87Operand(0)}" | |
829 | else | |
830 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
831 | $asm.puts "fstp #{operands[1].x87Operand(1)}" | |
832 | end | |
833 | else | |
834 | $asm.puts "movsd #{x86Operands(:double, :double)}" | |
835 | end | |
836 | when "stored" | |
837 | if useX87 | |
838 | if (operands[0].x87DefaultStackPosition == 0) | |
839 | $asm.puts "fstl #{operands[1].x86Operand(:double)}" | |
840 | else | |
841 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
842 | $asm.puts "fstpl #{operands[1].x86Operand(:double)}" | |
843 | end | |
844 | else | |
845 | $asm.puts "movsd #{x86Operands(:double, :double)}" | |
846 | end | |
6fe7ccc8 | 847 | when "addd" |
93a37866 A |
848 | if useX87 |
849 | handleX87BinOp("fadd", "fadd") | |
850 | else | |
851 | $asm.puts "addsd #{x86Operands(:double, :double)}" | |
852 | end | |
6fe7ccc8 | 853 | when "muld" |
93a37866 A |
854 | if useX87 |
855 | handleX87BinOp("fmul", "fmul") | |
856 | else | |
857 | $asm.puts "mulsd #{x86Operands(:double, :double)}" | |
858 | end | |
859 | when "subd" | |
860 | if useX87 | |
861 | handleX87BinOp("fsub", "fsubr") | |
862 | else | |
863 | $asm.puts "subsd #{x86Operands(:double, :double)}" | |
864 | end | |
865 | when "divd" | |
866 | if useX87 | |
867 | handleX87BinOp("fdiv", "fdivr") | |
868 | else | |
869 | $asm.puts "divsd #{x86Operands(:double, :double)}" | |
870 | end | |
6fe7ccc8 | 871 | when "sqrtd" |
93a37866 A |
872 | if useX87 |
873 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
874 | $asm.puts "fsqrtl" | |
875 | $asm.puts "fstp #{operands[1].x87Operand(1)}" | |
876 | else | |
877 | $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}" | |
878 | end | |
6fe7ccc8 | 879 | when "ci2d" |
93a37866 A |
880 | if useX87 |
881 | sp = RegisterID.new(nil, "sp") | |
882 | $asm.puts "movl #{operands[0].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})" | |
883 | $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})" | |
884 | $asm.puts "fstp #{operands[1].x87Operand(1)}" | |
885 | else | |
886 | $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}" | |
887 | end | |
6fe7ccc8 | 888 | when "bdeq" |
93a37866 A |
889 | if useX87 |
890 | handleX87Compare(:normal) | |
891 | else | |
892 | $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}" | |
893 | end | |
894 | if operands[0] == operands[1] | |
895 | # This is just a jump ordered, which is a jnp. | |
896 | $asm.puts "jnp #{operands[2].asmLabel}" | |
897 | else | |
898 | isUnordered = LocalLabel.unique("bdeq") | |
899 | $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}" | |
900 | $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}" | |
901 | isUnordered.lower("X86") | |
902 | end | |
6fe7ccc8 A |
903 | when "bdneq" |
904 | handleX86DoubleBranch("jne", :normal) | |
905 | when "bdgt" | |
906 | handleX86DoubleBranch("ja", :normal) | |
907 | when "bdgteq" | |
908 | handleX86DoubleBranch("jae", :normal) | |
909 | when "bdlt" | |
910 | handleX86DoubleBranch("ja", :reverse) | |
911 | when "bdlteq" | |
912 | handleX86DoubleBranch("jae", :reverse) | |
913 | when "bdequn" | |
914 | handleX86DoubleBranch("je", :normal) | |
915 | when "bdnequn" | |
93a37866 A |
916 | if useX87 |
917 | handleX87Compare(:normal) | |
918 | else | |
919 | $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}" | |
920 | end | |
921 | if operands[0] == operands[1] | |
922 | # This is just a jump unordered, which is a jp. | |
923 | $asm.puts "jp #{operands[2].asmLabel}" | |
924 | else | |
925 | isUnordered = LocalLabel.unique("bdnequn") | |
926 | isEqual = LocalLabel.unique("bdnequn") | |
927 | $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}" | |
928 | $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}" | |
929 | isUnordered.lower("X86") | |
930 | $asm.puts "jmp #{operands[2].asmLabel}" | |
931 | isEqual.lower("X86") | |
932 | end | |
6fe7ccc8 A |
933 | when "bdgtun" |
934 | handleX86DoubleBranch("jb", :reverse) | |
935 | when "bdgtequn" | |
936 | handleX86DoubleBranch("jbe", :reverse) | |
937 | when "bdltun" | |
938 | handleX86DoubleBranch("jb", :normal) | |
939 | when "bdltequn" | |
940 | handleX86DoubleBranch("jbe", :normal) | |
941 | when "btd2i" | |
93a37866 A |
942 | # FIXME: unused and unimplemented for x87 |
943 | raise if useX87 | |
6fe7ccc8 A |
944 | $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}" |
945 | $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}" | |
946 | $asm.puts "je #{operands[2].asmLabel}" | |
947 | when "td2i" | |
93a37866 A |
948 | # FIXME: unused and unimplemented for x87 |
949 | raise if useX87 | |
6fe7ccc8 A |
950 | $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}" |
951 | when "bcd2i" | |
93a37866 A |
952 | if useX87 |
953 | sp = RegisterID.new(nil, "sp") | |
954 | if (operands[0].x87DefaultStackPosition == 0) | |
955 | $asm.puts "fistl -4(#{sp.x86Operand(:ptr)})" | |
956 | else | |
957 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
958 | $asm.puts "fistpl -4(#{sp.x86Operand(:ptr)})" | |
959 | end | |
960 | $asm.puts "movl -4(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}" | |
961 | $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}" | |
962 | $asm.puts "je #{operands[2].asmLabel}" | |
963 | $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})" | |
964 | $asm.puts "fucomip #{operands[0].x87Operand(1)}" | |
965 | $asm.puts "jp #{operands[2].asmLabel}" | |
966 | $asm.puts "jne #{operands[2].asmLabel}" | |
967 | else | |
968 | $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}" | |
969 | $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}" | |
970 | $asm.puts "je #{operands[2].asmLabel}" | |
971 | $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7" | |
972 | $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7" | |
973 | $asm.puts "jp #{operands[2].asmLabel}" | |
974 | $asm.puts "jne #{operands[2].asmLabel}" | |
975 | end | |
6fe7ccc8 | 976 | when "movdz" |
93a37866 A |
977 | if useX87 |
978 | $asm.puts "fldzl" | |
979 | $asm.puts "fstp #{operands[0].x87Operand(1)}" | |
980 | else | |
981 | $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}" | |
982 | end | |
6fe7ccc8 A |
983 | when "pop" |
984 | $asm.puts "pop #{operands[0].x86Operand(:ptr)}" | |
985 | when "push" | |
986 | $asm.puts "push #{operands[0].x86Operand(:ptr)}" | |
987 | when "move" | |
988 | handleMove | |
93a37866 A |
989 | when "sxi2q" |
990 | $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:quad)}" | |
991 | when "zxi2q" | |
992 | $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}" | |
6fe7ccc8 A |
993 | when "nop" |
994 | $asm.puts "nop" | |
995 | when "bieq" | |
996 | handleX86IntBranch("je", :int) | |
997 | when "bpeq" | |
998 | handleX86IntBranch("je", :ptr) | |
93a37866 A |
999 | when "bqeq" |
1000 | handleX86IntBranch("je", :quad) | |
6fe7ccc8 A |
1001 | when "bineq" |
1002 | handleX86IntBranch("jne", :int) | |
1003 | when "bpneq" | |
1004 | handleX86IntBranch("jne", :ptr) | |
93a37866 A |
1005 | when "bqneq" |
1006 | handleX86IntBranch("jne", :quad) | |
6fe7ccc8 A |
1007 | when "bia" |
1008 | handleX86IntBranch("ja", :int) | |
1009 | when "bpa" | |
1010 | handleX86IntBranch("ja", :ptr) | |
93a37866 A |
1011 | when "bqa" |
1012 | handleX86IntBranch("ja", :quad) | |
6fe7ccc8 A |
1013 | when "biaeq" |
1014 | handleX86IntBranch("jae", :int) | |
1015 | when "bpaeq" | |
1016 | handleX86IntBranch("jae", :ptr) | |
93a37866 A |
1017 | when "bqaeq" |
1018 | handleX86IntBranch("jae", :quad) | |
6fe7ccc8 A |
1019 | when "bib" |
1020 | handleX86IntBranch("jb", :int) | |
1021 | when "bpb" | |
1022 | handleX86IntBranch("jb", :ptr) | |
93a37866 A |
1023 | when "bqb" |
1024 | handleX86IntBranch("jb", :quad) | |
6fe7ccc8 A |
1025 | when "bibeq" |
1026 | handleX86IntBranch("jbe", :int) | |
1027 | when "bpbeq" | |
1028 | handleX86IntBranch("jbe", :ptr) | |
93a37866 A |
1029 | when "bqbeq" |
1030 | handleX86IntBranch("jbe", :quad) | |
6fe7ccc8 A |
1031 | when "bigt" |
1032 | handleX86IntBranch("jg", :int) | |
1033 | when "bpgt" | |
1034 | handleX86IntBranch("jg", :ptr) | |
93a37866 A |
1035 | when "bqgt" |
1036 | handleX86IntBranch("jg", :quad) | |
6fe7ccc8 A |
1037 | when "bigteq" |
1038 | handleX86IntBranch("jge", :int) | |
1039 | when "bpgteq" | |
1040 | handleX86IntBranch("jge", :ptr) | |
93a37866 A |
1041 | when "bqgteq" |
1042 | handleX86IntBranch("jge", :quad) | |
6fe7ccc8 A |
1043 | when "bilt" |
1044 | handleX86IntBranch("jl", :int) | |
1045 | when "bplt" | |
1046 | handleX86IntBranch("jl", :ptr) | |
93a37866 A |
1047 | when "bqlt" |
1048 | handleX86IntBranch("jl", :quad) | |
6fe7ccc8 A |
1049 | when "bilteq" |
1050 | handleX86IntBranch("jle", :int) | |
1051 | when "bplteq" | |
1052 | handleX86IntBranch("jle", :ptr) | |
93a37866 A |
1053 | when "bqlteq" |
1054 | handleX86IntBranch("jle", :quad) | |
6fe7ccc8 A |
1055 | when "bbeq" |
1056 | handleX86IntBranch("je", :byte) | |
1057 | when "bbneq" | |
1058 | handleX86IntBranch("jne", :byte) | |
1059 | when "bba" | |
1060 | handleX86IntBranch("ja", :byte) | |
1061 | when "bbaeq" | |
1062 | handleX86IntBranch("jae", :byte) | |
1063 | when "bbb" | |
1064 | handleX86IntBranch("jb", :byte) | |
1065 | when "bbbeq" | |
1066 | handleX86IntBranch("jbe", :byte) | |
1067 | when "bbgt" | |
1068 | handleX86IntBranch("jg", :byte) | |
1069 | when "bbgteq" | |
1070 | handleX86IntBranch("jge", :byte) | |
1071 | when "bblt" | |
1072 | handleX86IntBranch("jl", :byte) | |
1073 | when "bblteq" | |
1074 | handleX86IntBranch("jlteq", :byte) | |
6fe7ccc8 A |
1075 | when "btis" |
1076 | handleX86BranchTest("js", :int) | |
1077 | when "btps" | |
1078 | handleX86BranchTest("js", :ptr) | |
93a37866 A |
1079 | when "btqs" |
1080 | handleX86BranchTest("js", :quad) | |
6fe7ccc8 A |
1081 | when "btiz" |
1082 | handleX86BranchTest("jz", :int) | |
1083 | when "btpz" | |
1084 | handleX86BranchTest("jz", :ptr) | |
93a37866 A |
1085 | when "btqz" |
1086 | handleX86BranchTest("jz", :quad) | |
6fe7ccc8 A |
1087 | when "btinz" |
1088 | handleX86BranchTest("jnz", :int) | |
1089 | when "btpnz" | |
1090 | handleX86BranchTest("jnz", :ptr) | |
93a37866 A |
1091 | when "btqnz" |
1092 | handleX86BranchTest("jnz", :quad) | |
6fe7ccc8 A |
1093 | when "btbs" |
1094 | handleX86BranchTest("js", :byte) | |
1095 | when "btbz" | |
1096 | handleX86BranchTest("jz", :byte) | |
1097 | when "btbnz" | |
1098 | handleX86BranchTest("jnz", :byte) | |
1099 | when "jmp" | |
1100 | $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}" | |
1101 | when "baddio" | |
1102 | handleX86OpBranch("addl", "jo", :int) | |
1103 | when "baddpo" | |
1104 | handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr) | |
93a37866 A |
1105 | when "baddqo" |
1106 | handleX86OpBranch("add#{x86Suffix(:quad)}", "jo", :quad) | |
6fe7ccc8 A |
1107 | when "baddis" |
1108 | handleX86OpBranch("addl", "js", :int) | |
1109 | when "baddps" | |
1110 | handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr) | |
93a37866 A |
1111 | when "baddqs" |
1112 | handleX86OpBranch("add#{x86Suffix(:quad)}", "js", :quad) | |
6fe7ccc8 A |
1113 | when "baddiz" |
1114 | handleX86OpBranch("addl", "jz", :int) | |
1115 | when "baddpz" | |
1116 | handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr) | |
93a37866 A |
1117 | when "baddqz" |
1118 | handleX86OpBranch("add#{x86Suffix(:quad)}", "jz", :quad) | |
6fe7ccc8 A |
1119 | when "baddinz" |
1120 | handleX86OpBranch("addl", "jnz", :int) | |
1121 | when "baddpnz" | |
1122 | handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr) | |
93a37866 A |
1123 | when "baddqnz" |
1124 | handleX86OpBranch("add#{x86Suffix(:quad)}", "jnz", :quad) | |
6fe7ccc8 A |
1125 | when "bsubio" |
1126 | handleX86SubBranch("jo", :int) | |
1127 | when "bsubis" | |
1128 | handleX86SubBranch("js", :int) | |
1129 | when "bsubiz" | |
1130 | handleX86SubBranch("jz", :int) | |
1131 | when "bsubinz" | |
1132 | handleX86SubBranch("jnz", :int) | |
1133 | when "bmulio" | |
1134 | handleX86OpBranch("imull", "jo", :int) | |
1135 | when "bmulis" | |
1136 | handleX86OpBranch("imull", "js", :int) | |
1137 | when "bmuliz" | |
1138 | handleX86OpBranch("imull", "jz", :int) | |
1139 | when "bmulinz" | |
1140 | handleX86OpBranch("imull", "jnz", :int) | |
1141 | when "borio" | |
1142 | handleX86OpBranch("orl", "jo", :int) | |
1143 | when "boris" | |
1144 | handleX86OpBranch("orl", "js", :int) | |
1145 | when "boriz" | |
1146 | handleX86OpBranch("orl", "jz", :int) | |
1147 | when "borinz" | |
1148 | handleX86OpBranch("orl", "jnz", :int) | |
1149 | when "break" | |
1150 | $asm.puts "int $3" | |
1151 | when "call" | |
1152 | $asm.puts "call #{operands[0].x86CallOperand(:ptr)}" | |
1153 | when "ret" | |
1154 | $asm.puts "ret" | |
1155 | when "cieq" | |
1156 | handleX86IntCompareSet("sete", :int) | |
1157 | when "cbeq" | |
1158 | handleX86IntCompareSet("sete", :byte) | |
1159 | when "cpeq" | |
1160 | handleX86IntCompareSet("sete", :ptr) | |
93a37866 A |
1161 | when "cqeq" |
1162 | handleX86IntCompareSet("sete", :quad) | |
6fe7ccc8 A |
1163 | when "cineq" |
1164 | handleX86IntCompareSet("setne", :int) | |
1165 | when "cbneq" | |
1166 | handleX86IntCompareSet("setne", :byte) | |
1167 | when "cpneq" | |
1168 | handleX86IntCompareSet("setne", :ptr) | |
93a37866 A |
1169 | when "cqneq" |
1170 | handleX86IntCompareSet("setne", :quad) | |
6fe7ccc8 A |
1171 | when "cia" |
1172 | handleX86IntCompareSet("seta", :int) | |
1173 | when "cba" | |
1174 | handleX86IntCompareSet("seta", :byte) | |
1175 | when "cpa" | |
1176 | handleX86IntCompareSet("seta", :ptr) | |
93a37866 A |
1177 | when "cqa" |
1178 | handleX86IntCompareSet("seta", :quad) | |
6fe7ccc8 A |
1179 | when "ciaeq" |
1180 | handleX86IntCompareSet("setae", :int) | |
1181 | when "cbaeq" | |
1182 | handleX86IntCompareSet("setae", :byte) | |
1183 | when "cpaeq" | |
1184 | handleX86IntCompareSet("setae", :ptr) | |
93a37866 A |
1185 | when "cqaeq" |
1186 | handleX86IntCompareSet("setae", :quad) | |
6fe7ccc8 A |
1187 | when "cib" |
1188 | handleX86IntCompareSet("setb", :int) | |
1189 | when "cbb" | |
1190 | handleX86IntCompareSet("setb", :byte) | |
1191 | when "cpb" | |
1192 | handleX86IntCompareSet("setb", :ptr) | |
93a37866 A |
1193 | when "cqb" |
1194 | handleX86IntCompareSet("setb", :quad) | |
6fe7ccc8 A |
1195 | when "cibeq" |
1196 | handleX86IntCompareSet("setbe", :int) | |
1197 | when "cbbeq" | |
1198 | handleX86IntCompareSet("setbe", :byte) | |
1199 | when "cpbeq" | |
1200 | handleX86IntCompareSet("setbe", :ptr) | |
93a37866 A |
1201 | when "cqbeq" |
1202 | handleX86IntCompareSet("setbe", :quad) | |
6fe7ccc8 A |
1203 | when "cigt" |
1204 | handleX86IntCompareSet("setg", :int) | |
1205 | when "cbgt" | |
1206 | handleX86IntCompareSet("setg", :byte) | |
1207 | when "cpgt" | |
1208 | handleX86IntCompareSet("setg", :ptr) | |
93a37866 A |
1209 | when "cqgt" |
1210 | handleX86IntCompareSet("setg", :quad) | |
6fe7ccc8 A |
1211 | when "cigteq" |
1212 | handleX86IntCompareSet("setge", :int) | |
1213 | when "cbgteq" | |
1214 | handleX86IntCompareSet("setge", :byte) | |
1215 | when "cpgteq" | |
1216 | handleX86IntCompareSet("setge", :ptr) | |
93a37866 A |
1217 | when "cqgteq" |
1218 | handleX86IntCompareSet("setge", :quad) | |
6fe7ccc8 A |
1219 | when "cilt" |
1220 | handleX86IntCompareSet("setl", :int) | |
1221 | when "cblt" | |
1222 | handleX86IntCompareSet("setl", :byte) | |
1223 | when "cplt" | |
1224 | handleX86IntCompareSet("setl", :ptr) | |
93a37866 A |
1225 | when "cqlt" |
1226 | handleX86IntCompareSet("setl", :quad) | |
6fe7ccc8 A |
1227 | when "cilteq" |
1228 | handleX86IntCompareSet("setle", :int) | |
1229 | when "cblteq" | |
1230 | handleX86IntCompareSet("setle", :byte) | |
1231 | when "cplteq" | |
1232 | handleX86IntCompareSet("setle", :ptr) | |
93a37866 A |
1233 | when "cqlteq" |
1234 | handleX86IntCompareSet("setle", :quad) | |
6fe7ccc8 A |
1235 | when "tis" |
1236 | handleX86SetTest("sets", :int) | |
1237 | when "tiz" | |
1238 | handleX86SetTest("setz", :int) | |
1239 | when "tinz" | |
1240 | handleX86SetTest("setnz", :int) | |
6fe7ccc8 A |
1241 | when "tps" |
1242 | handleX86SetTest("sets", :ptr) | |
1243 | when "tpz" | |
1244 | handleX86SetTest("setz", :ptr) | |
1245 | when "tpnz" | |
1246 | handleX86SetTest("setnz", :ptr) | |
93a37866 A |
1247 | when "tqs" |
1248 | handleX86SetTest("sets", :quad) | |
1249 | when "tqz" | |
1250 | handleX86SetTest("setz", :quad) | |
1251 | when "tqnz" | |
1252 | handleX86SetTest("setnz", :quad) | |
6fe7ccc8 A |
1253 | when "tbs" |
1254 | handleX86SetTest("sets", :byte) | |
1255 | when "tbz" | |
1256 | handleX86SetTest("setz", :byte) | |
1257 | when "tbnz" | |
1258 | handleX86SetTest("setnz", :byte) | |
1259 | when "peek" | |
1260 | sp = RegisterID.new(nil, "sp") | |
1261 | $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}" | |
93a37866 A |
1262 | when "peekq" |
1263 | sp = RegisterID.new(nil, "sp") | |
1264 | $asm.puts "mov#{x86Suffix(:quad)} #{operands[0].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}" | |
6fe7ccc8 A |
1265 | when "poke" |
1266 | sp = RegisterID.new(nil, "sp") | |
1267 | $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})" | |
93a37866 A |
1268 | when "pokeq" |
1269 | sp = RegisterID.new(nil, "sp") | |
1270 | $asm.puts "mov#{x86Suffix(:quad)} #{operands[0].x86Operand(:quad)}, #{operands[1].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)})" | |
6fe7ccc8 A |
1271 | when "cdqi" |
1272 | $asm.puts "cdq" | |
1273 | when "idivi" | |
1274 | $asm.puts "idivl #{operands[0].x86Operand(:int)}" | |
1275 | when "fii2d" | |
93a37866 A |
1276 | if useX87 |
1277 | sp = RegisterID.new(nil, "sp") | |
1278 | $asm.puts "movl #{operands[0].x86Operand(:int)}, -8(#{sp.x86Operand(:ptr)})" | |
1279 | $asm.puts "movl #{operands[1].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})" | |
1280 | $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})" | |
1281 | $asm.puts "fstp #{operands[2].x87Operand(1)}" | |
1282 | else | |
1283 | $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}" | |
1284 | $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7" | |
1285 | $asm.puts "psllq $32, %xmm7" | |
1286 | $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}" | |
1287 | end | |
6fe7ccc8 | 1288 | when "fd2ii" |
93a37866 A |
1289 | if useX87 |
1290 | sp = RegisterID.new(nil, "sp") | |
1291 | if (operands[0].x87DefaultStackPosition == 0) | |
1292 | $asm.puts "fstl -8(#{sp.x86Operand(:ptr)})" | |
1293 | else | |
1294 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
1295 | $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})" | |
1296 | end | |
1297 | $asm.puts "movl -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}" | |
1298 | $asm.puts "movl -4(#{sp.x86Operand(:ptr)}), #{operands[2].x86Operand(:int)}" | |
1299 | else | |
1300 | $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}" | |
1301 | $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7" | |
1302 | $asm.puts "psrlq $32, %xmm7" | |
1303 | $asm.puts "movd %xmm7, #{operands[2].x86Operand(:int)}" | |
1304 | end | |
1305 | when "fq2d" | |
1306 | if useX87 | |
1307 | sp = RegisterID.new(nil, "sp") | |
1308 | $asm.puts "movq #{operands[0].x86Operand(:quad)}, -8(#{sp.x86Operand(:ptr)})" | |
1309 | $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})" | |
1310 | $asm.puts "fstp #{operands[1].x87Operand(1)}" | |
1311 | else | |
1312 | $asm.puts "movq #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}" | |
1313 | end | |
1314 | when "fd2q" | |
1315 | if useX87 | |
1316 | sp = RegisterID.new(nil, "sp") | |
1317 | if (operands[0].x87DefaultStackPosition == 0) | |
1318 | $asm.puts "fstl -8(#{sp.x86Operand(:ptr)})" | |
1319 | else | |
1320 | $asm.puts "fld #{operands[0].x87Operand(0)}" | |
1321 | $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})" | |
1322 | end | |
1323 | $asm.puts "movq -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}" | |
1324 | else | |
1325 | $asm.puts "movq #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}" | |
1326 | end | |
6fe7ccc8 A |
1327 | when "bo" |
1328 | $asm.puts "jo #{operands[0].asmLabel}" | |
1329 | when "bs" | |
1330 | $asm.puts "js #{operands[0].asmLabel}" | |
1331 | when "bz" | |
1332 | $asm.puts "jz #{operands[0].asmLabel}" | |
1333 | when "bnz" | |
1334 | $asm.puts "jnz #{operands[0].asmLabel}" | |
1335 | when "leai" | |
1336 | $asm.puts "leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}" | |
1337 | when "leap" | |
1338 | $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}" | |
93a37866 A |
1339 | when "resetX87Stack" |
1340 | if useX87 | |
1341 | 2.times { | |
1342 | | offset | | |
1343 | $asm.puts "ffree %st(#{offset})" | |
1344 | } | |
1345 | end | |
6fe7ccc8 | 1346 | else |
93a37866 | 1347 | lowerDefault |
6fe7ccc8 A |
1348 | end |
1349 | end | |
1350 | end | |
1351 |