[Qt]REGRESSION(r92254): It made 2 tests timeout
[WebKit-https.git] / Source / JavaScriptCore / offlineasm / x86.rb
1 # Copyright (C) 2011 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 #    notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 #    notice, this list of conditions and the following disclaimer in the
10 #    documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22 # THE POSSIBILITY OF SUCH DAMAGE.
23
24 class RegisterID
25     def supports8BitOnX86
26         case name
27         when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
28             true
29         when "t4", "cfr"
30             false
31         else
32             raise
33         end
34     end
35     
36     def x86Operand(kind)
37         case name
38         when "t0", "a0", "r0"
39             case kind
40             when :byte
41                 "%al"
42             when :half
43                 "%ax"
44             when :int
45                 "%eax"
46             else
47                 raise
48             end
49         when "t1", "a1", "r1"
50             case kind
51             when :byte
52                 "%dl"
53             when :half
54                 "%dx"
55             when :int
56                 "%edx"
57             else
58                 raise
59             end
60         when "t2"
61             case kind
62             when :byte
63                 "%cl"
64             when :half
65                 "%cx"
66             when :int
67                 "%ecx"
68             else
69                 raise
70             end
71         when "t3"
72             case kind
73             when :byte
74                 "%bl"
75             when :half
76                 "%bx"
77             when :int
78                 "%ebx"
79             else
80                 raise
81             end
82         when "t4"
83             case kind
84             when :byte
85                 "%sil"
86             when :half
87                 "%si"
88             when :int
89                 "%esi"
90             else
91                 raise
92             end
93         when "cfr"
94             case kind
95             when :byte
96                 "%dil"
97             when :half
98                 "%di"
99             when :int
100                 "%edi"
101             else
102                 raise
103             end
104         when "sp"
105             case kind
106             when :byte
107                 "%spl"
108             when :half
109                 "%sp"
110             when :int
111                 "%esp"
112             else
113                 raise
114             end
115         else
116             raise "Bad register #{name} for X86 at #{codeOriginString}"
117         end
118     end
119     def x86CallOperand(kind)
120         "*#{x86Operand(kind)}"
121     end
122 end
123
124 class FPRegisterID
125     def x86Operand(kind)
126         raise unless kind == :double
127         case name
128         when "ft0", "fa0", "fr"
129             "%xmm0"
130         when "ft1", "fa1"
131             "%xmm1"
132         when "ft2", "fa2"
133             "%xmm2"
134         when "ft3", "fa3"
135             "%xmm3"
136         when "ft4"
137             "%xmm4"
138         when "ft5"
139             "%xmm5"
140         else
141             raise "Bad register #{name} for X86 at #{codeOriginString}"
142         end
143     end
144     def x86CallOperand(kind)
145         "*#{x86Operand(kind)}"
146     end
147 end
148
149 class Immediate
150     def x86Operand(kind)
151         "$#{value}"
152     end
153     def x86CallOperand(kind)
154         "#{value}"
155     end
156 end
157
158 class Address
159     def supports8BitOnX86
160         true
161     end
162     
163     def x86Operand(kind)
164         "#{offset.value}(#{base.x86Operand(:int)})"
165     end
166     def x86CallOperand(kind)
167         "*#{x86Operand(kind)}"
168     end
169 end
170
171 class BaseIndex
172     def supports8BitOnX86
173         true
174     end
175     
176     def x86Operand(kind)
177         "#{offset.value}(#{base.x86Operand(:int)}, #{index.x86Operand(:int)}, #{scale})"
178     end
179
180     def x86CallOperand(kind)
181         "*#{x86operand(kind)}"
182     end
183 end
184
185 class AbsoluteAddress
186     def supports8BitOnX86
187         true
188     end
189     
190     def x86Operand(kind)
191         "#{address.value}"
192     end
193
194     def x86CallOperand(kind)
195         "*#{address.value}"
196     end
197 end
198
199 class LabelReference
200     def x86CallOperand(kind)
201         asmLabel
202     end
203 end
204
205 class LocalLabelReference
206     def x86CallOperand(kind)
207         asmLabel
208     end
209 end
210
211 class Instruction
212     def x86Operands(*kinds)
213         raise unless kinds.size == operands.size
214         result = []
215         kinds.size.times {
216             | idx |
217             result << operands[idx].x86Operand(kinds[idx])
218         }
219         result.join(", ")
220     end
221
222     def x86Suffix(kind)
223         case kind
224         when :byte
225             "b"
226         when :half
227             "w"
228         when :int
229             "l"
230         when :double
231             "sd"
232         else
233             raise
234         end
235     end
236     
237     def handleX86OpWithNumOperands(opcode, kind, numOperands)
238         if numOperands == 3
239             if operands[0] == operands[2]
240                 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
241             elsif operands[1] == operands[2]
242                 $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
243             else
244                 $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
245                 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
246             end
247         else
248             $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
249         end
250     end
251     
252     def handleX86Op(opcode, kind)
253         handleX86OpWithNumOperands(opcode, kind, operands.size)
254     end
255     
256     def handleX86Shift(opcode, kind)
257         if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
258             $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}"
259         else
260             $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
261             $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
262             $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
263         end
264     end
265     
266     def handleX86DoubleBranch(branchOpcode, mode)
267         case mode
268         when :normal
269             $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
270         when :reverse
271             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
272         else
273             raise mode.inspect
274         end
275         $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
276     end
277     
278     def handleX86IntCompare(opcodeSuffix, kind)
279         if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
280             $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}"
281         elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
282             $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}"
283         else
284             $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
285         end
286     end
287     
288     def handleX86IntBranch(branchOpcode, kind)
289         handleX86IntCompare(branchOpcode[1..-1], kind)
290         $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
291     end
292     
293     def handleX86Set(setOpcode, operand)
294         if operand.supports8BitOnX86
295             $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
296             $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
297         else
298             $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
299             $asm.puts "#{setOpcode} %al"
300             $asm.puts "movzbl %al, %eax"
301             $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
302         end
303     end
304     
305     def handleX86IntCompareSet(setOpcode, kind)
306         handleX86IntCompare(setOpcode[3..-1], kind)
307         handleX86Set(setOpcode, operands[2])
308     end
309     
310     def handleX86Test(kind)
311         value = operands[0]
312         case operands.size
313         when 2
314             mask = Immediate.new(codeOrigin, -1)
315         when 3
316             mask = operands[1]
317         else
318             raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
319         end
320         
321         if mask.is_a? Immediate and mask.value == -1
322             if value.is_a? RegisterID
323                 $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}"
324             else
325                 $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
326             end
327         else
328             $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
329         end
330     end
331     
332     def handleX86BranchTest(branchOpcode, kind)
333         handleX86Test(kind)
334         $asm.puts "#{branchOpcode} #{operands.last.asmLabel}"
335     end
336     
337     def handleX86SetTest(setOpcode, kind)
338         handleX86Test(kind)
339         handleX86Set(setOpcode, operands.last)
340     end
341     
342     def handleX86OpBranch(opcode, branchOpcode, kind)
343         handleX86OpWithNumOperands(opcode, kind, operands.size - 1)
344         case operands.size
345         when 4
346             jumpTarget = operands[3]
347         when 3
348             jumpTarget = operands[2]
349         else
350             raise self.inspect
351         end
352         $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
353     end
354     
355     def handleX86SubBranch(branchOpcode, kind)
356         if operands.size == 4 and operands[1] == operands[2]
357             $asm.puts "negl #{operands[2].x86Operand(:int)}"
358             $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
359         else
360             handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
361         end
362         case operands.size
363         when 4
364             jumpTarget = operands[3]
365         when 3
366             jumpTarget = operands[2]
367         else
368             raise self.inspect
369         end
370         $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
371     end
372     
373     def lowerX86
374         $asm.comment codeOriginString
375         case opcode
376         when "addi", "addp"
377             if operands.size == 3 and operands[0].is_a? Immediate
378                 raise unless operands[1].is_a? RegisterID
379                 raise unless operands[2].is_a? RegisterID
380                 if operands[0].value == 0
381                     unless operands[1] == operands[2]
382                         $asm.puts "movl #{operands[1].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
383                     end
384                 else
385                     $asm.puts "leal #{operands[0].value}(#{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
386                 end
387             elsif operands.size == 3 and operands[0].is_a? RegisterID
388                 raise unless operands[1].is_a? RegisterID
389                 raise unless operands[2].is_a? RegisterID
390                 $asm.puts "leal (#{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
391             else
392                 unless Immediate.new(nil, 0) == operands[0]
393                     $asm.puts "addl #{x86Operands(:int, :int)}"
394                 end
395             end
396         when "andi", "andp"
397             handleX86Op("andl", :int)
398         when "lshifti"
399             handleX86Shift("sall", :int)
400         when "muli"
401             if operands.size == 3 and operands[0].is_a? Immediate
402                 $asm.puts "imull #{x86Operands(:int, :int, :int)}"
403             else
404                 # FIXME: could do some peephole in case the left operand is immediate and it's
405                 # a power of two.
406                 handleX86Op("imull", :int)
407             end
408         when "negi"
409             $asm.puts "negl #{x86Operands(:int)}"
410         when "noti"
411             $asm.puts "notl #{x86Operands(:int)}"
412         when "ori", "orp"
413             handleX86Op("orl", :int)
414         when "rshifti"
415             handleX86Shift("sarl", :int)
416         when "urshifti"
417             handleX86Shift("shrl", :int)
418         when "subi", "subp"
419             if operands.size == 3 and operands[1] == operands[2]
420                 $asm.puts "negl #{operands[2].x86Operand(:int)}"
421                 $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
422             else
423                 handleX86Op("subl", :int)
424             end
425         when "xori", "xorp"
426             handleX86Op("xorl", :int)
427         when "loadi", "storei", "loadp", "storep"
428             $asm.puts "movl #{x86Operands(:int, :int)}"
429         when "loadb"
430             $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
431         when "loadbs"
432             $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
433         when "loadh"
434             $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
435         when "loadhs"
436             $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
437         when "storeb"
438             $asm.puts "movb #{x86Operands(:byte, :byte)}"
439         when "loadd", "moved", "stored"
440             $asm.puts "movsd #{x86Operands(:double, :double)}"
441         when "addd"
442             $asm.puts "addsd #{x86Operands(:double, :double)}"
443         when "divd"
444             $asm.puts "divsd #{x86Operands(:double, :double)}"
445         when "subd"
446             $asm.puts "subsd #{x86Operands(:double, :double)}"
447         when "muld"
448             $asm.puts "mulsd #{x86Operands(:double, :double)}"
449         when "sqrtd"
450             $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
451         when "ci2d"
452             $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
453         when "bdeq"
454             isUnordered = LocalLabel.unique("bdeq")
455             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
456             $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
457             $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
458             isUnordered.lower("X86")
459         when "bdneq"
460             handleX86DoubleBranch("jne", :normal)
461         when "bdgt"
462             handleX86DoubleBranch("ja", :normal)
463         when "bdgteq"
464             handleX86DoubleBranch("jae", :normal)
465         when "bdlt"
466             handleX86DoubleBranch("ja", :reverse)
467         when "bdlteq"
468             handleX86DoubleBranch("jae", :reverse)
469         when "bdequn"
470             handleX86DoubleBranch("je", :normal)
471         when "bdnequn"
472             isUnordered = LocalLabel.unique("bdnequn")
473             isEqual = LocalLabel.unique("bdnequn")
474             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
475             $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
476             $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
477             isUnordered.lower("X86")
478             $asm.puts "jmp #{operands[2].asmLabel}"
479             isEqual.lower("X86")
480         when "bdgtun"
481             handleX86DoubleBranch("jb", :reverse)
482         when "bdgtequn"
483             handleX86DoubleBranch("jbe", :reverse)
484         when "bdltun"
485             handleX86DoubleBranch("jb", :normal)
486         when "bdltequn"
487             handleX86DoubleBranch("jbe", :normal)
488         when "btd2i"
489             $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
490             $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
491             $asm.puts "je #{operands[2].asmLabel}"
492         when "td2i"
493             $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
494         when "bcd2i"
495             $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
496             $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
497             $asm.puts "je #{operands[2].asmLabel}"
498             $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
499             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
500             $asm.puts "jp #{operands[2].asmLabel}"
501             $asm.puts "jne #{operands[2].asmLabel}"
502         when "movdz"
503             $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
504         when "pop"
505             $asm.puts "pop #{operands[0].x86Operand(:int)}"
506         when "push"
507             $asm.puts "push #{operands[0].x86Operand(:int)}"
508         when "move", "sxi2p", "zxi2p"
509             if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
510                 $asm.puts "xorl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
511             elsif operands[0] != operands[1]
512                 $asm.puts "movl #{x86Operands(:int, :int)}"
513             end
514         when "nop"
515             $asm.puts "nop"
516         when "bieq", "bpeq"
517             handleX86IntBranch("je", :int)
518         when "bineq", "bpneq"
519             handleX86IntBranch("jne", :int)
520         when "bia", "bpa"
521             handleX86IntBranch("ja", :int)
522         when "biaeq", "bpaeq"
523             handleX86IntBranch("jae", :int)
524         when "bib", "bpb"
525             handleX86IntBranch("jb", :int)
526         when "bibeq", "bpbeq"
527             handleX86IntBranch("jbe", :int)
528         when "bigt", "bpgt"
529             handleX86IntBranch("jg", :int)
530         when "bigteq", "bpgteq"
531             handleX86IntBranch("jge", :int)
532         when "bilt", "bplt"
533             handleX86IntBranch("jl", :int)
534         when "bilteq", "bplteq"
535             handleX86IntBranch("jle", :int)
536         when "bbeq"
537             handleX86IntBranch("je", :byte)
538         when "bbneq"
539             handleX86IntBranch("jne", :byte)
540         when "bba"
541             handleX86IntBranch("ja", :byte)
542         when "bbaeq"
543             handleX86IntBranch("jae", :byte)
544         when "bbb"
545             handleX86IntBranch("jb", :byte)
546         when "bbbeq"
547             handleX86IntBranch("jbe", :byte)
548         when "bbgt"
549             handleX86IntBranch("jg", :byte)
550         when "bbgteq"
551             handleX86IntBranch("jge", :byte)
552         when "bblt"
553             handleX86IntBranch("jl", :byte)
554         when "bblteq"
555             handleX86IntBranch("jlteq", :byte)
556         when "btio", "btpo"
557             handleX86BranchTest("jo", :int)
558         when "btis", "btps"
559             handleX86BranchTest("js", :int)
560         when "btiz", "btpz"
561             handleX86BranchTest("jz", :int)
562         when "btinz", "btpnz"
563             handleX86BranchTest("jnz", :int)
564         when "btbo"
565             handleX86BranchTest("jo", :byte)
566         when "btbs"
567             handleX86BranchTest("js", :byte)
568         when "btbz"
569             handleX86BranchTest("jz", :byte)
570         when "btbnz"
571             handleX86BranchTest("jnz", :byte)
572         when "jmp"
573             $asm.puts "jmp #{operands[0].x86CallOperand(:int)}"
574         when "baddio", "baddpo"
575             handleX86OpBranch("addl", "jo", :int)
576         when "baddis", "baddps"
577             handleX86OpBranch("addl", "js", :int)
578         when "baddiz", "baddpz"
579             handleX86OpBranch("addl", "jz", :int)
580         when "baddinz", "baddpnz"
581             handleX86OpBranch("addl", "jnz", :int)
582         when "bsubio"
583             handleX86SubBranch("jo", :int)
584         when "bsubis"
585             handleX86SubBranch("js", :int)
586         when "bsubiz"
587             handleX86SubBranch("jz", :int)
588         when "bsubinz"
589             handleX86SubBranch("jnz", :int)
590         when "bmulio"
591             handleX86OpBranch("imull", "jo", :int)
592         when "bmulis"
593             handleX86OpBranch("imull", "js", :int)
594         when "bmuliz"
595             handleX86OpBranch("imull", "jz", :int)
596         when "bmulinz"
597             handleX86OpBranch("imull", "jnz", :int)
598         when "borio"
599             handleX86OpBranch("orl", "jo", :int)
600         when "boris"
601             handleX86OpBranch("orl", "js", :int)
602         when "boriz"
603             handleX86OpBranch("orl", "jz", :int)
604         when "borinz"
605             handleX86OpBranch("orl", "jnz", :int)
606         when "break"
607             $asm.puts "int $3"
608         when "call"
609             $asm.puts "call #{operands[0].x86CallOperand(:int)}"
610         when "ret"
611             $asm.puts "ret"
612         when "cieq", "cpeq"
613             handleX86IntCompareSet("sete", :int)
614         when "cineq", "cpneq"
615             handleX86IntCompareSet("setne", :int)
616         when "cia", "cpa"
617             handleX86IntCompareSet("seta", :int)
618         when "ciaeq", "cpaeq"
619             handleX86IntCompareSet("setae", :int)
620         when "cib", "cpb"
621             handleX86IntCompareSet("setb", :int)
622         when "cibeq", "cpbeq"
623             handleX86IntCompareSet("setbe", :int)
624         when "cigt", "cpgt"
625             handleX86IntCompareSet("setg", :int)
626         when "cigteq", "cpgteq"
627             handleX86IntCompareSet("setge", :int)
628         when "cilt", "cplt"
629             handleX86IntCompareSet("setl", :int)
630         when "cilteq", "cplteq"
631             handleX86IntCompareSet("setle", :int)
632         when "tio"
633             handleX86SetTest("seto", :int)
634         when "tis"
635             handleX86SetTest("sets", :int)
636         when "tiz"
637             handleX86SetTest("setz", :int)
638         when "tinz"
639             handleX86SetTest("setnz", :int)
640         when "tbo"
641             handleX86SetTest("seto", :byte)
642         when "tbs"
643             handleX86SetTest("sets", :byte)
644         when "tbz"
645             handleX86SetTest("setz", :byte)
646         when "tbnz"
647             handleX86SetTest("setnz", :byte)
648         when "peek"
649             $asm.puts "movl #{operands[0].value * 4}(%esp), #{operands[1].x86Operand(:int)}"
650         when "poke"
651             $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].value * 4}(%esp)"
652         when "cdqi"
653             $asm.puts "cdq"
654         when "idivi"
655             $asm.puts "idivl #{operands[0].x86Operand(:int)}"
656         when "fii2d"
657             $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
658             $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
659             $asm.puts "psllq $32, %xmm7"
660             $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
661         when "fd2ii"
662             $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
663             $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
664             $asm.puts "psrlq $32, %xmm7"
665             $asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}"
666         when "bo"
667             $asm.puts "jo #{operands[0].asmLabel}"
668         when "bs"
669             $asm.puts "js #{operands[0].asmLabel}"
670         when "bz"
671             $asm.puts "jz #{operands[0].asmLabel}"
672         when "bnz"
673             $asm.puts "jnz #{operands[0].asmLabel}"
674         when "leai", "leap"
675             $asm.puts "leal #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
676         else
677             raise "Bad opcode: #{opcode}"
678         end
679     end
680 end
681