Changeset 157452 in webkit for trunk/Source/JavaScriptCore/offlineasm/sh4.rb
- Timestamp:
- Oct 15, 2013, 11:03:42 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/offlineasm/sh4.rb
r155876 r157452 145 145 end 146 146 147 class ConstPool < Node 148 attr_reader :size 149 attr_reader :entries 150 151 def initialize(codeOrigin, entries, size) 152 super(codeOrigin) 153 raise "Invalid size #{size} for ConstPool" unless size == 16 or size == 32 154 @size = size 155 @entries = entries 156 end 157 158 def dump 159 "#{size}: #{entries}" 160 end 161 162 def address? 163 false 164 end 165 166 def label? 167 false 168 end 169 170 def immediate? 171 false 172 end 173 174 def register? 175 false 176 end 177 178 def lowerSH4 179 if size == 16 180 $asm.puts ".balign 2" 181 else 182 $asm.puts ".balign 4" 183 end 184 entries.map { 185 |e| 186 e.label.lower("SH4") 187 if e.size == 16 188 $asm.puts ".word #{e.value}" 189 else 190 $asm.puts ".long #{e.value}" 191 end 192 } 193 end 194 end 195 196 class ConstPoolEntry < Node 197 attr_reader :size 198 attr_reader :value 199 attr_reader :label 200 attr_reader :labelref 201 202 def initialize(codeOrigin, value, size) 203 super(codeOrigin) 204 raise "Invalid size #{size} for ConstPoolEntry" unless size == 16 or size == 32 205 @size = size 206 @value = value 207 @label = LocalLabel.unique("constpool#{size}") 208 @labelref = LocalLabelReference.new(codeOrigin, label) 209 end 210 211 def dump 212 "#{value} (#{size} @ #{label})" 213 end 214 215 def ==(other) 216 other.is_a? ConstPoolEntry and other.value == @value 217 end 218 219 def address? 220 false 221 end 222 223 def label? 224 false 225 end 226 227 def immediate? 228 false 229 end 230 231 def register? 232 false 233 end 234 end 235 147 236 148 237 # … … 359 448 if node.is_a? Instruction 360 449 case node.opcode 361 when "jmp" 450 when "jmp", "call" 362 451 if node.operands[0].is_a? LabelReference 363 452 tmp = Tmp.new(codeOrigin, :gpr) 364 newList << Instruction.new(codeOrigin, "jmpf", [tmp, node.operands[0]]) 453 newList << Instruction.new(codeOrigin, "move", [node.operands[0], tmp]) 454 newList << Instruction.new(codeOrigin, node.opcode, [tmp]) 365 455 else 366 456 newList << node 367 457 end 368 when "call" 369 if node.operands[0].is_a? LabelReference 370 tmp1 = Tmp.new(codeOrigin, :gpr) 371 tmp2 = Tmp.new(codeOrigin, :gpr) 372 newList << Instruction.new(codeOrigin, "callf", [tmp1, tmp2, node.operands[0]]) 458 else 459 newList << node 460 end 461 else 462 newList << node 463 end 464 } 465 newList 466 end 467 468 469 # 470 # Group immediate values outside -128..127 range into constant pools for SH4. 471 # These constant pools will be placed behind non-return opcodes jmp and ret, for example: 472 # 473 # move 1024, foo 474 # ... 475 # ret 476 # 477 # becomes: 478 # 479 # move [label], foo 480 # ... 481 # ret 482 # label: 1024 483 # 484 485 def sh4LowerConstPool(list) 486 newList = [] 487 currentPool16 = [] 488 currentPool32 = [] 489 list.each { 490 | node | 491 if node.is_a? Instruction 492 case node.opcode 493 when "jmp", "ret" 494 newList << node 495 if not currentPool16.empty? 496 newList << ConstPool.new(codeOrigin, currentPool16, 16) 497 currentPool16 = [] 498 end 499 if not currentPool32.empty? 500 newList << ConstPool.new(codeOrigin, currentPool32, 32) 501 currentPool32 = [] 502 end 503 when "move" 504 if node.operands[0].is_a? Immediate and not (-128..127).include? node.operands[0].value 505 poolEntry = nil 506 if (-32768..32767).include? node.operands[0].value 507 currentPool16.each { |e| 508 if e.value == node.operands[0].value 509 poolEntry = e 510 end 511 } 512 if !poolEntry 513 poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].value, 16) 514 currentPool16 << poolEntry 515 end 516 else 517 currentPool32.each { |e| 518 if e.value == node.operands[0].value 519 poolEntry = e 520 end 521 } 522 if !poolEntry 523 poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].value, 32) 524 currentPool32 << poolEntry 525 end 526 end 527 newList << Instruction.new(codeOrigin, "move", [poolEntry, node.operands[1]]) 528 elsif node.operands[0].is_a? LabelReference 529 poolEntry = nil 530 currentPool32.each { |e| 531 if e.value == node.operands[0].asmLabel 532 poolEntry = e 533 end 534 } 535 if !poolEntry 536 poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].asmLabel, 32) 537 currentPool32 << poolEntry 538 end 539 newList << Instruction.new(codeOrigin, "move", [poolEntry, node.operands[1]]) 373 540 else 374 541 newList << node … … 381 548 end 382 549 } 550 if not currentPool16.empty? 551 newList << ConstPool.new(codeOrigin, currentPool16, 16) 552 end 553 if not currentPool32.empty? 554 newList << ConstPool.new(codeOrigin, currentPool32, 32) 555 end 383 556 newList 384 557 end … … 434 607 result = assignRegistersToTemporaries(result, :gpr, SH4_TMP_FPRS) 435 608 609 result = sh4LowerConstPool(result) 610 436 611 return result 437 612 end … … 440 615 def sh4Operands(operands) 441 616 operands.map{|v| v.sh4Operand}.join(", ") 442 end443 444 def emitSH4Load32AndJump(constant, scratch)445 $asm.puts "mov.l 2f, #{scratch.sh4Operand}"446 $asm.puts "braf #{scratch.sh4Operand}"447 $asm.puts "nop"448 $asm.puts "1: .balign 4"449 $asm.puts "2: .long #{constant}-1b"450 end451 452 def emitSH4LoadImm(operands)453 if operands[0].value == 0x40000000454 # FirstConstantRegisterIndex const is often used (0x40000000).455 # It's more efficient to "build" the value with 3 opcodes without branch.456 $asm.puts "mov #64, #{operands[1].sh4Operand}"457 $asm.puts "shll16 #{operands[1].sh4Operand}"458 $asm.puts "shll8 #{operands[1].sh4Operand}"459 elsif (-128..127).include? operands[0].value460 $asm.puts "mov #{sh4Operands(operands)}"461 elsif (-32768..32767).include? operands[0].value462 constlabel = LocalLabel.unique("loadconstant")463 $asm.puts "mov.w @(6, PC), #{operands[1].sh4Operand}"464 $asm.puts "bra #{LocalLabelReference.new(codeOrigin, constlabel).asmLabel}"465 $asm.puts "nop"466 $asm.puts ".word #{operands[0].value}"467 constlabel.lower("SH4")468 else469 outlabel = LocalLabel.unique("load32out")470 constlabel = LocalLabel.unique("load32const")471 $asm.puts "mov.l #{LocalLabelReference.new(codeOrigin, constlabel).asmLabel}, #{operands[1].sh4Operand}"472 $asm.puts "bra #{LocalLabelReference.new(codeOrigin, outlabel).asmLabel}"473 $asm.puts "nop"474 $asm.puts ".balign 4"475 constlabel.lower("SH4")476 $asm.puts ".long #{operands[0].value}"477 outlabel.lower("SH4")478 end479 617 end 480 618 … … 507 645 sh4opcode = neg ? "bt" : "bf" 508 646 $asm.puts "#{sh4opcode} #{LocalLabelReference.new(codeOrigin, outlabel).asmLabel}" 509 if label.is_a? LocalLabelReference 510 $asm.puts "bra #{label.asmLabel}" 511 $asm.puts "nop" 512 else 513 emitSH4Load32AndJump(label.asmLabel, SH4_TMP_GPRS[0]) 514 end 647 $asm.puts "bra #{label.asmLabel}" 648 $asm.puts "nop" 515 649 outlabel.lower("SH4") 516 650 end … … 572 706 when "subi", "subp" 573 707 if operands.size == 3 574 if operands[1] == operands[2]708 if operands[1].sh4Operand == operands[2].sh4Operand 575 709 $asm.puts "neg #{sh4Operands([operands[2], operands[2]])}" 576 710 $asm.puts "add #{sh4Operands([operands[0], operands[2]])}" … … 715 849 raise "Unhandled parameters for opcode #{opcode} at #{codeOriginString}" 716 850 end 717 when "callf"718 $asm.puts ".balign 4"719 $asm.puts "mov r0, #{operands[0].sh4Operand}"720 $asm.puts "mova @(14, PC), r0"721 $asm.puts "lds r0, pr"722 $asm.puts "mov.l @(6, PC), #{operands[1].sh4Operand}"723 $asm.puts "braf #{operands[1].sh4Operand}"724 $asm.puts "mov #{operands[0].sh4Operand}, r0"725 $asm.puts ".long #{operands[2].asmLabel}-."726 851 when "jmp" 727 852 if operands[0].is_a? LocalLabelReference … … 733 858 raise "Unhandled parameters for opcode #{opcode} at #{codeOriginString}" 734 859 end 735 when "jmpf"736 emitSH4Load32AndJump(operands[1].asmLabel, operands[0])737 860 when "ret" 738 861 $asm.puts "rts" … … 749 872 $asm.puts "mov.l #{sh4Operands(operands)}" 750 873 when "move" 751 if operands[0].is_a? Immediate 752 emitSH4LoadImm(operands) 874 if operands[0].is_a? ConstPoolEntry 875 if operands[0].size == 16 876 $asm.puts "mov.w #{operands[0].labelref.asmLabel}, #{operands[1].sh4Operand}" 877 else 878 $asm.puts "mov.l #{operands[0].labelref.asmLabel}, #{operands[1].sh4Operand}" 879 end 753 880 else 754 881 $asm.puts "mov #{sh4Operands(operands)}"
Note:
See TracChangeset
for help on using the changeset viewer.