Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (194353 => 194354)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2015-12-21 23:32:57 UTC (rev 194353)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2015-12-21 23:40:36 UTC (rev 194354)
@@ -821,7 +821,26 @@
m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
}
+ void store16(RegisterID src, Address address)
+ {
+#if CPU(X86)
+ // On 32-bit x86 we can only store from the first 4 registers;
+ // esp..edi are mapped to the 'h' registers!
+ if (src >= 4) {
+ // Pick a temporary register.
+ RegisterID temp = getUnusedRegister(address);
+ // Swap to the temporary register to perform the store.
+ swap(src, temp);
+ m_assembler.movw_rm(temp, address.offset, address.base);
+ swap(src, temp);
+ return;
+ }
+#endif
+ m_assembler.movw_rm(src, address.offset, address.base);
+ }
+
+
// Floating-point operation:
//
// Presently only supports SSE, not x87 floating point.
Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (194353 => 194354)
--- trunk/Source/_javascript_Core/assembler/X86Assembler.h 2015-12-21 23:32:57 UTC (rev 194353)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h 2015-12-21 23:40:36 UTC (rev 194354)
@@ -1550,6 +1550,12 @@
m_formatter.oneByteOp8(OP_MOV_EbGb, src, base, index, scale, offset);
}
+ void movw_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ m_formatter.oneByteOp8(OP_MOV_EvGv, src, base, offset);
+ }
+
void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
{
m_formatter.prefix(PRE_OPERAND_SIZE);
Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (194353 => 194354)
--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2015-12-21 23:32:57 UTC (rev 194353)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2015-12-21 23:40:36 UTC (rev 194354)
@@ -422,6 +422,10 @@
Addr, Tmp
Index, Tmp
+Store16 U:G:16, D:G:16
+ Tmp, Index
+ Tmp, Addr
+
Compare32 U:G:32, U:G:32, U:G:32, ZD:G:32
RelCond, Tmp, Tmp, Tmp
RelCond, Tmp, Imm, Tmp
Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (194353 => 194354)
--- trunk/Source/_javascript_Core/b3/testb3.cpp 2015-12-21 23:32:57 UTC (rev 194353)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp 2015-12-21 23:40:36 UTC (rev 194354)
@@ -4044,6 +4044,84 @@
CHECK(!storage);
}
+void testStore16Arg()
+{
+ { // Direct addressing.
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+
+ root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
+ root->appendNew<ControlValue>(proc, Return, Origin(), value);
+
+ int16_t storage = -1;
+ CHECK(compileAndRun<int64_t>(proc, 42, &storage) == 42);
+ CHECK(storage == 42);
+ }
+
+ { // Indexed addressing.
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* value = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+ Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
+ Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
+
+ Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
+ Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
+
+ root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
+ root->appendNew<ControlValue>(proc, Return, Origin(), value);
+
+ int8_t storage = -1;
+ CHECK(compileAndRun<int64_t>(proc, 42, &storage, 1) == 42);
+ CHECK(storage == 42);
+ }
+}
+
+void testStore16Imm()
+{
+ { // Direct addressing.
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
+ Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+
+ root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
+ root->appendNew<ControlValue>(proc, Return, Origin(), value);
+
+ int16_t storage = -1;
+ CHECK(compileAndRun<int64_t>(proc, &storage) == 42);
+ CHECK(storage == 42);
+ }
+
+ { // Indexed addressing.
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* value = root->appendNew<Const32Value>(proc, Origin(), 42);
+ Value* base = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+ Value* displacement = root->appendNew<Const64Value>(proc, Origin(), -1);
+
+ Value* baseDisplacement = root->appendNew<Value>(proc, Add, Origin(), displacement, base);
+ Value* address = root->appendNew<Value>(proc, Add, Origin(), baseDisplacement, offset);
+
+ root->appendNew<MemoryValue>(proc, Store16, Origin(), value, address);
+ root->appendNew<ControlValue>(proc, Return, Origin(), value);
+
+ int16_t storage = -1;
+ CHECK(compileAndRun<int64_t>(proc, &storage, 1) == 42);
+ CHECK(storage == 42);
+ }
+}
+
void testTrunc(int64_t value)
{
Procedure proc;
@@ -9437,6 +9515,8 @@
RUN(testStore8Arg());
RUN(testStore8Imm());
RUN(testStorePartial8BitRegisterOnX86());
+ RUN(testStore16Arg());
+ RUN(testStore16Imm());
RUN(testTrunc((static_cast<int64_t>(1) << 40) + 42));
RUN(testAdd1(45));
RUN(testAdd1Ptr(51));