Changeset 148790 in webkit


Ignore:
Timestamp:
Apr 20, 2013 3:27:33 AM (11 years ago)
Author:
allan.jensen@digia.com
Message:

LLint should be able to use x87 instead of SSE for floating pointer
https://bugs.webkit.org/show_bug.cgi?id=112239

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Implements LLInt floating point operations in x87, to ensure we support
x86 without SSE2.

X86 (except 64bit) now defaults to using x87 instructions in order to
support all 32bit x86 back to i686. The implementation uses the fucomi
instruction from i686 which sets the new minimum.

The FPU registers must always be empty on entering or exiting a function.
We make sure to only use two X87 registers, and they are always emptied
before calling deeper functions or returning from the LLInt.

  • jit/JITStubs.cpp:

(JSC): Empty FPU registers before exiting.

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • offlineasm/instructions.rb:
  • offlineasm/x86.rb:

Source/WTF:

Disable GTK workaround now that LLInt does not require SSE2.

  • wtf/Platform.h:
Location:
trunk/Source
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r148779 r148790  
     12013-04-20  Allan Sandfeld Jensen  <allan.jensen@digia.com>
     2
     3        LLint should be able to use x87 instead of SSE for floating pointer
     4        https://bugs.webkit.org/show_bug.cgi?id=112239
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Implements LLInt floating point operations in x87, to ensure we support
     9        x86 without SSE2.
     10
     11        X86 (except 64bit) now defaults to using x87 instructions in order to
     12        support all 32bit x86 back to i686. The implementation uses the fucomi
     13        instruction from i686 which sets the new minimum.
     14
     15        The FPU registers must always be empty on entering or exiting a function.
     16        We make sure to only use two X87 registers, and they are always emptied
     17        before calling deeper functions or returning from the LLInt.
     18
     19        * jit/JITStubs.cpp:
     20        (JSC): Empty FPU registers before exiting.
     21        * llint/LowLevelInterpreter32_64.asm:
     22        * llint/LowLevelInterpreter64.asm:
     23        * offlineasm/instructions.rb:
     24        * offlineasm/x86.rb:
     25
    1262013-04-19  Roger Fong  <roger_fong@apple.com>
    227
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r148696 r148790  
    100100    "pushl %ebx" "\n"
    101101    "subl $0x3c, %esp" "\n"
     102    "movw $0x02FF, %bx" "\n"
     103    "movw %bx, 0(%esp)" "\n"
     104    "fldcw 0(%esp)" "\n"
    102105    "movl 0x58(%esp), %edi" "\n"
    103106    "call *0x50(%esp)" "\n"
     
    107110    "popl %esi" "\n"
    108111    "popl %ebp" "\n"
     112    "ffree %st(1)" "\n"
    109113    "ret" "\n"
    110114".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r148696 r148790  
    111111        call function
    112112    elsif X86
     113        resetX87Stack
    113114        poke arg1, 0
    114115        poke arg2, 1
     
    134135        call function
    135136    elsif X86
     137        resetX87Stack
    136138        poke arg1, 0
    137139        poke arg2, 1
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r148696 r148790  
    8989    leap [PB, PC, 8], PC
    9090    move PB, t3
     91    if X86_64
     92        resetX87Stack
     93    end
    9194end
    9295
  • trunk/Source/JavaScriptCore/offlineasm/instructions.rb

    r148474 r148790  
    255255    [
    256256     "cdqi",
    257      "idivi"
     257     "idivi",
     258     "resetX87Stack"
    258259    ]
    259260
  • trunk/Source/JavaScriptCore/offlineasm/x86.rb

    r147794 r148790  
    11# Copyright (C) 2012 Apple Inc. All rights reserved.
     2# Copyright (C) 2013 Digia Plc. and/or its subsidiary(-ies)
    23#
    34# Redistribution and use in source and binary forms, with or without
     
    3536end
    3637
     38def useX87
     39    case $activeBackend
     40    when "X86"
     41        true
     42    when "X86_64"
     43        false
     44    else
     45        raise "bad value for $activeBackend: #{$activeBackend}"
     46    end
     47end
     48
    3749class SpecialRegister < NoChildren
    3850    def x86Operand(kind)
     
    256268    def x86Operand(kind)
    257269        raise unless kind == :double
     270        raise if useX87
    258271        case name
    259272        when "ft0", "fa0", "fr"
     
    272285            raise "Bad register #{name} for X86 at #{codeOriginString}"
    273286        end
     287    end
     288    def x87DefaultStackPosition
     289        case name
     290        when "ft0", "fr"
     291            0
     292        when "ft1"
     293            1
     294        when "ft2", "ft3", "ft4", "ft5"
     295            raise "Unimplemented register #{name} for X86 at #{codeOriginString}"
     296        else
     297            raise "Bad register #{name} for X86 at #{codeOriginString}"
     298        end
     299    end
     300    def x87Operand(offset)
     301        raise unless useX87
     302        raise unless offset == 0 or offset == 1
     303        "%st(#{x87DefaultStackPosition + offset})"
    274304    end
    275305    def x86CallOperand(kind)
     
    423453            isX64 ? "q" : raise
    424454        when :double
    425             "sd"
     455            not useX87 ? "sd" : raise
    426456        else
    427457            raise
     
    479509   
    480510    def handleX86DoubleBranch(branchOpcode, mode)
    481         case mode
    482         when :normal
    483             $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
    484         when :reverse
    485             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
    486         else
    487             raise mode.inspect
     511        if useX87
     512            handleX87Compare(mode)
     513        else
     514            case mode
     515            when :normal
     516                $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
     517            when :reverse
     518                $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
     519            else
     520                raise mode.inspect
     521            end
    488522        end
    489523        $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
     
    585619        $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
    586620    end
    587    
     621
    588622    def handleX86Add(kind)
    589623        if operands.size == 3 and operands[1] == operands[2]
     
    651685    end
    652686   
     687    def handleX87Compare(mode)
     688        case mode
     689        when :normal
     690            if (operands[0].x87DefaultStackPosition == 0)
     691                $asm.puts "fucomi #{operands[1].x87Operand(0)}"
     692            else
     693                $asm.puts "fld #{operands[0].x87Operand(0)}"
     694                $asm.puts "fucomip #{operands[1].x87Operand(1)}"
     695            end
     696        when :reverse
     697            if (operands[1].x87DefaultStackPosition == 0)
     698                $asm.puts "fucomi #{operands[0].x87Operand(0)}"
     699            else
     700                $asm.puts "fld #{operands[1].x87Operand(0)}"
     701                $asm.puts "fucomip #{operands[0].x87Operand(1)}"
     702            end
     703        else
     704            raise mode.inspect
     705        end
     706    end
     707
     708    def handleX87BinOp(opcode, opcodereverse)
     709        if (operands[1].x87DefaultStackPosition == 0)
     710            $asm.puts "#{opcode} #{operands[0].x87Operand(0)}, %st"
     711        elsif (operands[0].x87DefaultStackPosition == 0)
     712            $asm.puts "#{opcodereverse} %st, #{operands[1].x87Operand(0)}"
     713        else
     714            $asm.puts "fld #{operands[0].x87Operand(0)}"
     715            $asm.puts "#{opcodereverse}p %st, #{operands[1].x87Operand(1)}"
     716        end
     717    end
     718
    653719    def lowerX86
    654720        raise unless $activeBackend == "X86"
     
    750816        when "storeb"
    751817            $asm.puts "movb #{x86Operands(:byte, :byte)}"
    752         when "loadd", "moved", "stored"
    753             $asm.puts "movsd #{x86Operands(:double, :double)}"
     818        when "loadd"
     819            if useX87
     820                $asm.puts "fldl #{operands[0].x86Operand(:double)}"
     821                $asm.puts "fstp #{operands[1].x87Operand(1)}"
     822            else
     823                $asm.puts "movsd #{x86Operands(:double, :double)}"
     824            end
     825        when "moved"
     826            if useX87
     827                if (operands[0].x87DefaultStackPosition == 0)
     828                    $asm.puts "fst #{operands[1].x87Operand(0)}"
     829                else
     830                    $asm.puts "fld #{operands[0].x87Operand(0)}"
     831                    $asm.puts "fstp #{operands[1].x87Operand(1)}"
     832                end
     833            else
     834                $asm.puts "movsd #{x86Operands(:double, :double)}"
     835            end
     836        when "stored"
     837            if useX87
     838                if (operands[0].x87DefaultStackPosition == 0)
     839                    $asm.puts "fstl #{operands[1].x86Operand(:double)}"
     840                else
     841                    $asm.puts "fld #{operands[0].x87Operand(0)}"
     842                    $asm.puts "fstpl #{operands[1].x86Operand(:double)}"
     843                end
     844            else
     845                $asm.puts "movsd #{x86Operands(:double, :double)}"
     846            end
    754847        when "addd"
    755             $asm.puts "addsd #{x86Operands(:double, :double)}"
     848            if useX87
     849                handleX87BinOp("fadd", "fadd")
     850            else
     851                $asm.puts "addsd #{x86Operands(:double, :double)}"
     852            end
     853        when "muld"
     854            if useX87
     855                handleX87BinOp("fmul", "fmul")
     856            else
     857                $asm.puts "mulsd #{x86Operands(:double, :double)}"
     858            end
     859        when "subd"
     860            if useX87
     861                handleX87BinOp("fsub", "fsubr")
     862            else
     863                $asm.puts "subsd #{x86Operands(:double, :double)}"
     864            end
    756865        when "divd"
    757             $asm.puts "divsd #{x86Operands(:double, :double)}"
    758         when "subd"
    759             $asm.puts "subsd #{x86Operands(:double, :double)}"
    760         when "muld"
    761             $asm.puts "mulsd #{x86Operands(:double, :double)}"
     866            if useX87
     867                handleX87BinOp("fdiv", "fdivr")
     868            else
     869                $asm.puts "divsd #{x86Operands(:double, :double)}"
     870            end
    762871        when "sqrtd"
    763             $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
     872            if useX87
     873                $asm.puts "fld #{operands[0].x87Operand(0)}"
     874                $asm.puts "fsqrtl"
     875                $asm.puts "fstp #{operands[1].x87Operand(1)}"
     876            else
     877                $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
     878            end
    764879        when "ci2d"
    765             $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
     880            if useX87
     881                sp = RegisterID.new(nil, "sp")
     882                $asm.puts "movl #{operands[0].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})"
     883                $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})"
     884                $asm.puts "fstp #{operands[1].x87Operand(1)}"
     885            else
     886                $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
     887            end
    766888        when "bdeq"
    767             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
     889            if useX87
     890                handleX87Compare(:normal)
     891            else
     892                $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
     893            end
    768894            if operands[0] == operands[1]
    769895                # This is just a jump ordered, which is a jnp.
     
    788914            handleX86DoubleBranch("je", :normal)
    789915        when "bdnequn"
    790             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
     916            if useX87
     917                handleX87Compare(:normal)
     918            else
     919                $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
     920            end
    791921            if operands[0] == operands[1]
    792922                # This is just a jump unordered, which is a jp.
     
    810940            handleX86DoubleBranch("jbe", :normal)
    811941        when "btd2i"
     942            # FIXME: unused and unimplemented for x87
     943            raise if useX87
    812944            $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
    813945            $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
    814946            $asm.puts "je #{operands[2].asmLabel}"
    815947        when "td2i"
     948            # FIXME: unused and unimplemented for x87
     949            raise if useX87
    816950            $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
    817951        when "bcd2i"
    818             $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
    819             $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
    820             $asm.puts "je #{operands[2].asmLabel}"
    821             $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
    822             $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
    823             $asm.puts "jp #{operands[2].asmLabel}"
    824             $asm.puts "jne #{operands[2].asmLabel}"
     952            if useX87
     953                sp = RegisterID.new(nil, "sp")
     954                if (operands[0].x87DefaultStackPosition == 0)
     955                    $asm.puts "fistl -4(#{sp.x86Operand(:ptr)})"
     956                else
     957                    $asm.puts "fld #{operands[0].x87Operand(0)}"
     958                    $asm.puts "fistpl -4(#{sp.x86Operand(:ptr)})"
     959                end
     960                $asm.puts "movl -4(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}"
     961                $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
     962                $asm.puts "je #{operands[2].asmLabel}"
     963                $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})"
     964                $asm.puts "fucomip #{operands[0].x87Operand(1)}"
     965                $asm.puts "jp #{operands[2].asmLabel}"
     966                $asm.puts "jne #{operands[2].asmLabel}"
     967            else
     968                $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
     969                $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
     970                $asm.puts "je #{operands[2].asmLabel}"
     971                $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
     972                $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
     973                $asm.puts "jp #{operands[2].asmLabel}"
     974                $asm.puts "jne #{operands[2].asmLabel}"
     975            end
    825976        when "movdz"
    826             $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
     977            if useX87
     978                $asm.puts "fldzl"
     979                $asm.puts "fstp #{operands[0].x87Operand(1)}"
     980            else
     981                $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
     982            end
    827983        when "pop"
    828984            $asm.puts "pop #{operands[0].x86Operand(:ptr)}"
     
    11181274            $asm.puts "idivl #{operands[0].x86Operand(:int)}"
    11191275        when "fii2d"
    1120             $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
    1121             $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
    1122             $asm.puts "psllq $32, %xmm7"
    1123             $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
     1276            if useX87
     1277                sp = RegisterID.new(nil, "sp")
     1278                $asm.puts "movl #{operands[0].x86Operand(:int)}, -8(#{sp.x86Operand(:ptr)})"
     1279                $asm.puts "movl #{operands[1].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})"
     1280                $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})"
     1281                $asm.puts "fstp #{operands[2].x87Operand(1)}"
     1282            else
     1283                $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
     1284                $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
     1285                $asm.puts "psllq $32, %xmm7"
     1286                $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
     1287            end
    11241288        when "fd2ii"
    1125             $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
    1126             $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
    1127             $asm.puts "psrlq $32, %xmm7"
    1128             $asm.puts "movd %xmm7, #{operands[2].x86Operand(:int)}"
     1289            if useX87
     1290                sp = RegisterID.new(nil, "sp")
     1291                if (operands[0].x87DefaultStackPosition == 0)
     1292                    $asm.puts "fstl -8(#{sp.x86Operand(:ptr)})"
     1293                else
     1294                    $asm.puts "fld #{operands[0].x87Operand(0)}"
     1295                    $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
     1296                end
     1297                $asm.puts "movl -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}"
     1298                $asm.puts "movl -4(#{sp.x86Operand(:ptr)}), #{operands[2].x86Operand(:int)}"
     1299            else
     1300                $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
     1301                $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
     1302                $asm.puts "psrlq $32, %xmm7"
     1303                $asm.puts "movd %xmm7, #{operands[2].x86Operand(:int)}"
     1304            end
    11291305        when "fq2d"
    1130             $asm.puts "movd #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}"
     1306            if useX87
     1307                sp = RegisterID.new(nil, "sp")
     1308                $asm.puts "movq #{operands[0].x86Operand(:quad)}, -8(#{sp.x86Operand(:ptr)})"
     1309                $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})"
     1310                $asm.puts "fstp #{operands[1].x87Operand(1)}"
     1311            else
     1312                $asm.puts "movq #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}"
     1313            end
    11311314        when "fd2q"
    1132             $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}"
     1315            if useX87
     1316                sp = RegisterID.new(nil, "sp")
     1317                if (operands[0].x87DefaultStackPosition == 0)
     1318                    $asm.puts "fstl -8(#{sp.x86Operand(:ptr)})"
     1319                else
     1320                    $asm.puts "fld #{operands[0].x87Operand(0)}"
     1321                    $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
     1322                end
     1323                $asm.puts "movq -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
     1324            else
     1325                $asm.puts "movq #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}"
     1326            end
    11331327        when "bo"
    11341328            $asm.puts "jo #{operands[0].asmLabel}"
     
    11431337        when "leap"
    11441338            $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
     1339        when "resetX87Stack"
     1340            if useX87
     1341                2.times {
     1342                    | offset |
     1343                    $asm.puts "ffree %st(#{offset})"
     1344                }
     1345            end
    11451346        else
    11461347            lowerDefault
  • trunk/Source/WTF/ChangeLog

    r148779 r148790  
     12013-04-20  Allan Sandfeld Jensen  <allan.jensen@digia.com>
     2
     3        LLint should be able to use x87 instead of SSE for floating pointer
     4        https://bugs.webkit.org/show_bug.cgi?id=112239
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Disable GTK workaround now that LLInt does not require SSE2.
     9
     10        * wtf/Platform.h:
     11
    1122013-04-19  Roger Fong  <roger_fong@apple.com>
    213
  • trunk/Source/WTF/wtf/Platform.h

    r148625 r148790  
    729729#endif
    730730
    731 /* On the GTK+ port we take an extra precaution for LLINT support:
    732  * We disable it on x86 builds if the build target doesn't support SSE2
    733  * instructions (LLINT requires SSE2 on this platform). */
    734 #if !defined(ENABLE_LLINT) && PLATFORM(GTK) && CPU(X86) && COMPILER(GCC) \
    735     && !defined(__SSE2__)
    736 #define ENABLE_LLINT 0
    737 #endif
    738 
    739731/* On some of the platforms where we have a JIT, we want to also have the
    740732   low-level interpreter. */
Note: See TracChangeset for help on using the changeset viewer.