x86.rb 45 KB

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