JavaScriptCore/ChangeLog

 12010-03-09 Chao-ying Fu <fu@mips.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 MIPS JIT Supports
 6 https://bugs.webkit.org/show_bug.cgi?id=30144
 7
 8 The following changes enable MIPS JIT.
 9
 10 * assembler/MIPSAssembler.h:
 11 (JSC::MIPSAssembler::lb):
 12 * assembler/MacroAssemblerMIPS.h:
 13 (JSC::MacroAssemblerMIPS::load8):
 14 (JSC::MacroAssemblerMIPS::branch8):
 15 (JSC::MacroAssemblerMIPS::branchTest8):
 16 (JSC::MacroAssemblerMIPS::setTest8):
 17 * jit/JIT.h:
 18 * jit/JITInlineMethods.h:
 19 (JSC::JIT::preserveReturnAddressAfterCall):
 20 (JSC::JIT::restoreReturnAddressBeforeReturn):
 21 * jit/JITOpcodes.cpp:
 22 * jit/JITStubs.cpp:
 23 (JSC::JITThunks::JITThunks):
 24 * jit/JITStubs.h:
 25 (JSC::JITStackFrame::returnAddressSlot):
 26 * wtf/Platform.h:
 27
1282010-03-09 Gabor Loki <loki@webkit.org>
229
330 Rubber-stamped by Maciej Stachowiak.
55736

JavaScriptCore/assembler/MIPSAssembler.h

@@public:
392392 | (rs << OP_SH_RS));
393393 }
394394
 395 void lb(RegisterID rt, RegisterID rs, int offset)
 396 {
 397 emitInst(0x80000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 398 | (offset & 0xffff));
 399 loadDelayNop();
 400 }
 401
395402 void lw(RegisterID rt, RegisterID rs, int offset)
396403 {
397404 emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
55696

JavaScriptCore/assembler/MacroAssemblerMIPS.h

@@public:
442442 // operand objects to loads and store will be implicitly constructed if a
443443 // register is passed.
444444
 445 void load8(ImplicitAddress address, RegisterID dest)
 446 {
 447 if (address.offset >= -32768 && address.offset <= 32767
 448 && !m_fixedWidth)
 449 m_assembler.lb(dest, address.base, address.offset);
 450 else {
 451 /*
 452 lui addrTemp, (offset + 0x8000) >> 16
 453 addu addrTemp, addrTemp, base
 454 lb dest, (offset & 0xffff)(addrTemp)
 455 */
 456 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 457 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 458 m_assembler.lb(dest, addrTempRegister, address.offset);
 459 }
 460 }
 461
445462 void load32(ImplicitAddress address, RegisterID dest)
446463 {
447464 if (address.offset >= -32768 && address.offset <= 32767

@@public:
856873 // jz and jnz test whether the first operand is equal to zero, and take
857874 // an optional second operand of a mask under which to perform the test.
858875
 876 Jump branch8(Condition cond, Address left, Imm32 right)
 877 {
 878 load8(left, dataTempRegister);
 879 move(right, immTempRegister);
 880 return branch32(cond, dataTempRegister, immTempRegister);
 881 }
 882
859883 Jump branch32(Condition cond, RegisterID left, RegisterID right)
860884 {
861885 if (cond == Equal || cond == Zero)

@@public:
10381062 return branchTest32(cond, dataTempRegister, mask);
10391063 }
10401064
 1065 Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
 1066 {
 1067 load8(address, dataTempRegister);
 1068 return branchTest32(cond, dataTempRegister, mask);
 1069 }
 1070
10411071 Jump jump()
10421072 {
10431073 return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);

@@public:
13321362 set32(cond, left, immTempRegister, dest);
13331363 }
13341364
 1365 void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
 1366 {
 1367 ASSERT((cond == Zero) || (cond == NonZero));
 1368 load8(address, dataTempRegister);
 1369 if (mask.m_value == -1 && !m_fixedWidth) {
 1370 if (cond == Zero)
 1371 m_assembler.sltiu(dest, dataTempRegister, 1);
 1372 else
 1373 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
 1374 } else {
 1375 move(mask, immTempRegister);
 1376 m_assembler.andInsn(cmpTempRegister, dataTempRegister,
 1377 immTempRegister);
 1378 if (cond == Zero)
 1379 m_assembler.sltiu(dest, cmpTempRegister, 1);
 1380 else
 1381 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
 1382 }
 1383 }
 1384
13351385 void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
13361386 {
13371387 ASSERT((cond == Zero) || (cond == NonZero));
55696

JavaScriptCore/jit/JIT.h

@@namespace JSC {
266266 static const FPRegisterID fpRegT0 = ARMRegisters::d0;
267267 static const FPRegisterID fpRegT1 = ARMRegisters::d1;
268268 static const FPRegisterID fpRegT2 = ARMRegisters::d2;
 269#elif CPU(MIPS)
 270 static const RegisterID returnValueRegister = MIPSRegisters::v0;
 271 static const RegisterID cachedResultRegister = MIPSRegisters::v0;
 272 static const RegisterID firstArgumentRegister = MIPSRegisters::a0;
 273
 274 // regT0 must be v0 for returning a 32-bit value.
 275 static const RegisterID regT0 = MIPSRegisters::v0;
 276
 277 // regT1 must be v1 for returning a pair of 32-bit value.
 278 static const RegisterID regT1 = MIPSRegisters::v1;
 279
 280 static const RegisterID regT2 = MIPSRegisters::t4;
 281
 282 // regT3 must be saved in the callee, so use an S register.
 283 static const RegisterID regT3 = MIPSRegisters::s2;
 284
 285 static const RegisterID callFrameRegister = MIPSRegisters::s0;
 286 static const RegisterID timeoutCheckRegister = MIPSRegisters::s1;
 287
 288 static const FPRegisterID fpRegT0 = MIPSRegisters::f4;
 289 static const FPRegisterID fpRegT1 = MIPSRegisters::f6;
 290 static const FPRegisterID fpRegT2 = MIPSRegisters::f8;
269291#else
270292 #error "JIT not supported on this platform."
271293#endif

@@namespace JSC {
684706 // sequencePutById
685707 static const int sequencePutByIdInstructionSpace = 28;
686708 static const int sequencePutByIdConstantSpace = 3;
 709#elif CPU(MIPS)
 710#if WTF_MIPS_ISA(1)
 711 static const int patchOffsetPutByIdStructure = 16;
 712 static const int patchOffsetPutByIdExternalLoad = 48;
 713 static const int patchLengthPutByIdExternalLoad = 20;
 714 static const int patchOffsetPutByIdPropertyMapOffset = 68;
 715 static const int patchOffsetGetByIdStructure = 16;
 716 static const int patchOffsetGetByIdBranchToSlowCase = 48;
 717 static const int patchOffsetGetByIdExternalLoad = 48;
 718 static const int patchLengthGetByIdExternalLoad = 20;
 719 static const int patchOffsetGetByIdPropertyMapOffset = 68;
 720 static const int patchOffsetGetByIdPutResult = 88;
 721#if ENABLE(OPCODE_SAMPLING)
 722 #error "OPCODE_SAMPLING is not yet supported"
 723#else
 724 static const int patchOffsetGetByIdSlowCaseCall = 40;
 725#endif
 726 static const int patchOffsetOpCallCompareToJump = 32;
 727 static const int patchOffsetMethodCheckProtoObj = 32;
 728 static const int patchOffsetMethodCheckProtoStruct = 56;
 729 static const int patchOffsetMethodCheckPutFunction = 88;
 730#else // WTF_MIPS_ISA(1)
 731 static const int patchOffsetPutByIdStructure = 12;
 732 static const int patchOffsetPutByIdExternalLoad = 44;
 733 static const int patchLengthPutByIdExternalLoad = 16;
 734 static const int patchOffsetPutByIdPropertyMapOffset = 60;
 735 static const int patchOffsetGetByIdStructure = 12;
 736 static const int patchOffsetGetByIdBranchToSlowCase = 44;
 737 static const int patchOffsetGetByIdExternalLoad = 44;
 738 static const int patchLengthGetByIdExternalLoad = 16;
 739 static const int patchOffsetGetByIdPropertyMapOffset = 60;
 740 static const int patchOffsetGetByIdPutResult = 76;
 741#if ENABLE(OPCODE_SAMPLING)
 742 #error "OPCODE_SAMPLING is not yet supported"
 743#else
 744 static const int patchOffsetGetByIdSlowCaseCall = 40;
 745#endif
 746 static const int patchOffsetOpCallCompareToJump = 32;
 747 static const int patchOffsetMethodCheckProtoObj = 32;
 748 static const int patchOffsetMethodCheckProtoStruct = 52;
 749 static const int patchOffsetMethodCheckPutFunction = 84;
 750#endif
687751#endif
688752#endif // USE(JSVALUE32_64)
689753
55696

JavaScriptCore/jit/JITInlineMethods.h

@@ALWAYS_INLINE void JIT::restoreReturnAdd
160160 loadPtr(address, linkRegister);
161161}
162162
 163#elif CPU(MIPS)
 164
 165ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
 166{
 167 move(returnAddressRegister, reg);
 168}
 169
 170ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
 171{
 172 move(reg, returnAddressRegister);
 173}
 174
 175ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 176{
 177 loadPtr(address, returnAddressRegister);
 178}
 179
163180#else // CPU(X86) || CPU(X86_64)
164181
165182ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
55696

JavaScriptCore/jit/JITOpcodes.cpp

@@void JIT::privateCompileCTIMachineTrampo
18341834 addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
18351835#endif // OS(WINCE)
18361836
 1837#elif CPU(MIPS)
 1838 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
 1839
 1840 // Allocate stack space for our arglist
 1841 COMPILE_ASSERT(!(sizeof(ArgList) & 0x7), ArgList_should_by_8byte_aligned);
 1842 subPtr(Imm32(sizeof(ArgList) + 24), stackPointerRegister);
 1843
 1844 // Set up arguments
 1845 subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
 1846
 1847 // Push argcount to 24 + offset($sp)
 1848 storePtr(regT0, Address(stackPointerRegister, 24 + OBJECT_OFFSETOF(ArgList, m_argCount)));
 1849
 1850 // Calculate the start of the callframe header, and store in regT1
 1851 move(callFrameRegister, regT1);
 1852 sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
 1853
 1854 // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
 1855 mul32(Imm32(sizeof(Register)), regT0, regT0);
 1856 subPtr(regT0, regT1);
 1857
 1858 // push pointer to arguments to 24 + offset($sp)
 1859 storePtr(regT1, Address(stackPointerRegister, 24 + OBJECT_OFFSETOF(ArgList, m_args)));
 1860
 1861 // Setup arg3: regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
 1862 loadPtr(Address(regT1, -(int32_t)sizeof(Register)), MIPSRegisters::a3);
 1863
 1864 // Setup arg2:
 1865 emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2);
 1866
 1867 // Setup arg1:
 1868 move(callFrameRegister, MIPSRegisters::a1);
 1869
 1870 // Setup arg4: ArgList is passed by reference. At 16($sp), store ($sp + 24)
 1871 addPtr(Imm32(24), stackPointerRegister, regT2);
 1872 storePtr(regT2, Address(stackPointerRegister, 16));
 1873
 1874 // Setup arg0 as 20($sp) to hold the returned structure.
 1875 ASSERT(sizeof(JSValue) == 4);
 1876 addPtr(Imm32(20), stackPointerRegister, MIPSRegisters::a0);
 1877
 1878 // Call
 1879 call(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_data)));
 1880
 1881 // Get returned value from 0($v0) which is the same as 20($sp)
 1882 loadPtr(Address(returnValueRegister, 0), returnValueRegister);
 1883
 1884 // Restore stack space
 1885 addPtr(Imm32(sizeof(ArgList) + 24), stackPointerRegister);
 1886
18371887#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
18381888#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
18391889#else
55696

JavaScriptCore/jit/JITStubs.cpp

@@SYMBOL_STRING(ctiOpThrowNotCaught) ":" "
642642 "mov pc, lr" "\n"
643643);
644644
 645#elif CPU(MIPS)
 646
 647#if USE(JIT_STUB_ARGUMENT_VA_LIST)
 648#error "JIT_STUB_ARGUMENT_VA_LIST not supported on MIPS."
 649#endif
 650
 651asm volatile(
 652".text" "\n"
 653".align 2" "\n"
 654".set noreorder" "\n"
 655".set nomacro" "\n"
 656".set nomips16" "\n"
 657".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 658".ent " SYMBOL_STRING(ctiTrampoline) "\n"
 659SYMBOL_STRING(ctiTrampoline) ":" "\n"
 660 "addiu $29,$29,-72" "\n"
 661 "sw $31,44($29)" "\n"
 662 "sw $18,40($29)" "\n"
 663 "sw $17,36($29)" "\n"
 664 "sw $16,32($29)" "\n"
 665#if WTF_MIPS_PIC
 666 "sw $28,28($29)" "\n"
 667#endif
 668 "move $16,$6 # set callFrameRegister" "\n"
 669 "li $17,512 # set timeoutCheckRegister" "\n"
 670 "move $25,$4 # move executableAddress to t9" "\n"
 671 "sw $5,52($29) # store registerFile to current stack" "\n"
 672 "sw $6,56($29) # store callFrame to curent stack" "\n"
 673 "sw $7,60($29) # store exception to current stack" "\n"
 674 "lw $8,88($29) # load enableProfilerReference from previous stack" "\n"
 675 "lw $9,92($29) # load globalData from previous stack" "\n"
 676 "sw $8,64($29) # store enableProfilerReference to current stack" "\n"
 677 "jalr $25" "\n"
 678 "sw $9,68($29) # store globalData to current stack" "\n"
 679 "lw $16,32($29)" "\n"
 680 "lw $17,36($29)" "\n"
 681 "lw $18,40($29)" "\n"
 682 "lw $31,44($29)" "\n"
 683 "jr $31" "\n"
 684 "addiu $29,$29,72" "\n"
 685".set reorder" "\n"
 686".set macro" "\n"
 687".end " SYMBOL_STRING(ctiTrampoline) "\n"
 688);
 689
 690asm volatile(
 691".text" "\n"
 692".align 2" "\n"
 693".set noreorder" "\n"
 694".set nomacro" "\n"
 695".set nomips16" "\n"
 696".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 697".ent " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 698SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 699#if WTF_MIPS_PIC
 700 "lw $28,28($29)" "\n"
 701".set macro" "\n"
 702 "la $25," SYMBOL_STRING(cti_vm_throw) "\n"
 703".set nomacro" "\n"
 704 "bal " SYMBOL_STRING(cti_vm_throw) "\n"
 705 "move $4,$29" "\n"
 706#else
 707 "jal " SYMBOL_STRING(cti_vm_throw) "\n"
 708 "move $4,$29" "\n"
 709#endif
 710 "lw $16,32($29)" "\n"
 711 "lw $17,36($29)" "\n"
 712 "lw $18,40($29)" "\n"
 713 "lw $31,44($29)" "\n"
 714 "jr $31" "\n"
 715 "addiu $29,$29,72" "\n"
 716".set reorder" "\n"
 717".set macro" "\n"
 718".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 719);
 720
 721asm volatile(
 722".text" "\n"
 723".align 2" "\n"
 724".set noreorder" "\n"
 725".set nomacro" "\n"
 726".set nomips16" "\n"
 727".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 728".ent " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 729SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 730 "lw $16,32($29)" "\n"
 731 "lw $17,36($29)" "\n"
 732 "lw $18,40($29)" "\n"
 733 "lw $31,44($29)" "\n"
 734 "jr $31" "\n"
 735 "addiu $29,$29,72" "\n"
 736".set reorder" "\n"
 737".set macro" "\n"
 738".end " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 739);
 740
645741#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
646742
647743__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)

@@JITThunks::JITThunks(JSGlobalData* globa
776872 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 0x40);
777873
778874 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 0x1C);
 875
 876#elif CPU(MIPS)
 877 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == 28);
 878 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == 32);
 879 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == 36);
 880 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == 40);
 881 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == 44);
 882 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 48);
 883 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == 52);
 884 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 56);
 885 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 60);
 886 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 64);
 887 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == 68);
 888
779889#endif
780890}
781891

@@static NEVER_INLINE void throwStackOverf
10341144 ); \
10351145 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
10361146
 1147#elif CPU(MIPS)
 1148#if WTF_MIPS_PIC
 1149#define DEFINE_STUB_FUNCTION(rtype, op) \
 1150 extern "C" { \
 1151 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
 1152 }; \
 1153 asm volatile( \
 1154 ".text" "\n" \
 1155 ".align 2" "\n" \
 1156 ".set noreorder" "\n" \
 1157 ".set nomacro" "\n" \
 1158 ".set nomips16" "\n" \
 1159 ".globl " SYMBOL_STRING(cti_##op) "\n" \
 1160 ".ent " SYMBOL_STRING(cti_##op) "\n" \
 1161 SYMBOL_STRING(cti_##op) ":" "\n" \
 1162 "lw $28,28($29)" "\n" \
 1163 "sw $31,48($29)" "\n" \
 1164 ".set macro" "\n" \
 1165 "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
 1166 ".set nomacro" "\n" \
 1167 "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
 1168 "nop" "\n" \
 1169 "lw $31,48($29)" "\n" \
 1170 "jr $31" "\n" \
 1171 "nop" "\n" \
 1172 ".set reorder" "\n" \
 1173 ".set macro" "\n" \
 1174 ".end " SYMBOL_STRING(cti_##op) "\n" \
 1175 ); \
 1176 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
 1177
 1178#else // WTF_MIPS_PIC
 1179#define DEFINE_STUB_FUNCTION(rtype, op) \
 1180 extern "C" { \
 1181 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
 1182 }; \
 1183 asm volatile( \
 1184 ".text" "\n" \
 1185 ".align 2" "\n" \
 1186 ".set noreorder" "\n" \
 1187 ".set nomacro" "\n" \
 1188 ".set nomips16" "\n" \
 1189 ".globl " SYMBOL_STRING(cti_##op) "\n" \
 1190 ".ent " SYMBOL_STRING(cti_##op) "\n" \
 1191 SYMBOL_STRING(cti_##op) ":" "\n" \
 1192 "sw $31,48($29)" "\n" \
 1193 "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
 1194 "nop" "\n" \
 1195 "lw $31,48($29)" "\n" \
 1196 "jr $31" "\n" \
 1197 "nop" "\n" \
 1198 ".set reorder" "\n" \
 1199 ".set macro" "\n" \
 1200 ".end " SYMBOL_STRING(cti_##op) "\n" \
 1201 ); \
 1202 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
 1203
 1204#endif
 1205
10371206#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
10381207
10391208#if USE(JSVALUE32_64)
55696

JavaScriptCore/jit/JITStubs.h

@@namespace JSC {
189189 // When JIT code makes a call, it pushes its return address just below the rest of the stack.
190190 ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
191191 };
 192#elif CPU(MIPS)
 193 struct JITStackFrame {
 194 void* reserved; // Unused
 195 JITStubArg args[6];
 196
 197 void* preservedGP; // store GP when using PIC code
 198 void* preservedS0;
 199 void* preservedS1;
 200 void* preservedS2;
 201 void* preservedReturnAddress;
 202
 203 ReturnAddressPtr thunkReturnAddress;
 204
 205 // These arguments passed in a1..a3 (a0 contained the entry code pointed, which is not preserved)
 206 RegisterFile* registerFile;
 207 CallFrame* callFrame;
 208 JSValue* exception;
 209
 210 // These arguments passed on the stack.
 211 Profiler** enabledProfilerReference;
 212 JSGlobalData* globalData;
 213
 214 ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
 215 };
192216#else
193217#error "JITStackFrame not defined for this platform."
194218#endif
55696

JavaScriptCore/wtf/Platform.h

@@on MinGW. See https://bugs.webkit.org/sh
905905 #define ENABLE_JIT 1
906906#elif CPU(ARM_TRADITIONAL) && OS(LINUX)
907907 #define ENABLE_JIT 1
 908#elif CPU(MIPS) && OS(LINUX)
 909 #define ENABLE_JIT 1
 910 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 0
908911#endif
909912#endif /* PLATFORM(QT) */
910913
55696