]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/x86.rb
JavaScriptCore-7601.1.46.3.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 57def isWindows
ed1e77d3 58 ENV['OS'] == 'Windows_NT'
81345200
A
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 }
6fe7ccc8
A
1149 when "move"
1150 handleMove
93a37866 1151 when "sxi2q"
81345200
A
1152 if !isIntelSyntax
1153 $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:quad)}"
1154 else
1155 $asm.puts "movsxd #{orderOperands(operands[0].x86Operand(:int), operands[1].x86Operand(:quad))}"
1156 end
93a37866 1157 when "zxi2q"
81345200 1158 $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(operands[0].x86Operand(:int), operands[1].x86Operand(:int))}"
6fe7ccc8
A
1159 when "nop"
1160 $asm.puts "nop"
1161 when "bieq"
1162 handleX86IntBranch("je", :int)
1163 when "bpeq"
1164 handleX86IntBranch("je", :ptr)
93a37866
A
1165 when "bqeq"
1166 handleX86IntBranch("je", :quad)
6fe7ccc8
A
1167 when "bineq"
1168 handleX86IntBranch("jne", :int)
1169 when "bpneq"
1170 handleX86IntBranch("jne", :ptr)
93a37866
A
1171 when "bqneq"
1172 handleX86IntBranch("jne", :quad)
6fe7ccc8
A
1173 when "bia"
1174 handleX86IntBranch("ja", :int)
1175 when "bpa"
1176 handleX86IntBranch("ja", :ptr)
93a37866
A
1177 when "bqa"
1178 handleX86IntBranch("ja", :quad)
6fe7ccc8
A
1179 when "biaeq"
1180 handleX86IntBranch("jae", :int)
1181 when "bpaeq"
1182 handleX86IntBranch("jae", :ptr)
93a37866
A
1183 when "bqaeq"
1184 handleX86IntBranch("jae", :quad)
6fe7ccc8
A
1185 when "bib"
1186 handleX86IntBranch("jb", :int)
1187 when "bpb"
1188 handleX86IntBranch("jb", :ptr)
93a37866
A
1189 when "bqb"
1190 handleX86IntBranch("jb", :quad)
6fe7ccc8
A
1191 when "bibeq"
1192 handleX86IntBranch("jbe", :int)
1193 when "bpbeq"
1194 handleX86IntBranch("jbe", :ptr)
93a37866
A
1195 when "bqbeq"
1196 handleX86IntBranch("jbe", :quad)
6fe7ccc8
A
1197 when "bigt"
1198 handleX86IntBranch("jg", :int)
1199 when "bpgt"
1200 handleX86IntBranch("jg", :ptr)
93a37866
A
1201 when "bqgt"
1202 handleX86IntBranch("jg", :quad)
6fe7ccc8
A
1203 when "bigteq"
1204 handleX86IntBranch("jge", :int)
1205 when "bpgteq"
1206 handleX86IntBranch("jge", :ptr)
93a37866
A
1207 when "bqgteq"
1208 handleX86IntBranch("jge", :quad)
6fe7ccc8
A
1209 when "bilt"
1210 handleX86IntBranch("jl", :int)
1211 when "bplt"
1212 handleX86IntBranch("jl", :ptr)
93a37866
A
1213 when "bqlt"
1214 handleX86IntBranch("jl", :quad)
6fe7ccc8
A
1215 when "bilteq"
1216 handleX86IntBranch("jle", :int)
1217 when "bplteq"
1218 handleX86IntBranch("jle", :ptr)
93a37866
A
1219 when "bqlteq"
1220 handleX86IntBranch("jle", :quad)
6fe7ccc8
A
1221 when "bbeq"
1222 handleX86IntBranch("je", :byte)
1223 when "bbneq"
1224 handleX86IntBranch("jne", :byte)
1225 when "bba"
1226 handleX86IntBranch("ja", :byte)
1227 when "bbaeq"
1228 handleX86IntBranch("jae", :byte)
1229 when "bbb"
1230 handleX86IntBranch("jb", :byte)
1231 when "bbbeq"
1232 handleX86IntBranch("jbe", :byte)
1233 when "bbgt"
1234 handleX86IntBranch("jg", :byte)
1235 when "bbgteq"
1236 handleX86IntBranch("jge", :byte)
1237 when "bblt"
1238 handleX86IntBranch("jl", :byte)
1239 when "bblteq"
1240 handleX86IntBranch("jlteq", :byte)
6fe7ccc8
A
1241 when "btis"
1242 handleX86BranchTest("js", :int)
1243 when "btps"
1244 handleX86BranchTest("js", :ptr)
93a37866
A
1245 when "btqs"
1246 handleX86BranchTest("js", :quad)
6fe7ccc8
A
1247 when "btiz"
1248 handleX86BranchTest("jz", :int)
1249 when "btpz"
1250 handleX86BranchTest("jz", :ptr)
93a37866
A
1251 when "btqz"
1252 handleX86BranchTest("jz", :quad)
6fe7ccc8
A
1253 when "btinz"
1254 handleX86BranchTest("jnz", :int)
1255 when "btpnz"
1256 handleX86BranchTest("jnz", :ptr)
93a37866
A
1257 when "btqnz"
1258 handleX86BranchTest("jnz", :quad)
6fe7ccc8
A
1259 when "btbs"
1260 handleX86BranchTest("js", :byte)
1261 when "btbz"
1262 handleX86BranchTest("jz", :byte)
1263 when "btbnz"
1264 handleX86BranchTest("jnz", :byte)
1265 when "jmp"
1266 $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}"
1267 when "baddio"
81345200 1268 handleX86OpBranch("add#{x86Suffix(:int)}", "jo", :int)
6fe7ccc8
A
1269 when "baddpo"
1270 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
93a37866
A
1271 when "baddqo"
1272 handleX86OpBranch("add#{x86Suffix(:quad)}", "jo", :quad)
6fe7ccc8 1273 when "baddis"
81345200 1274 handleX86OpBranch("add#{x86Suffix(:int)}", "js", :int)
6fe7ccc8
A
1275 when "baddps"
1276 handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
93a37866
A
1277 when "baddqs"
1278 handleX86OpBranch("add#{x86Suffix(:quad)}", "js", :quad)
6fe7ccc8 1279 when "baddiz"
81345200 1280 handleX86OpBranch("add#{x86Suffix(:int)}", "jz", :int)
6fe7ccc8
A
1281 when "baddpz"
1282 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
93a37866
A
1283 when "baddqz"
1284 handleX86OpBranch("add#{x86Suffix(:quad)}", "jz", :quad)
6fe7ccc8 1285 when "baddinz"
81345200 1286 handleX86OpBranch("add#{x86Suffix(:int)}", "jnz", :int)
6fe7ccc8
A
1287 when "baddpnz"
1288 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr)
93a37866
A
1289 when "baddqnz"
1290 handleX86OpBranch("add#{x86Suffix(:quad)}", "jnz", :quad)
6fe7ccc8
A
1291 when "bsubio"
1292 handleX86SubBranch("jo", :int)
1293 when "bsubis"
1294 handleX86SubBranch("js", :int)
1295 when "bsubiz"
1296 handleX86SubBranch("jz", :int)
1297 when "bsubinz"
1298 handleX86SubBranch("jnz", :int)
1299 when "bmulio"
81345200 1300 handleX86OpBranch("imul#{x86Suffix(:int)}", "jo", :int)
6fe7ccc8 1301 when "bmulis"
81345200 1302 handleX86OpBranch("imul#{x86Suffix(:int)}", "js", :int)
6fe7ccc8 1303 when "bmuliz"
81345200 1304 handleX86OpBranch("imul#{x86Suffix(:int)}", "jz", :int)
6fe7ccc8 1305 when "bmulinz"
81345200 1306 handleX86OpBranch("imul#{x86Suffix(:int)}", "jnz", :int)
6fe7ccc8
A
1307 when "borio"
1308 handleX86OpBranch("orl", "jo", :int)
1309 when "boris"
1310 handleX86OpBranch("orl", "js", :int)
1311 when "boriz"
1312 handleX86OpBranch("orl", "jz", :int)
1313 when "borinz"
1314 handleX86OpBranch("orl", "jnz", :int)
1315 when "break"
81345200 1316 $asm.puts "int #{const(3)}"
6fe7ccc8 1317 when "call"
81345200
A
1318 if useX87
1319 2.times {
1320 | offset |
1321 $asm.puts "ffree #{register("st")}(#{offset})"
1322 }
1323 end
1324 op = operands[0].x86CallOperand(:ptr)
1325 if operands[0].is_a? LabelReference
1326 operands[0].used
1327 end
1328 $asm.puts "call #{op}"
6fe7ccc8
A
1329 when "ret"
1330 $asm.puts "ret"
1331 when "cieq"
1332 handleX86IntCompareSet("sete", :int)
1333 when "cbeq"
1334 handleX86IntCompareSet("sete", :byte)
1335 when "cpeq"
1336 handleX86IntCompareSet("sete", :ptr)
93a37866
A
1337 when "cqeq"
1338 handleX86IntCompareSet("sete", :quad)
6fe7ccc8
A
1339 when "cineq"
1340 handleX86IntCompareSet("setne", :int)
1341 when "cbneq"
1342 handleX86IntCompareSet("setne", :byte)
1343 when "cpneq"
1344 handleX86IntCompareSet("setne", :ptr)
93a37866
A
1345 when "cqneq"
1346 handleX86IntCompareSet("setne", :quad)
6fe7ccc8
A
1347 when "cia"
1348 handleX86IntCompareSet("seta", :int)
1349 when "cba"
1350 handleX86IntCompareSet("seta", :byte)
1351 when "cpa"
1352 handleX86IntCompareSet("seta", :ptr)
93a37866
A
1353 when "cqa"
1354 handleX86IntCompareSet("seta", :quad)
6fe7ccc8
A
1355 when "ciaeq"
1356 handleX86IntCompareSet("setae", :int)
1357 when "cbaeq"
1358 handleX86IntCompareSet("setae", :byte)
1359 when "cpaeq"
1360 handleX86IntCompareSet("setae", :ptr)
93a37866
A
1361 when "cqaeq"
1362 handleX86IntCompareSet("setae", :quad)
6fe7ccc8
A
1363 when "cib"
1364 handleX86IntCompareSet("setb", :int)
1365 when "cbb"
1366 handleX86IntCompareSet("setb", :byte)
1367 when "cpb"
1368 handleX86IntCompareSet("setb", :ptr)
93a37866
A
1369 when "cqb"
1370 handleX86IntCompareSet("setb", :quad)
6fe7ccc8
A
1371 when "cibeq"
1372 handleX86IntCompareSet("setbe", :int)
1373 when "cbbeq"
1374 handleX86IntCompareSet("setbe", :byte)
1375 when "cpbeq"
1376 handleX86IntCompareSet("setbe", :ptr)
93a37866
A
1377 when "cqbeq"
1378 handleX86IntCompareSet("setbe", :quad)
6fe7ccc8
A
1379 when "cigt"
1380 handleX86IntCompareSet("setg", :int)
1381 when "cbgt"
1382 handleX86IntCompareSet("setg", :byte)
1383 when "cpgt"
1384 handleX86IntCompareSet("setg", :ptr)
93a37866
A
1385 when "cqgt"
1386 handleX86IntCompareSet("setg", :quad)
6fe7ccc8
A
1387 when "cigteq"
1388 handleX86IntCompareSet("setge", :int)
1389 when "cbgteq"
1390 handleX86IntCompareSet("setge", :byte)
1391 when "cpgteq"
1392 handleX86IntCompareSet("setge", :ptr)
93a37866
A
1393 when "cqgteq"
1394 handleX86IntCompareSet("setge", :quad)
6fe7ccc8
A
1395 when "cilt"
1396 handleX86IntCompareSet("setl", :int)
1397 when "cblt"
1398 handleX86IntCompareSet("setl", :byte)
1399 when "cplt"
1400 handleX86IntCompareSet("setl", :ptr)
93a37866
A
1401 when "cqlt"
1402 handleX86IntCompareSet("setl", :quad)
6fe7ccc8
A
1403 when "cilteq"
1404 handleX86IntCompareSet("setle", :int)
1405 when "cblteq"
1406 handleX86IntCompareSet("setle", :byte)
1407 when "cplteq"
1408 handleX86IntCompareSet("setle", :ptr)
93a37866
A
1409 when "cqlteq"
1410 handleX86IntCompareSet("setle", :quad)
6fe7ccc8
A
1411 when "tis"
1412 handleX86SetTest("sets", :int)
1413 when "tiz"
1414 handleX86SetTest("setz", :int)
1415 when "tinz"
1416 handleX86SetTest("setnz", :int)
6fe7ccc8
A
1417 when "tps"
1418 handleX86SetTest("sets", :ptr)
1419 when "tpz"
1420 handleX86SetTest("setz", :ptr)
1421 when "tpnz"
1422 handleX86SetTest("setnz", :ptr)
93a37866
A
1423 when "tqs"
1424 handleX86SetTest("sets", :quad)
1425 when "tqz"
1426 handleX86SetTest("setz", :quad)
1427 when "tqnz"
1428 handleX86SetTest("setnz", :quad)
6fe7ccc8
A
1429 when "tbs"
1430 handleX86SetTest("sets", :byte)
1431 when "tbz"
1432 handleX86SetTest("setz", :byte)
1433 when "tbnz"
1434 handleX86SetTest("setnz", :byte)
1435 when "peek"
81345200 1436 handleX86Peek()
6fe7ccc8 1437 when "poke"
81345200 1438 handleX86Poke()
6fe7ccc8
A
1439 when "cdqi"
1440 $asm.puts "cdq"
1441 when "idivi"
81345200 1442 $asm.puts "idiv#{x86Suffix(:int)} #{operands[0].x86Operand(:int)}"
6fe7ccc8 1443 when "fii2d"
93a37866
A
1444 if useX87
1445 sp = RegisterID.new(nil, "sp")
81345200
A
1446 $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(operands[0].x86Operand(:int), offsetRegister(-8, sp.x86Operand(:ptr)))}"
1447 $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(operands[1].x86Operand(:int), offsetRegister(-4, sp.x86Operand(:ptr)))}"
1448 $asm.puts "fld#{x86Suffix(:ptr)} #{getSizeString(:double)}#{offsetRegister(-8, sp.x86Operand(:ptr))}"
93a37866
A
1449 $asm.puts "fstp #{operands[2].x87Operand(1)}"
1450 else
1451 $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
1452 $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
1453 $asm.puts "psllq $32, %xmm7"
1454 $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
1455 end
6fe7ccc8 1456 when "fd2ii"
93a37866
A
1457 if useX87
1458 sp = RegisterID.new(nil, "sp")
1459 if (operands[0].x87DefaultStackPosition == 0)
81345200 1460 $asm.puts "fst#{x86Suffix(:ptr)} #{getSizeString(:double)}#{offsetRegister(-8, sp.x86Operand(:ptr))}"
93a37866
A
1461 else
1462 $asm.puts "fld #{operands[0].x87Operand(0)}"
1463 $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
1464 end
81345200
A
1465 $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(offsetRegister(-8, sp.x86Operand(:ptr)), operands[1].x86Operand(:int))}"
1466 $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(offsetRegister(-4, sp.x86Operand(:ptr)), operands[2].x86Operand(:int))}"
93a37866
A
1467 else
1468 $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
1469 $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
1470 $asm.puts "psrlq $32, %xmm7"
1471 $asm.puts "movd %xmm7, #{operands[2].x86Operand(:int)}"
1472 end
1473 when "fq2d"
1474 if useX87
1475 sp = RegisterID.new(nil, "sp")
1476 $asm.puts "movq #{operands[0].x86Operand(:quad)}, -8(#{sp.x86Operand(:ptr)})"
1477 $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})"
1478 $asm.puts "fstp #{operands[1].x87Operand(1)}"
1479 else
81345200
A
1480 if !isIntelSyntax
1481 $asm.puts "movq #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}"
1482 else
1483 # MASM does not accept register operands with movq.
1484 # Debugging shows that movd actually moves a qword when using MASM.
1485 $asm.puts "movd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:quad)}"
1486 end
93a37866
A
1487 end
1488 when "fd2q"
1489 if useX87
1490 sp = RegisterID.new(nil, "sp")
1491 if (operands[0].x87DefaultStackPosition == 0)
81345200 1492 $asm.puts "fst#{x86Suffix(:int)} #{getSizeString(:int)}#{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
1497 $asm.puts "movq -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
1498 else
81345200
A
1499 if !isIntelSyntax
1500 $asm.puts "movq #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}"
1501 else
1502 # MASM does not accept register operands with movq.
1503 # Debugging shows that movd actually moves a qword when using MASM.
1504 $asm.puts "movd #{operands[1].x86Operand(:quad)}, #{operands[0].x86Operand(:double)}"
1505 end
93a37866 1506 end
6fe7ccc8
A
1507 when "bo"
1508 $asm.puts "jo #{operands[0].asmLabel}"
1509 when "bs"
1510 $asm.puts "js #{operands[0].asmLabel}"
1511 when "bz"
1512 $asm.puts "jz #{operands[0].asmLabel}"
1513 when "bnz"
1514 $asm.puts "jnz #{operands[0].asmLabel}"
1515 when "leai"
81345200 1516 $asm.puts "lea#{x86Suffix(:int)} #{orderOperands(operands[0].x86AddressOperand(:int), operands[1].x86Operand(:int))}"
6fe7ccc8 1517 when "leap"
81345200
A
1518 $asm.puts "lea#{x86Suffix(:ptr)} #{orderOperands(operands[0].x86AddressOperand(:ptr), operands[1].x86Operand(:ptr))}"
1519 when "memfence"
1520 $asm.puts "mfence"
6fe7ccc8 1521 else
93a37866 1522 lowerDefault
6fe7ccc8
A
1523 end
1524 end
1525end
1526