blob: c847d564a0d0c2558f306da751c69e5b4156ece1 [file] [log] [blame]
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001# Copyright (C) 2013 Apple Inc. All rights reserved.
2# Copyright (C) 2013 Cisco Systems, Inc. All rights reserved.
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 CISCO SYSTEMS, INC. ``AS IS'' AND ANY
14# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CISCO SYSTEMS, INC. OR ITS
17# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25require 'risc'
26
msaboff@apple.com33539122015-09-03 22:16:23 +000027# GPR conventions, to match the baseline JIT
28#
29# r0 => t0, r0
30# r1 => t1, r1
31# r2 => t4
32# r3 => t5
33# r4 => a0
34# r5 => a1
35# r6 => t2, a2
36# r7 => t3, a3
37# r10 => (scratch)
38# r11 => (scratch)
39# r13 => (scratch)
40# r14 => cfr
41# r15 => sp
42# pr => lr
43
44# FPR conventions, to match the baseline JIT
45# We don't have fa2 or fa3!
46# dr0 => ft0, fr
47# dr2 => ft1
48# dr4 => ft2, fa0
49# dr6 => ft3, fa1
50# dr8 => ft4
51# dr10 => ft5
52# dr12 => (scratch)
53
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +000054class Node
55 def sh4SingleHi
56 doubleOperand = sh4Operand
57 raise "Bogus register name #{doubleOperand}" unless doubleOperand =~ /^dr/
58 "fr" + ($~.post_match.to_i).to_s
59 end
60 def sh4SingleLo
61 doubleOperand = sh4Operand
62 raise "Bogus register name #{doubleOperand}" unless doubleOperand =~ /^dr/
63 "fr" + ($~.post_match.to_i + 1).to_s
64 end
65end
66
67class SpecialRegister < NoChildren
68 def sh4Operand
69 @name
70 end
71
72 def dump
73 @name
74 end
75
76 def register?
77 true
78 end
79end
80
msaboff@apple.com33539122015-09-03 22:16:23 +000081SH4_TMP_GPRS = [ SpecialRegister.new("r10"), SpecialRegister.new("r11"), SpecialRegister.new("r13") ]
82SH4_TMP_FPRS = [ SpecialRegister.new("dr12") ]
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +000083
84class RegisterID
85 def sh4Operand
86 case name
msaboff@apple.com33539122015-09-03 22:16:23 +000087 when "a0"
msaboff@apple.com4655f792013-11-14 07:39:30 +000088 "r4"
msaboff@apple.com33539122015-09-03 22:16:23 +000089 when "a1"
msaboff@apple.com4655f792013-11-14 07:39:30 +000090 "r5"
msaboff@apple.com33539122015-09-03 22:16:23 +000091 when "r0", "t0"
92 "r0"
93 when "r1", "t1"
94 "r1"
95 when "a2", "t2"
commit-queue@webkit.orgefebe0f2013-12-04 18:30:49 +000096 "r6"
msaboff@apple.com33539122015-09-03 22:16:23 +000097 when "a3", "t3"
commit-queue@webkit.orgefebe0f2013-12-04 18:30:49 +000098 "r7"
msaboff@apple.com33539122015-09-03 22:16:23 +000099 when "t4"
100 "r2"
101 when "t5"
102 "r3"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000103 when "cfr"
104 "r14"
105 when "sp"
106 "r15"
107 when "lr"
108 "pr"
109 else
110 raise "Bad register #{name} for SH4 at #{codeOriginString}"
111 end
112 end
113end
114
115class FPRegisterID
116 def sh4Operand
117 case name
118 when "ft0", "fr"
119 "dr0"
120 when "ft1"
121 "dr2"
msaboff@apple.com33539122015-09-03 22:16:23 +0000122 when "ft2", "fa0"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000123 "dr4"
msaboff@apple.com33539122015-09-03 22:16:23 +0000124 when "ft3", "fa1"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000125 "dr6"
126 when "ft4"
127 "dr8"
msaboff@apple.com33539122015-09-03 22:16:23 +0000128 when "ft5"
129 "dr10"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000130 else
131 raise "Bad register #{name} for SH4 at #{codeOriginString}"
132 end
133 end
134end
135
136class Immediate
137 def sh4Operand
138 raise "Invalid immediate #{value} at #{codeOriginString}" if value < -128 or value > 127
139 "##{value}"
140 end
141end
142
143class Address
144 def sh4Operand
145 raise "Bad offset #{offset.value} at #{codeOriginString}" if offset.value < 0 or offset.value > 60
146 if offset.value == 0
147 "@#{base.sh4Operand}"
148 else
149 "@(#{offset.value}, #{base.sh4Operand})"
150 end
151 end
152
153 def sh4OperandPostInc
154 raise "Bad offset #{offset.value} for post inc at #{codeOriginString}" unless offset.value == 0
155 "@#{base.sh4Operand}+"
156 end
157
158 def sh4OperandPreDec
159 raise "Bad offset #{offset.value} for pre dec at #{codeOriginString}" unless offset.value == 0
160 "@-#{base.sh4Operand}"
161 end
162end
163
164class BaseIndex
165 def sh4Operand
166 raise "Unconverted base index at #{codeOriginString}"
167 end
168end
169
170class AbsoluteAddress
171 def sh4Operand
172 raise "Unconverted absolute address at #{codeOriginString}"
173 end
174end
175
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +0000176class LabelReference
177 def sh4Operand
178 value
179 end
180end
181
julien.brianceau@gmail.com39fbe662014-04-14 21:46:18 +0000182class SubImmediates < Node
183 def sh4Operand
184 "#{@left.sh4Operand} - #{@right.sh4Operand}"
185 end
186end
187
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000188class ConstPool < Node
189 attr_reader :size
190 attr_reader :entries
191
192 def initialize(codeOrigin, entries, size)
193 super(codeOrigin)
194 raise "Invalid size #{size} for ConstPool" unless size == 16 or size == 32
195 @size = size
196 @entries = entries
197 end
198
199 def dump
200 "#{size}: #{entries}"
201 end
202
203 def address?
204 false
205 end
206
207 def label?
208 false
209 end
210
211 def immediate?
212 false
213 end
214
215 def register?
216 false
217 end
218
219 def lowerSH4
220 if size == 16
221 $asm.puts ".balign 2"
222 else
223 $asm.puts ".balign 4"
224 end
225 entries.map {
226 |e|
227 e.label.lower("SH4")
228 if e.size == 16
229 $asm.puts ".word #{e.value}"
230 else
231 $asm.puts ".long #{e.value}"
232 end
233 }
234 end
235end
236
237class ConstPoolEntry < Node
238 attr_reader :size
239 attr_reader :value
240 attr_reader :label
241 attr_reader :labelref
242
243 def initialize(codeOrigin, value, size)
244 super(codeOrigin)
245 raise "Invalid size #{size} for ConstPoolEntry" unless size == 16 or size == 32
246 @size = size
247 @value = value
248 @label = LocalLabel.unique("constpool#{size}")
249 @labelref = LocalLabelReference.new(codeOrigin, label)
250 end
251
252 def dump
253 "#{value} (#{size} @ #{label})"
254 end
255
256 def ==(other)
257 other.is_a? ConstPoolEntry and other.value == @value
258 end
259
260 def address?
261 false
262 end
263
264 def label?
265 false
266 end
267
268 def immediate?
269 false
270 end
271
272 def register?
273 false
274 end
275end
276
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000277
278#
279# Lowering of shift ops for SH4. For example:
280#
281# rshifti foo, bar
282#
283# becomes:
284#
285# negi foo, tmp
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000286# shad tmp, bar
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000287#
288
289def sh4LowerShiftOps(list)
290 newList = []
291 list.each {
292 | node |
293 if node.is_a? Instruction
294 case node.opcode
295 when "ulshifti", "ulshiftp", "urshifti", "urshiftp", "lshifti", "lshiftp", "rshifti", "rshiftp"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000296 if node.opcode[0, 1] == "u"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000297 type = "l"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000298 direction = node.opcode[1, 1]
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000299 else
300 type = "a"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000301 direction = node.opcode[0, 1]
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000302 end
303 if node.operands[0].is_a? Immediate
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000304 maskedImm = Immediate.new(node.operands[0].codeOrigin, node.operands[0].value & 31)
305 if maskedImm.value == 0
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000306 # There is nothing to do here.
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000307 elsif maskedImm.value == 1 or (type == "l" and [2, 8, 16].include? maskedImm.value)
308 newList << Instruction.new(node.codeOrigin, "sh#{type}#{direction}x", [maskedImm, node.operands[1]])
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000309 else
310 tmp = Tmp.new(node.codeOrigin, :gpr)
311 if direction == "l"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000312 newList << Instruction.new(node.codeOrigin, "move", [maskedImm, tmp])
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000313 else
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000314 newList << Instruction.new(node.codeOrigin, "move", [Immediate.new(node.operands[0].codeOrigin, -1 * maskedImm.value), tmp])
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000315 end
316 newList << Instruction.new(node.codeOrigin, "sh#{type}d", [tmp, node.operands[1]])
317 end
318 else
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000319 tmp = Tmp.new(node.codeOrigin, :gpr)
320 newList << Instruction.new(node.codeOrigin, "move", [Immediate.new(node.operands[0].codeOrigin, 31), tmp])
321 newList << Instruction.new(node.codeOrigin, "andi", [node.operands[0], tmp])
322 if direction == "r"
323 newList << Instruction.new(node.codeOrigin, "negi", [tmp, tmp])
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000324 end
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000325 newList << Instruction.new(node.codeOrigin, "sh#{type}d", [tmp, node.operands[1]])
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000326 end
327 else
328 newList << node
329 end
330 else
331 newList << node
332 end
333 }
334 newList
335end
336
337
338#
339# Lowering of simple branch ops for SH4. For example:
340#
341# baddis foo, bar, baz
342#
343# will become:
344#
oliver@apple.com22b28562013-08-13 22:15:13 +0000345# addi foo, bar
346# bs bar, baz
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000347#
348
349def sh4LowerSimpleBranchOps(list)
350 newList = []
351 list.each {
352 | node |
353 if node.is_a? Instruction
354 annotation = node.annotation
355 case node.opcode
356 when /^b(addi|subi|ori|addp)/
357 op = $1
358 bc = $~.post_match
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000359
360 case op
361 when "addi", "addp"
362 op = "addi"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000363 when "subi", "subp"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000364 op = "subi"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000365 when "ori", "orp"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000366 op = "ori"
367 end
368
369 if bc == "s"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000370 raise "Invalid operands number (#{node.operands.size})" unless node.operands.size == 3
371 if node.operands[1].is_a? RegisterID or node.operands[1].is_a? SpecialRegister
372 newList << Instruction.new(node.codeOrigin, op, node.operands[0..1])
373 newList << Instruction.new(node.codeOrigin, "bs", node.operands[1..2])
374 else
375 tmpVal = Tmp.new(node.codeOrigin, :gpr)
376 tmpPtr = Tmp.new(node.codeOrigin, :gpr)
377 addr = Address.new(node.codeOrigin, tmpPtr, Immediate.new(node.codeOrigin, 0))
378 newList << Instruction.new(node.codeOrigin, "leap", [node.operands[1], tmpPtr])
379 newList << Instruction.new(node.codeOrigin, "loadi", [addr, tmpVal])
380 newList << Instruction.new(node.codeOrigin, op, [node.operands[0], tmpVal])
381 newList << Instruction.new(node.codeOrigin, "storei", [tmpVal, addr])
382 newList << Instruction.new(node.codeOrigin, "bs", [tmpVal, node.operands[2]])
383 end
commit-queue@webkit.orgecae89d2013-07-25 12:29:26 +0000384 elsif bc == "nz"
385 raise "Invalid operands number (#{node.operands.size})" unless node.operands.size == 3
386 newList << Instruction.new(node.codeOrigin, op, node.operands[0..1])
387 newList << Instruction.new(node.codeOrigin, "btinz", node.operands[1..2])
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000388 else
389 newList << node
390 end
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000391 when "bmulio", "bmulpo"
392 raise "Invalid operands number (#{node.operands.size})" unless node.operands.size == 3
393 tmp1 = Tmp.new(node.codeOrigin, :gpr)
394 tmp2 = Tmp.new(node.codeOrigin, :gpr)
395 newList << Instruction.new(node.codeOrigin, node.opcode, [tmp1, tmp2].concat(node.operands))
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000396 else
397 newList << node
398 end
399 else
400 newList << node
401 end
402 }
403 newList
404end
405
406
407#
408# Lowering of double accesses for SH4. For example:
409#
410# loadd [foo, bar, 8], baz
411#
412# becomes:
413#
414# leap [foo, bar, 8], tmp
415# loaddReversedAndIncrementAddress [tmp], baz
416#
417
418def sh4LowerDoubleAccesses(list)
419 newList = []
420 list.each {
421 | node |
422 if node.is_a? Instruction
423 case node.opcode
424 when "loadd"
425 tmp = Tmp.new(codeOrigin, :gpr)
426 addr = Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
427 newList << Instruction.new(codeOrigin, "leap", [node.operands[0], tmp])
428 newList << Instruction.new(node.codeOrigin, "loaddReversedAndIncrementAddress", [addr, node.operands[1]], node.annotation)
429 when "stored"
430 tmp = Tmp.new(codeOrigin, :gpr)
431 addr = Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
432 newList << Instruction.new(codeOrigin, "leap", [node.operands[1].withOffset(8), tmp])
433 newList << Instruction.new(node.codeOrigin, "storedReversedAndDecrementAddress", [node.operands[0], addr], node.annotation)
434 else
435 newList << node
436 end
437 else
438 newList << node
439 end
440 }
441 newList
442end
443
444
445#
446# Lowering of double specials for SH4.
447#
448
449def sh4LowerDoubleSpecials(list)
450 newList = []
451 list.each {
452 | node |
453 if node.is_a? Instruction
454 case node.opcode
commit-queue@webkit.org265e4ab2013-05-24 16:46:10 +0000455 when "bdltun", "bdgtun"
456 # Handle specific floating point unordered opcodes.
commit-queue@webkit.org899992352013-05-30 23:21:17 +0000457 newList << Instruction.new(codeOrigin, "bdnan", [node.operands[0], node.operands[2]])
458 newList << Instruction.new(codeOrigin, "bdnan", [node.operands[1], node.operands[2]])
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000459 newList << Instruction.new(codeOrigin, node.opcode[0..-3], node.operands)
commit-queue@webkit.org265e4ab2013-05-24 16:46:10 +0000460 when "bdnequn", "bdgtequn", "bdltequn"
461 newList << Instruction.new(codeOrigin, node.opcode[0..-3], node.operands)
462 when "bdneq", "bdgteq", "bdlteq"
463 # Handle specific floating point ordered opcodes.
commit-queue@webkit.org265e4ab2013-05-24 16:46:10 +0000464 outlabel = LocalLabel.unique("out_#{node.opcode}")
465 outref = LocalLabelReference.new(codeOrigin, outlabel)
commit-queue@webkit.org899992352013-05-30 23:21:17 +0000466 newList << Instruction.new(codeOrigin, "bdnan", [node.operands[0], outref])
467 newList << Instruction.new(codeOrigin, "bdnan", [node.operands[1], outref])
commit-queue@webkit.org265e4ab2013-05-24 16:46:10 +0000468 newList << Instruction.new(codeOrigin, node.opcode, node.operands)
469 newList << outlabel
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000470 else
471 newList << node
472 end
473 else
474 newList << node
475 end
476 }
477 newList
478end
479
480
481#
482# Lowering of misplaced labels for SH4.
483#
484
485def sh4LowerMisplacedLabels(list)
486 newList = []
487 list.each {
488 | node |
489 if node.is_a? Instruction
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000490 operands = node.operands
491 newOperands = []
492 operands.each {
493 | operand |
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +0000494 if operand.is_a? LabelReference and node.opcode != "mova"
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000495 tmp = Tmp.new(operand.codeOrigin, :gpr)
496 newList << Instruction.new(operand.codeOrigin, "move", [operand, tmp])
497 newOperands << tmp
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000498 else
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000499 newOperands << operand
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000500 end
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000501 }
502 newList << Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation)
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000503 else
504 newList << node
505 end
506 }
507 newList
508end
509
510
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000511#
commit-queue@webkit.orgc19522a2013-11-16 22:28:27 +0000512# Lowering of misplaced special registers for SH4. For example:
513#
514# storep pr, foo
515#
516# becomes:
517#
518# stspr tmp
519# storep tmp, foo
520#
521
522def sh4LowerMisplacedSpecialRegisters(list)
523 newList = []
524 list.each {
525 | node |
526 if node.is_a? Instruction
527 case node.opcode
commit-queue@webkit.orgf89c35e2013-11-18 16:01:17 +0000528 when "move"
529 if node.operands[0].is_a? RegisterID and node.operands[0].sh4Operand == "pr"
530 newList << Instruction.new(codeOrigin, "stspr", [node.operands[1]])
531 elsif node.operands[1].is_a? RegisterID and node.operands[1].sh4Operand == "pr"
532 newList << Instruction.new(codeOrigin, "ldspr", [node.operands[0]])
533 else
534 newList << node
535 end
commit-queue@webkit.orgc19522a2013-11-16 22:28:27 +0000536 when "loadi", "loadis", "loadp"
537 if node.operands[1].is_a? RegisterID and node.operands[1].sh4Operand == "pr"
538 tmp = Tmp.new(codeOrigin, :gpr)
539 newList << Instruction.new(codeOrigin, node.opcode, [node.operands[0], tmp])
540 newList << Instruction.new(codeOrigin, "ldspr", [tmp])
541 else
542 newList << node
543 end
544 when "storei", "storep"
545 if node.operands[0].is_a? RegisterID and node.operands[0].sh4Operand == "pr"
546 tmp = Tmp.new(codeOrigin, :gpr)
547 newList << Instruction.new(codeOrigin, "stspr", [tmp])
548 newList << Instruction.new(codeOrigin, node.opcode, [tmp, node.operands[1]])
549 else
550 newList << node
551 end
552 else
553 newList << node
554 end
555 else
556 newList << node
557 end
558 }
559 newList
560end
561
562
563#
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000564# Group immediate values outside -128..127 range into constant pools for SH4.
565# These constant pools will be placed behind non-return opcodes jmp and ret, for example:
566#
567# move 1024, foo
568# ...
569# ret
570#
571# becomes:
572#
573# move [label], foo
574# ...
575# ret
576# label: 1024
577#
578
579def sh4LowerConstPool(list)
580 newList = []
581 currentPool16 = []
582 currentPool32 = []
583 list.each {
584 | node |
585 if node.is_a? Instruction
586 case node.opcode
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +0000587 when "jmp", "ret", "flushcp"
588 if node.opcode == "flushcp"
589 outlabel = LocalLabel.unique("flushcp")
590 newList << Instruction.new(codeOrigin, "jmp", [LocalLabelReference.new(codeOrigin, outlabel)])
591 else
592 newList << node
593 end
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000594 if not currentPool16.empty?
595 newList << ConstPool.new(codeOrigin, currentPool16, 16)
596 currentPool16 = []
597 end
598 if not currentPool32.empty?
599 newList << ConstPool.new(codeOrigin, currentPool32, 32)
600 currentPool32 = []
601 end
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +0000602 if node.opcode == "flushcp"
603 newList << outlabel
604 end
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000605 when "move"
606 if node.operands[0].is_a? Immediate and not (-128..127).include? node.operands[0].value
607 poolEntry = nil
608 if (-32768..32767).include? node.operands[0].value
609 currentPool16.each { |e|
610 if e.value == node.operands[0].value
611 poolEntry = e
612 end
613 }
614 if !poolEntry
615 poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].value, 16)
616 currentPool16 << poolEntry
617 end
618 else
619 currentPool32.each { |e|
620 if e.value == node.operands[0].value
621 poolEntry = e
622 end
623 }
624 if !poolEntry
625 poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].value, 32)
626 currentPool32 << poolEntry
627 end
628 end
629 newList << Instruction.new(codeOrigin, "move", [poolEntry, node.operands[1]])
630 elsif node.operands[0].is_a? LabelReference
631 poolEntry = nil
632 currentPool32.each { |e|
633 if e.value == node.operands[0].asmLabel
634 poolEntry = e
635 end
636 }
637 if !poolEntry
638 poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].asmLabel, 32)
639 currentPool32 << poolEntry
640 end
641 newList << Instruction.new(codeOrigin, "move", [poolEntry, node.operands[1]])
julien.brianceau@gmail.com39fbe662014-04-14 21:46:18 +0000642 elsif node.operands[0].is_a? SubImmediates
643 poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].sh4Operand, 32)
644 currentPool32 << poolEntry
645 newList << Instruction.new(codeOrigin, "move", [poolEntry, node.operands[1]])
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000646 else
647 newList << node
648 end
649 else
650 newList << node
651 end
652 else
653 newList << node
654 end
655 }
656 if not currentPool16.empty?
657 newList << ConstPool.new(codeOrigin, currentPool16, 16)
658 end
659 if not currentPool32.empty?
660 newList << ConstPool.new(codeOrigin, currentPool32, 32)
661 end
662 newList
663end
664
665
commit-queue@webkit.orgea3fae72013-11-14 16:52:48 +0000666#
667# Lowering of argument setup for SH4.
668# This phase avoids argument register trampling. For example, if a0 == t4:
669#
670# setargs t1, t4
671#
672# becomes:
673#
674# move t4, a1
675# move t1, a0
676#
677
678def sh4LowerArgumentSetup(list)
679 a0 = RegisterID.forName(codeOrigin, "a0")
680 a1 = RegisterID.forName(codeOrigin, "a1")
681 a2 = RegisterID.forName(codeOrigin, "a2")
682 a3 = RegisterID.forName(codeOrigin, "a3")
683 newList = []
684 list.each {
685 | node |
686 if node.is_a? Instruction
687 case node.opcode
688 when "setargs"
689 if node.operands.size == 2
690 if node.operands[1].sh4Operand != a0.sh4Operand
691 newList << Instruction.new(codeOrigin, "move", [node.operands[0], a0])
692 newList << Instruction.new(codeOrigin, "move", [node.operands[1], a1])
693 elsif node.operands[0].sh4Operand != a1.sh4Operand
694 newList << Instruction.new(codeOrigin, "move", [node.operands[1], a1])
695 newList << Instruction.new(codeOrigin, "move", [node.operands[0], a0])
696 else
697 # As (operands[0] == a1) and (operands[1] == a0), we just need to swap a0 and a1.
698 newList << Instruction.new(codeOrigin, "xori", [a0, a1])
699 newList << Instruction.new(codeOrigin, "xori", [a1, a0])
700 newList << Instruction.new(codeOrigin, "xori", [a0, a1])
701 end
702 elsif node.operands.size == 4
703 # FIXME: We just raise an error if something is likely to go wrong for now.
704 # It would be better to implement a recovering algorithm.
705 if (node.operands[0].sh4Operand == a1.sh4Operand) or
706 (node.operands[0].sh4Operand == a2.sh4Operand) or
707 (node.operands[0].sh4Operand == a3.sh4Operand) or
708 (node.operands[1].sh4Operand == a0.sh4Operand) or
709 (node.operands[1].sh4Operand == a2.sh4Operand) or
710 (node.operands[1].sh4Operand == a3.sh4Operand) or
711 (node.operands[2].sh4Operand == a0.sh4Operand) or
712 (node.operands[2].sh4Operand == a1.sh4Operand) or
713 (node.operands[2].sh4Operand == a3.sh4Operand) or
714 (node.operands[3].sh4Operand == a0.sh4Operand) or
715 (node.operands[3].sh4Operand == a1.sh4Operand) or
716 (node.operands[3].sh4Operand == a2.sh4Operand)
717 raise "Potential argument register trampling detected."
718 end
719
720 newList << Instruction.new(codeOrigin, "move", [node.operands[0], a0])
721 newList << Instruction.new(codeOrigin, "move", [node.operands[1], a1])
722 newList << Instruction.new(codeOrigin, "move", [node.operands[2], a2])
723 newList << Instruction.new(codeOrigin, "move", [node.operands[3], a3])
724 else
725 raise "Invalid operands number (#{node.operands.size}) for setargs"
726 end
727 else
728 newList << node
729 end
730 else
731 newList << node
732 end
733 }
734 newList
735end
736
737
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000738class Sequence
739 def getModifiedListSH4
740 result = @list
741
742 # Verify that we will only see instructions and labels.
743 result.each {
744 | node |
745 unless node.is_a? Instruction or
746 node.is_a? Label or
747 node.is_a? LocalLabel or
748 node.is_a? Skip
749 raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
750 end
751 }
752
753 result = sh4LowerShiftOps(result)
754 result = sh4LowerSimpleBranchOps(result)
755 result = riscLowerMalformedAddresses(result) {
756 | node, address |
757 if address.is_a? Address
758 case node.opcode
oliver@apple.com22b28562013-08-13 22:15:13 +0000759 when "btbz", "btbnz", "cbeq", "bbeq", "bbneq", "bbb", "loadb", "storeb"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000760 (0..15).include? address.offset.value and
761 ((node.operands[0].is_a? RegisterID and node.operands[0].sh4Operand == "r0") or
762 (node.operands[1].is_a? RegisterID and node.operands[1].sh4Operand == "r0"))
763 when "loadh"
764 (0..30).include? address.offset.value and
765 ((node.operands[0].is_a? RegisterID and node.operands[0].sh4Operand == "r0") or
766 (node.operands[1].is_a? RegisterID and node.operands[1].sh4Operand == "r0"))
767 else
768 (0..60).include? address.offset.value
769 end
770 else
771 false
772 end
773 }
774 result = sh4LowerDoubleAccesses(result)
775 result = sh4LowerDoubleSpecials(result)
776 result = riscLowerMisplacedImmediates(result, ["storeb", "storei", "storep", "muli", "mulp", "andi", "ori", "xori",
777 "cbeq", "cieq", "cpeq", "cineq", "cpneq", "cib", "baddio", "bsubio", "bmulio", "baddis",
778 "bbeq", "bbneq", "bbb", "bieq", "bpeq", "bineq", "bpneq", "bia", "bpa", "biaeq", "bpaeq", "bib", "bpb",
779 "bigteq", "bpgteq", "bilt", "bplt", "bigt", "bpgt", "bilteq", "bplteq", "btiz", "btpz", "btinz", "btpnz", "btbz", "btbnz"])
780 result = riscLowerMalformedImmediates(result, -128..127)
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000781 result = riscLowerMisplacedAddresses(result)
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000782 result = sh4LowerMisplacedLabels(result)
commit-queue@webkit.orgc19522a2013-11-16 22:28:27 +0000783 result = sh4LowerMisplacedSpecialRegisters(result)
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000784
785 result = assignRegistersToTemporaries(result, :gpr, SH4_TMP_GPRS)
786 result = assignRegistersToTemporaries(result, :gpr, SH4_TMP_FPRS)
787
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000788 result = sh4LowerConstPool(result)
commit-queue@webkit.orgea3fae72013-11-14 16:52:48 +0000789 result = sh4LowerArgumentSetup(result)
commit-queue@webkit.org004ed102013-10-15 18:03:42 +0000790
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000791 return result
792 end
793end
794
795def sh4Operands(operands)
796 operands.map{|v| v.sh4Operand}.join(", ")
797end
798
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000799def emitSH4Branch(sh4opcode, operand)
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000800 raise "Invalid operand #{operand}" unless operand.is_a? RegisterID or operand.is_a? SpecialRegister
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000801 $asm.puts "#{sh4opcode} @#{operand.sh4Operand}"
802 $asm.puts "nop"
803end
804
805def emitSH4ShiftImm(val, operand, direction)
806 tmp = val
807 while tmp > 0
808 if tmp >= 16
809 $asm.puts "shl#{direction}16 #{operand.sh4Operand}"
810 tmp -= 16
811 elsif tmp >= 8
812 $asm.puts "shl#{direction}8 #{operand.sh4Operand}"
813 tmp -= 8
814 elsif tmp >= 2
815 $asm.puts "shl#{direction}2 #{operand.sh4Operand}"
816 tmp -= 2
817 else
818 $asm.puts "shl#{direction} #{operand.sh4Operand}"
819 tmp -= 1
820 end
821 end
822end
823
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000824def emitSH4BranchIfT(dest, neg)
commit-queue@webkit.org4a39b022013-04-18 01:08:49 +0000825 outlabel = LocalLabel.unique("branchIfT")
826 sh4opcode = neg ? "bt" : "bf"
827 $asm.puts "#{sh4opcode} #{LocalLabelReference.new(codeOrigin, outlabel).asmLabel}"
commit-queue@webkit.org9e799622013-12-09 18:36:44 +0000828 if dest.is_a? LocalLabelReference
829 $asm.puts "bra #{dest.asmLabel}"
830 $asm.puts "nop"
831 else
832 emitSH4Branch("jmp", dest)
833 end
commit-queue@webkit.org4a39b022013-04-18 01:08:49 +0000834 outlabel.lower("SH4")
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000835end
836
837def emitSH4IntCompare(cmpOpcode, operands)
838 $asm.puts "cmp/#{cmpOpcode} #{sh4Operands([operands[1], operands[0]])}"
839end
840
841def emitSH4CondBranch(cmpOpcode, neg, operands)
842 emitSH4IntCompare(cmpOpcode, operands)
843 emitSH4BranchIfT(operands[2], neg)
844end
845
846def emitSH4CompareSet(cmpOpcode, neg, operands)
847 emitSH4IntCompare(cmpOpcode, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000848 if !neg
849 $asm.puts "movt #{operands[2].sh4Operand}"
850 else
851 outlabel = LocalLabel.unique("compareSet")
852 $asm.puts "mov #0, #{operands[2].sh4Operand}"
853 $asm.puts "bt #{LocalLabelReference.new(codeOrigin, outlabel).asmLabel}"
854 $asm.puts "mov #1, #{operands[2].sh4Operand}"
855 outlabel.lower("SH4")
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000856 end
857end
858
859def emitSH4BranchIfNaN(operands)
commit-queue@webkit.org899992352013-05-30 23:21:17 +0000860 raise "Invalid operands number (#{operands.size})" unless operands.size == 2
861 $asm.puts "fcmp/eq #{sh4Operands([operands[0], operands[0]])}"
862 $asm.puts "bf #{operands[1].asmLabel}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000863end
864
865def emitSH4DoubleCondBranch(cmpOpcode, neg, operands)
866 if cmpOpcode == "lt"
commit-queue@webkit.org265e4ab2013-05-24 16:46:10 +0000867 $asm.puts "fcmp/gt #{sh4Operands([operands[0], operands[1]])}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000868 else
869 $asm.puts "fcmp/#{cmpOpcode} #{sh4Operands([operands[1], operands[0]])}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000870 end
commit-queue@webkit.org265e4ab2013-05-24 16:46:10 +0000871 emitSH4BranchIfT(operands[2], neg)
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000872end
873
874class Instruction
875 def lowerSH4
876 $asm.comment codeOriginString
877 case opcode
878 when "addi", "addp"
879 if operands.size == 3
880 if operands[0].sh4Operand == operands[2].sh4Operand
881 $asm.puts "add #{sh4Operands([operands[1], operands[2]])}"
882 elsif operands[1].sh4Operand == operands[2].sh4Operand
883 $asm.puts "add #{sh4Operands([operands[0], operands[2]])}"
884 else
885 $asm.puts "mov #{sh4Operands([operands[0], operands[2]])}"
886 $asm.puts "add #{sh4Operands([operands[1], operands[2]])}"
887 end
888 else
889 $asm.puts "add #{sh4Operands(operands)}"
890 end
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000891 when "subi", "subp"
commit-queue@webkit.org673814c2013-09-16 09:05:38 +0000892 if operands.size == 3
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +0000893 if operands[1].is_a? Immediate
894 $asm.puts "mov #{sh4Operands([Immediate.new(codeOrigin, -1 * operands[1].value), operands[2]])}"
895 $asm.puts "add #{sh4Operands([operands[0], operands[2]])}"
896 elsif operands[1].sh4Operand == operands[2].sh4Operand
commit-queue@webkit.org673814c2013-09-16 09:05:38 +0000897 $asm.puts "neg #{sh4Operands([operands[2], operands[2]])}"
898 $asm.puts "add #{sh4Operands([operands[0], operands[2]])}"
899 else
900 $asm.puts "mov #{sh4Operands([operands[0], operands[2]])}"
901 $asm.puts "sub #{sh4Operands([operands[1], operands[2]])}"
902 end
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000903 else
commit-queue@webkit.org673814c2013-09-16 09:05:38 +0000904 if operands[0].is_a? Immediate
905 $asm.puts "add #{sh4Operands([Immediate.new(codeOrigin, -1 * operands[0].value), operands[1]])}"
906 else
907 $asm.puts "sub #{sh4Operands(operands)}"
908 end
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000909 end
910 when "muli", "mulp"
911 $asm.puts "mul.l #{sh4Operands(operands[0..1])}"
912 $asm.puts "sts macl, #{operands[-1].sh4Operand}"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000913 when "negi", "negp"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000914 if operands.size == 2
915 $asm.puts "neg #{sh4Operands(operands)}"
916 else
917 $asm.puts "neg #{sh4Operands([operands[0], operands[0]])}"
918 end
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000919 when "andi", "andp", "ori", "orp", "xori", "xorp"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000920 raise "#{opcode} with #{operands.size} operands is not handled yet" unless operands.size == 2
921 sh4opcode = opcode[0..-2]
922 $asm.puts "#{sh4opcode} #{sh4Operands(operands)}"
923 when "shllx", "shlrx"
924 raise "Unhandled parameters for opcode #{opcode}" unless operands[0].is_a? Immediate
925 if operands[0].value == 1
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000926 $asm.puts "shl#{opcode[3, 1]} #{operands[1].sh4Operand}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000927 else
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000928 $asm.puts "shl#{opcode[3, 1]}#{operands[0].value} #{operands[1].sh4Operand}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000929 end
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +0000930 when "shalx", "sharx"
931 raise "Unhandled parameters for opcode #{opcode}" unless operands[0].is_a? Immediate and operands[0].value == 1
932 $asm.puts "sha#{opcode[3, 1]} #{operands[1].sh4Operand}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000933 when "shld", "shad"
934 $asm.puts "#{opcode} #{sh4Operands(operands)}"
935 when "loaddReversedAndIncrementAddress"
936 # As we are little endian, we don't use "fmov @Rm, DRn" here.
937 $asm.puts "fmov.s #{operands[0].sh4OperandPostInc}, #{operands[1].sh4SingleLo}"
938 $asm.puts "fmov.s #{operands[0].sh4OperandPostInc}, #{operands[1].sh4SingleHi}"
939 when "storedReversedAndDecrementAddress"
940 # As we are little endian, we don't use "fmov DRm, @Rn" here.
941 $asm.puts "fmov.s #{operands[0].sh4SingleHi}, #{operands[1].sh4OperandPreDec}"
942 $asm.puts "fmov.s #{operands[0].sh4SingleLo}, #{operands[1].sh4OperandPreDec}"
943 when "ci2d"
944 $asm.puts "lds #{operands[0].sh4Operand}, fpul"
945 $asm.puts "float fpul, #{operands[1].sh4Operand}"
946 when "fii2d"
947 $asm.puts "lds #{operands[0].sh4Operand}, fpul"
948 $asm.puts "fsts fpul, #{operands[2].sh4SingleLo}"
949 $asm.puts "lds #{operands[1].sh4Operand}, fpul"
950 $asm.puts "fsts fpul, #{operands[2].sh4SingleHi}"
951 when "fd2ii"
952 $asm.puts "flds #{operands[0].sh4SingleLo}, fpul"
953 $asm.puts "sts fpul, #{operands[1].sh4Operand}"
954 $asm.puts "flds #{operands[0].sh4SingleHi}, fpul"
955 $asm.puts "sts fpul, #{operands[2].sh4Operand}"
956 when "addd", "subd", "muld", "divd"
957 sh4opcode = opcode[0..-2]
958 $asm.puts "f#{sh4opcode} #{sh4Operands(operands)}"
959 when "bcd2i"
960 $asm.puts "ftrc #{operands[0].sh4Operand}, fpul"
961 $asm.puts "sts fpul, #{operands[1].sh4Operand}"
962 $asm.puts "float fpul, #{SH4_TMP_FPRS[0].sh4Operand}"
963 $asm.puts "fcmp/eq #{sh4Operands([operands[0], SH4_TMP_FPRS[0]])}"
964 $asm.puts "bf #{operands[2].asmLabel}"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000965 $asm.puts "tst #{sh4Operands([operands[1], operands[1]])}"
966 $asm.puts "bt #{operands[2].asmLabel}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000967 when "bdnan"
968 emitSH4BranchIfNaN(operands)
969 when "bdneq"
970 emitSH4DoubleCondBranch("eq", true, operands)
971 when "bdgteq"
972 emitSH4DoubleCondBranch("lt", true, operands)
973 when "bdlt"
974 emitSH4DoubleCondBranch("lt", false, operands)
975 when "bdlteq"
976 emitSH4DoubleCondBranch("gt", true, operands)
977 when "bdgt"
978 emitSH4DoubleCondBranch("gt", false, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000979 when "baddio", "baddpo", "bsubio", "bsubpo"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000980 raise "#{opcode} with #{operands.size} operands is not handled yet" unless operands.size == 3
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000981 $asm.puts "#{opcode[1, 3]}v #{sh4Operands([operands[0], operands[1]])}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000982 $asm.puts "bt #{operands[2].asmLabel}"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000983 when "bmulio", "bmulpo"
984 raise "Invalid operands number (#{operands.size})" unless operands.size == 5
985 $asm.puts "dmuls.l #{sh4Operands([operands[2], operands[3]])}"
986 $asm.puts "sts macl, #{operands[3].sh4Operand}"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000987 $asm.puts "cmp/pz #{operands[3].sh4Operand}"
988 $asm.puts "movt #{operands[1].sh4Operand}"
oliver@apple.com22b28562013-08-13 22:15:13 +0000989 $asm.puts "add #-1, #{operands[1].sh4Operand}"
990 $asm.puts "sts mach, #{operands[0].sh4Operand}"
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +0000991 $asm.puts "cmp/eq #{sh4Operands([operands[0], operands[1]])}"
992 $asm.puts "bf #{operands[4].asmLabel}"
993 when "btiz", "btpz", "btbz", "btinz", "btpnz", "btbnz"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +0000994 if operands.size == 3
995 $asm.puts "tst #{sh4Operands([operands[0], operands[1]])}"
996 else
997 if operands[0].sh4Operand == "r0"
998 $asm.puts "cmp/eq #0, r0"
999 else
1000 $asm.puts "tst #{sh4Operands([operands[0], operands[0]])}"
1001 end
1002 end
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001003 emitSH4BranchIfT(operands[-1], (opcode[-2, 2] == "nz"))
1004 when "cieq", "cpeq", "cbeq"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001005 emitSH4CompareSet("eq", false, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001006 when "cineq", "cpneq", "cbneq"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001007 emitSH4CompareSet("eq", true, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001008 when "cib", "cpb", "cbb"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001009 emitSH4CompareSet("hs", true, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001010 when "bieq", "bpeq", "bbeq"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001011 emitSH4CondBranch("eq", false, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001012 when "bineq", "bpneq", "bbneq"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001013 emitSH4CondBranch("eq", true, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001014 when "bib", "bpb", "bbb"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001015 emitSH4CondBranch("hs", true, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001016 when "bia", "bpa", "bba"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001017 emitSH4CondBranch("hi", false, operands)
commit-queue@webkit.org673814c2013-09-16 09:05:38 +00001018 when "bibeq", "bpbeq"
1019 emitSH4CondBranch("hi", true, operands)
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001020 when "biaeq", "bpaeq"
1021 emitSH4CondBranch("hs", false, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001022 when "bigteq", "bpgteq", "bbgteq"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001023 emitSH4CondBranch("ge", false, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001024 when "bilt", "bplt", "bblt"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001025 emitSH4CondBranch("ge", true, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001026 when "bigt", "bpgt", "bbgt"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001027 emitSH4CondBranch("gt", false, operands)
commit-queue@webkit.org6e0ff702013-04-30 22:10:51 +00001028 when "bilteq", "bplteq", "bblteq"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001029 emitSH4CondBranch("gt", true, operands)
1030 when "bs"
1031 $asm.puts "cmp/pz #{operands[0].sh4Operand}"
1032 $asm.puts "bf #{operands[1].asmLabel}"
1033 when "call"
1034 if operands[0].is_a? LocalLabelReference
1035 $asm.puts "bsr #{operands[0].asmLabel}"
1036 $asm.puts "nop"
1037 elsif operands[0].is_a? RegisterID or operands[0].is_a? SpecialRegister
1038 emitSH4Branch("jsr", operands[0])
1039 else
1040 raise "Unhandled parameters for opcode #{opcode} at #{codeOriginString}"
1041 end
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001042 when "jmp"
1043 if operands[0].is_a? LocalLabelReference
1044 $asm.puts "bra #{operands[0].asmLabel}"
1045 $asm.puts "nop"
1046 elsif operands[0].is_a? RegisterID or operands[0].is_a? SpecialRegister
1047 emitSH4Branch("jmp", operands[0])
1048 else
1049 raise "Unhandled parameters for opcode #{opcode} at #{codeOriginString}"
1050 end
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001051 when "ret"
1052 $asm.puts "rts"
1053 $asm.puts "nop"
1054 when "loadb"
1055 $asm.puts "mov.b #{sh4Operands(operands)}"
1056 $asm.puts "extu.b #{sh4Operands([operands[1], operands[1]])}"
oliver@apple.com22b28562013-08-13 22:15:13 +00001057 when "storeb"
1058 $asm.puts "mov.b #{sh4Operands(operands)}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001059 when "loadh"
1060 $asm.puts "mov.w #{sh4Operands(operands)}"
1061 $asm.puts "extu.w #{sh4Operands([operands[1], operands[1]])}"
1062 when "loadi", "loadis", "loadp", "storei", "storep"
1063 $asm.puts "mov.l #{sh4Operands(operands)}"
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +00001064 when "alignformova"
julien.brianceau@gmail.com39fbe662014-04-14 21:46:18 +00001065 $asm.puts ".balign 4" # As balign directive is in a code section, fill value is 'nop' instruction.
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +00001066 when "mova"
1067 $asm.puts "mova #{sh4Operands(operands)}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001068 when "move"
commit-queue@webkit.org004ed102013-10-15 18:03:42 +00001069 if operands[0].is_a? ConstPoolEntry
1070 if operands[0].size == 16
1071 $asm.puts "mov.w #{operands[0].labelref.asmLabel}, #{operands[1].sh4Operand}"
1072 else
1073 $asm.puts "mov.l #{operands[0].labelref.asmLabel}, #{operands[1].sh4Operand}"
1074 end
commit-queue@webkit.orgea3fae72013-11-14 16:52:48 +00001075 elsif operands[0].sh4Operand != operands[1].sh4Operand
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001076 $asm.puts "mov #{sh4Operands(operands)}"
1077 end
1078 when "leap"
1079 if operands[0].is_a? BaseIndex
1080 biop = operands[0]
oliver@apple.com22b28562013-08-13 22:15:13 +00001081 $asm.puts "mov #{sh4Operands([biop.index, operands[1]])}"
1082 if biop.scaleShift > 0
1083 emitSH4ShiftImm(biop.scaleShift, operands[1], "l")
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001084 end
oliver@apple.com22b28562013-08-13 22:15:13 +00001085 $asm.puts "add #{sh4Operands([biop.base, operands[1]])}"
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001086 if biop.offset.value != 0
1087 $asm.puts "add #{sh4Operands([biop.offset, operands[1]])}"
1088 end
1089 elsif operands[0].is_a? Address
1090 if operands[0].base != operands[1]
1091 $asm.puts "mov #{sh4Operands([operands[0].base, operands[1]])}"
1092 end
1093 if operands[0].offset.value != 0
1094 $asm.puts "add #{sh4Operands([operands[0].offset, operands[1]])}"
1095 end
1096 else
1097 raise "Unhandled parameters for opcode #{opcode} at #{codeOriginString}"
1098 end
1099 when "ldspr"
1100 $asm.puts "lds #{sh4Operands(operands)}, pr"
1101 when "stspr"
1102 $asm.puts "sts pr, #{sh4Operands(operands)}"
commit-queue@webkit.org5c642dd2013-11-21 17:11:35 +00001103 when "memfence"
1104 $asm.puts "synco"
julien.brianceau@gmail.comb05cfba2014-04-11 15:55:29 +00001105 when "pop"
1106 if operands[0].sh4Operand == "pr"
1107 $asm.puts "lds.l @r15+, #{sh4Operands(operands)}"
1108 else
1109 $asm.puts "mov.l @r15+, #{sh4Operands(operands)}"
1110 end
1111 when "push"
1112 if operands[0].sh4Operand == "pr"
1113 $asm.puts "sts.l #{sh4Operands(operands)}, @-r15"
1114 else
1115 $asm.puts "mov.l #{sh4Operands(operands)}, @-r15"
1116 end
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001117 when "break"
1118 # This special opcode always generates an illegal instruction exception.
1119 $asm.puts ".word 0xfffd"
1120 else
commit-queue@webkit.orge458dcb2013-07-25 10:24:20 +00001121 lowerDefault
commit-queue@webkit.org0486d5d2013-04-15 23:04:15 +00001122 end
1123 end
1124end
1125