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