Commits

Armin Rigo committed 62c521e

Fix the usage of the 'j' mode (in INSN_j) on 64-bit to take as
argument the absolute address, as on 32-bit. Previously, it would
be encoded as the IP-relative address, and feature that no code
in the current backend can take advantage of; so it was carefully
systematically avoided in 64-bit.

Comments (0)

Files changed (4)

pypy/jit/backend/x86/regloc.py

             # These are the worst cases:
             val2 = loc2.value_i()
             code1 = loc1.location_code()
-            if (code1 == 'j'
-                or (code1 == 'm' and not rx86.fits_in_32bits(loc1.value_m()[1]))
-                or (code1 == 'a' and not rx86.fits_in_32bits(loc1.value_a()[3]))):
+            if code1 == 'j':
+                checkvalue = loc1.value_j()
+            elif code1 == 'm':
+                checkvalue = loc1.value_m()[1]
+            elif code1 == 'a':
+                checkvalue = loc1.value_a()[3]
+            else:
+                checkvalue = 0
+            if not rx86.fits_in_32bits(checkvalue):
                 # INSN_ji, and both operands are 64-bit; or INSN_mi or INSN_ai
                 # and the constant offset in the address is 64-bit.
                 # Hopefully this doesn't happen too often
                         if code1 == possible_code1:
                             val1 = getattr(loc1, "value_" + possible_code1)()
                             # More faking out of certain operations for x86_64
-                            if self.WORD == 8 and possible_code1 == 'j':
+                            if possible_code1 == 'j' and not rx86.fits_in_32bits(val1):
                                 val1 = self._addr_as_reg_offset(val1)
                                 invoke(self, "m" + possible_code2, val1, val2)
-                            elif self.WORD == 8 and possible_code2 == 'j':
+                            elif possible_code2 == 'j' and not rx86.fits_in_32bits(val2):
                                 val2 = self._addr_as_reg_offset(val2)
                                 invoke(self, possible_code1 + "m", val1, val2)
                             elif possible_code1 == 'm' and not rx86.fits_in_32bits(val1[1]):

pypy/jit/backend/x86/rx86.py

             rex_mem_reg_plus_scaled_reg_plus_const)
 
 # ____________________________________________________________
+# Emit a mod/rm referencing an immediate address that fits in 32-bit
+# (the immediate address itself must be explicitely encoded as well,
+# with immediate(argnum)).
+
+def encode_abs(mc, _1, _2, orbyte):
+    # expands to either '\x05' on 32-bit, or '\x04\x25' or 64-bit
+    if mc.WORD == 8:
+        mc.writechar(chr(0x04 | orbyte))
+        mc.writechar(chr(0x25))
+    else:
+        mc.writechar(chr(0x05 | orbyte))
+    return 0
+
+abs_ = encode_abs, 0, None, None
+
+# ____________________________________________________________
 # For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes
 
 REX_W = 8
     INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1))
     INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2))
     INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2))
-    INSN_rj = insn(rex_w, chr(base+3), register(1,8), '\x05', immediate(2))
-    INSN_ji8 = insn(rex_w, '\x83', orbyte(base), '\x05', immediate(1),
+    INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_, immediate(2))
+    INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1),
                     immediate(2,'b'))
     INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b'))
     INSN_bi32= insn(rex_w, '\x81', orbyte(base), stack_bp(1), immediate(2))
     CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32)
     CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1))
 
-    CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b'))
-    CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2))
+    CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_,
+                   immediate(1), immediate(2, 'b'))
+    CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_,
+                    immediate(1), immediate(2))
     CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32)
-    CMP_jr = insn(rex_w, '\x39', register(2, 8), '\x05', immediate(1))
+    CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1))
 
     CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
 
     LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True))
     LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2))
     LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2))
-    LEA_rj = insn(rex_w, '\x8D', register(1, 8), '\x05', immediate(2))
+    LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2))
 
     CALL_l = insn('\xE8', relative(1))
     CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3)))
     CDQ = insn(rex_nw, '\x99')
 
     TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b'))
-    TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), '\x05', immediate(1), immediate(2, 'b'))
+    TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b'))
     TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
 
     # x87 instructions
     add_insn('s', stack_sp(modrm_argnum))
     add_insn('m', mem_reg_plus_const(modrm_argnum))
     add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum))
-    add_insn('j', '\x05', immediate(modrm_argnum))
+    add_insn('j', abs_, immediate(modrm_argnum))
 
 # Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a
 # register
     #
     assert insnname_template.count('*') == 1
     add_insn('x', register(2), '\xC0')
-    add_insn('j', '\x05', immediate(2))
+    add_insn('j', abs_, immediate(2))
 
 define_pxmm_insn('PADDQ_x*',     '\xD4')
 define_pxmm_insn('PSUBQ_x*',     '\xFB')

pypy/jit/backend/x86/test/test_rx86.py

     s = CodeBuilder64()
     s.MOV_rm(edx, (edi, -1))
     assert s.getvalue() == '\x48\x8B\x57\xFF'
+
+def test_movsd_xj_64():
+    s = CodeBuilder64()
+    s.MOVSD_xj(xmm2, 0x01234567)
+    assert s.getvalue() == '\xF2\x0F\x10\x14\x25\x67\x45\x23\x01'

pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py

     def should_skip_instruction(self, instrname, argmodes):
         return (
                 super(TestRx86_64, self).should_skip_instruction(instrname, argmodes) or
-                ('j' in argmodes) or
                 # Not testing FSTP on 64-bit for now
                 (instrname == 'FSTP')
         )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.