Browse Source

* tcgx86.make_simple_ref: handle references to absolute addresses (these are quite rare on x86_64, but still worth to handle correctly).
* If possible, use reference base instead of index, this yields shorter instructions.
* Added comment about offset limits for rip-relative addressing.
- Removed code related to taking threadvar address on win32, it is incorrect because Windows TLS is not directly accessible via segment registers (fs:0x2c points to array of pointers to TLS storages of each module, so at least double indirection is needed).

git-svn-id: trunk@23342 -

sergei 12 years ago
parent
commit
7530fb3352
1 changed files with 10 additions and 13 deletions
  1. 10 13
      compiler/x86/cgx86.pas

+ 10 - 13
compiler/x86/cgx86.pas

@@ -370,7 +370,13 @@ unit cgx86;
 
 {$ifdef x86_64}
         { Only 32bit is allowed }
-        if ((ref.offset<low(longint)) or (ref.offset>high(longint))) then
+        { Note that this isn't entirely correct: for RIP-relative targets/memory models,
+          it is actually (offset+@symbol-RIP) that should fit into 32 bits. Since two last
+          members aren't known until link time, ABIs place very pessimistic limits
+          on offset values, e.g. SysV AMD64 allows +/-$1000000 (16 megabytes) }
+        if ((ref.offset<low(longint)) or (ref.offset>high(longint))) or
+           { absolute address is not a common thing in x64, but nevertheless a possible one }
+           ((ref.base=NR_NO) and (ref.index=NR_NO) and (ref.symbol=nil)) then
           begin
             { Load constant value to register }
             hreg:=GetAddressRegister(list);
@@ -382,7 +388,9 @@ unit cgx86;
                 ref.symbol:=nil;
               end;}
             { Add register to reference }
-            if ref.index=NR_NO then
+            if ref.base=NR_NO then
+              ref.base:=hreg
+            else if ref.index=NR_NO then
               ref.index:=hreg
             else
               begin
@@ -1004,17 +1012,6 @@ unit cgx86;
                           end
                         else
                           cgmessage(cg_e_cant_use_far_pointer_there);
-                      system_i386_win32:
-                        if segment=NR_FS then
-                          begin
-                            allocallcpuregisters(list);
-                            a_call_name(list,'GetTls',false);
-                            deallocallcpuregisters(list);
-                            list.concat(Taicpu.op_reg_reg(A_ADD,tcgsize2opsize[OS_ADDR],NR_EAX,r));
-                          end
-                        else
-                          cgmessage(cg_e_cant_use_far_pointer_there);
-
                       else
                         cgmessage(cg_e_cant_use_far_pointer_there);
                     end;