@@ -731,6 +731,54 @@ _emit_load_fast_borrow(unsigned char *code, int reg_variant, int oparg)
731731 code [10 ] = 0x01 ; // imm8 = 1
732732}
733733
734+ #elif defined(_M_IX86 ) || defined(__i386__ )
735+
736+ // i686: movl 8(%esp),%ecx ; movl off(%ecx),%ecx ; orl $1,%ecx ;
737+ // movl %ecx,cache(%esp) (17 bytes, no data)
738+ // i686 does not use preserve_none (unsupported by MSVC).
739+ // Stack layout: 8(%esp)=frame, 20/24/28(%esp)=cache0/1/2
740+ #define LOAD_FAST_BORROW_CODE_SIZE 17
741+
742+ // Stack offsets for cache slots (from %esp)
743+ static const uint8_t _i686_cache_offsets [3 ] = {
744+ 20 , // c0 (r01)
745+ 24 , // c1 (r12)
746+ 28 , // c2 (r23)
747+ };
748+
749+ static void
750+ _emit_load_fast_borrow (unsigned char * code , int reg_variant , int oparg )
751+ {
752+ uint32_t byte_offset = (uint32_t )(offsetof(_PyInterpreterFrame , localsplus )
753+ + (unsigned )oparg * sizeof (_PyStackRef ));
754+ uint8_t cache_off = _i686_cache_offsets [reg_variant ];
755+
756+ // movl 8(%esp), %ecx — load frame
757+ code [0 ] = 0x8B ; // MOV r32, r/m32
758+ code [1 ] = 0x4C ; // ModRM: mod=01, reg=ecx(001), r/m=100(SIB)
759+ code [2 ] = 0x24 ; // SIB: scale=00, index=100(none), base=100(esp)
760+ code [3 ] = 0x08 ; // disp8 = 8
761+
762+ // movl byte_offset(%ecx), %ecx — load localsplus[oparg]
763+ code [4 ] = 0x8B ; // MOV r32, r/m32
764+ code [5 ] = 0x89 ; // ModRM: mod=10(disp32), reg=ecx(001), r/m=001(ecx)
765+ memcpy (code + 6 , & byte_offset , 4 ); // disp32
766+
767+ // orl $1, %ecx — borrow tag
768+ code [10 ] = 0x83 ; // OR r/m32, imm8
769+ code [11 ] = 0xC9 ; // ModRM: mod=11, reg=001(/1), r/m=001(ecx)
770+ code [12 ] = 0x01 ; // imm8 = 1
771+
772+ // movl %ecx, cache_off(%esp) — write to cache slot
773+ code [13 ] = 0x89 ; // MOV r/m32, r32
774+ code [14 ] = 0x4C ; // ModRM: mod=01, reg=ecx(001), r/m=100(SIB)
775+ code [15 ] = 0x24 ; // SIB: scale=00, index=100(none), base=100(esp)
776+ code [16 ] = cache_off ; // disp8
777+
778+ }
779+
780+ #else
781+ # error "unsupported architecture for manual _LOAD_FAST_BORROW emission"
734782#endif
735783
736784// Compiles executor in-place. Don't forget to call _PyJIT_Free later!
0 commit comments