瀏覽代碼

+ support for @page and @pageoffs addressing on AArch64: these are PIC
references that directly take the address of a symbol, rather than
of its GOT entry
o use these addressing modes to access local symbols

git-svn-id: trunk@29932 -

Jonas Maebe 10 年之前
父節點
當前提交
7fc9d775df
共有 5 個文件被更改,包括 115 次插入75 次删除
  1. 5 5
      compiler/aarch64/aasmcpu.pas
  2. 72 63
      compiler/aarch64/agcpugas.pas
  3. 27 7
      compiler/aarch64/cgcpu.pas
  4. 9 0
      compiler/aarch64/racpugas.pas
  5. 2 0
      compiler/cgbase.pas

+ 5 - 5
compiler/aarch64/aasmcpu.pas

@@ -569,7 +569,7 @@ implementation
       begin
         result:=sr_complex;
         if not assigned(ref.symboldata) and
-           not(ref.refaddr in [addr_pic,addr_gotpageoffset,addr_gotpage]) then
+           not(ref.refaddr in [addr_gotpageoffset,addr_gotpage,addr_pageoffset,addr_page]) then
           exit;
         { can't use pre-/post-indexed mode here (makes no sense either) }
         if ref.addressmode<>AM_OFFSET then
@@ -580,9 +580,9 @@ implementation
             not(oppostfix in [PF_NONE,PF_W,PF_SW]) or
             not assigned(ref.symbol)) then
           exit;
-        { if this is a got offset load, we must have a base register and a
+        { if this is a (got) page offset load, we must have a base register and a
           symbol }
-        if (ref.refaddr=addr_gotpageoffset) and
+        if (ref.refaddr in [addr_gotpageoffset,addr_pageoffset]) and
            (not assigned(ref.symbol) or
             (ref.base=NR_NO) or
             (ref.index<>NR_NO) or
@@ -594,7 +594,7 @@ implementation
         { cannot have base or index register (we generate these kind of
           references internally, they should never end up here with an
           extra base or offset) }
-        if (ref.refaddr in [addr_gotpage,addr_pic]) and
+        if (ref.refaddr in [addr_gotpage,addr_page]) and
            (ref.base<>NR_NO) or
            (ref.index<>NR_NO) then
           begin
@@ -647,7 +647,7 @@ implementation
           end;
 
         { any other reference cannot be gotpage/gotpageoffset/pic }
-        if ref.refaddr in [addr_gotpage,addr_gotpageoffset,addr_pic] then
+        if ref.refaddr in [addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset,addr_pic] then
           exit;
 
         { base & index:

+ 72 - 63
compiler/aarch64/agcpugas.pas

@@ -83,76 +83,85 @@ unit agcpugas;
 {****************************************************************************}
 
     function getreferencestring(var ref : treference) : string;
+      const
+        darwin_addrpage2str: array[addr_page..addr_gotpageoffset] of string[11] =
+           ('@PAGE','@PAGEOFF','@GOTPAGE','@GOTPAGEOFF');
       begin
-        case ref.refaddr of
-          addr_gotpage:
-            begin
-              if not assigned(ref.symbol) or
-                 (ref.base<>NR_NO) or
-                 (ref.index<>NR_NO) or
-                 (ref.shiftmode<>SM_None) or
-                 (ref.offset<>0) then
-                internalerror(2014121501);
-              if target_asm.id=as_darwin then
-                result:=ref.symbol.name+'@GOTPAGE'
-              else
-                { todo }
-                internalerror(2014121502);
-            end
-          else
-            begin
-              if ref.base=NR_NO then
-                internalerror(2014121503);
-              result:='['+gas_regname(ref.base);
-              if ref.addressmode=AM_POSTINDEXED then
-                result:=result+']';
-              if ref.index<>NR_NO then
+        if ref.base=NR_NO then
+          begin
+            case ref.refaddr of
+              addr_gotpage,
+              addr_page,
+              addr_gotpageoffset,
+              addr_pageoffset:
                 begin
-                  if (ref.offset<>0) or
-                     assigned(ref.symbol) then
-                    internalerror(2014121504);
-                  result:=result+', '+gas_regname(ref.index);
-                  case ref.shiftmode of
-                    SM_None: ;
-                    SM_LSL,
-                    SM_UXTB, SM_UXTH, SM_UXTW, SM_UXTX,
-                    SM_SXTB, SM_SXTH, SM_SXTW, SM_SXTX:
-                      result:=result+', lsl #'+tostr(ref.shiftimm);
-                    else
-                      internalerror(2014121505);
-                  end;
+                  if not assigned(ref.symbol) or
+                     (ref.base<>NR_NO) or
+                     (ref.index<>NR_NO) or
+                     (ref.shiftmode<>SM_None) or
+                     (ref.offset<>0) then
+                    internalerror(2014121501);
+                  if target_asm.id=as_darwin then
+                    result:=ref.symbol.name+darwin_addrpage2str[ref.refaddr]
+                  else
+                    { todo }
+                    internalerror(2014121502);
                 end
-              else
-                begin
-                  if assigned(ref.symbol) then
-                    begin
-                      case ref.refaddr of
-                        addr_gotpageoffset:
-                          begin
-                            if target_asm.id=as_darwin then
-                              result:=result+', '+ref.symbol.name+'@GOTPAGEOFF'
-                            else
-                              result:=result+', #:lo12:'+ref.symbol.name;
-                          end
-                        else
-                          { todo: not yet generated/don't know syntax }
-                          internalerror(2014121506);
-                      end;
-                    end
+            end
+          end
+        else
+          begin
+            result:='['+gas_regname(ref.base);
+            if ref.addressmode=AM_POSTINDEXED then
+              result:=result+']';
+            if ref.index<>NR_NO then
+              begin
+                if (ref.offset<>0) or
+                   assigned(ref.symbol) then
+                  internalerror(2014121504);
+                result:=result+', '+gas_regname(ref.index);
+                case ref.shiftmode of
+                  SM_None: ;
+                  SM_LSL,
+                  SM_UXTB, SM_UXTH, SM_UXTW, SM_UXTX,
+                  SM_SXTB, SM_SXTH, SM_SXTW, SM_SXTX:
+                    result:=result+', lsl #'+tostr(ref.shiftimm);
                   else
-                    begin
-                      if ref.refaddr<>addr_no then
+                    internalerror(2014121505);
+                end;
+              end
+            else
+              begin
+                if assigned(ref.symbol) then
+                  begin
+                    case ref.refaddr of
+                      addr_gotpageoffset,
+                      addr_pageoffset:
+                        begin
+                          if target_asm.id=as_darwin then
+                            result:=result+', '+ref.symbol.name+darwin_addrpage2str[ref.refaddr]
+                          else
+                            { todo }
+                            internalerror(2014122510);
+                        end
+                      else
+                        { todo: not yet generated/don't know syntax }
                         internalerror(2014121506);
-                      if (ref.offset<>0) then
-                        result:=result+', #'+tostr(ref.offset);
                     end;
-                end;
-              case ref.addressmode of
-                AM_OFFSET:
-                  result:=result+']';
-                AM_PREINDEXED:
-                  result:=result+']!';
+                  end
+                else
+                  begin
+                    if ref.refaddr<>addr_no then
+                      internalerror(2014121506);
+                    if (ref.offset<>0) then
+                      result:=result+', #'+tostr(ref.offset);
+                  end;
               end;
+            case ref.addressmode of
+              AM_OFFSET:
+                result:=result+']';
+              AM_PREINDEXED:
+                result:=result+']!';
             end;
           end;
       end;

+ 27 - 7
compiler/aarch64/cgcpu.pas

@@ -154,7 +154,7 @@ implementation
           begin
             { internal "load symbol" instructions should already be valid }
             if assigned(ref.symboldata) or
-               (ref.refaddr in [addr_pic,addr_gotpage,addr_gotpageoffset]) then
+               (ref.refaddr in [addr_pic,addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset]) then
               internalerror(2014110802);
             { no relative symbol support (needed) yet }
             if assigned(ref.relsymbol) then
@@ -171,17 +171,37 @@ implementation
                    (ref.base=preferred_newbasereg) or
                    (ref.index=preferred_newbasereg) then
                   preferred_newbasereg:=getaddressregister(list);
-                { load the GOT page }
+                { load the (GOT) page }
                 reference_reset_symbol(href,ref.symbol,0,8);
-                href.refaddr:=addr_gotpage;
+                if ((ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) and
+                    (ref.symbol.bind in [AB_LOCAL,AB_GLOBAL])) or
+                   ((ref.symbol.typ=AT_DATA) and
+                    (ref.symbol.bind=AB_LOCAL)) then
+                  href.refaddr:=addr_page
+                else
+                  href.refaddr:=addr_gotpage;
                 list.concat(taicpu.op_reg_ref(A_ADRP,preferred_newbasereg,href));
                 { load the GOT entry (= address of the variable) }
                 reference_reset_base(href,preferred_newbasereg,0,sizeof(pint));
                 href.symbol:=ref.symbol;
-                href.refaddr:=addr_gotpageoffset;
-                { use a_load_ref_reg() rather than directly encoding the LDR,
-                  so that we'll check the validity of the reference }
-                a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,preferred_newbasereg);
+                { code symbols defined in the current compilation unit do not
+                  have to be accessed via the GOT }
+                if ((ref.symbol.typ in [AT_FUNCTION,AT_LABEL]) and
+                    (ref.symbol.bind in [AB_LOCAL,AB_GLOBAL])) or
+                   ((ref.symbol.typ=AT_DATA) and
+                    (ref.symbol.bind=AB_LOCAL)) then
+                  begin
+                    href.base:=NR_NO;
+                    href.refaddr:=addr_pageoffset;
+                    list.concat(taicpu.op_reg_reg_ref(A_ADD,preferred_newbasereg,preferred_newbasereg,href));
+                  end
+                else
+                  begin
+                    href.refaddr:=addr_gotpageoffset;
+                    { use a_load_ref_reg() rather than directly encoding the LDR,
+                      so that we'll check the validity of the reference }
+                    a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,preferred_newbasereg);
+                  end;
                 { set as new base register }
                 if ref.base=NR_NO then
                   ref.base:=preferred_newbasereg

+ 9 - 0
compiler/aarch64/racpugas.pas

@@ -308,6 +308,11 @@ Unit racpugas;
                         consume(actasmtoken);
                         oper.opr.ref.refaddr:=addr_gotpageoffset;
                       end
+                    else if actasmpattern='PAGEOFF' then
+                      begin
+                        consume(actasmtoken);
+                        oper.opr.ref.refaddr:=addr_pageoffset;
+                      end
                     else
                       begin
                         do_error;
@@ -532,6 +537,10 @@ Unit racpugas;
                   oper.opr.ref.refaddr:=addr_gotpage
                 else if actasmpattern='GOTPAGEOFF' then
                   oper.opr.ref.refaddr:=addr_gotpageoffset
+                else if actasmpattern='PAGE' then
+                  oper.opr.ref.refaddr:=addr_page
+                else if actasmpattern='PAGEOFF' then
+                  oper.opr.ref.refaddr:=addr_pageoffset
                 else
                   Message(asmr_e_expr_illegal);
                 consume(actasmtoken);

+ 2 - 0
compiler/cgbase.pas

@@ -102,6 +102,8 @@ interface
          ,addr_seg         // used for getting the segment of an object, e.g. 'mov ax, SEG symbol'
          {$ENDIF}
          {$IFDEF AARCH64}
+         ,addr_page
+         ,addr_pageoffset
          ,addr_gotpage
          ,addr_gotpageoffset
          {$ENDIF AARCH64}