فهرست منبع

+ Xtensa: a_loadaddr_ref_reg implemented

git-svn-id: trunk@44326 -
florian 5 سال پیش
والد
کامیت
d0106d08b9
1فایلهای تغییر یافته به همراه96 افزوده شده و 3 حذف شده
  1. 96 3
      compiler/xtensa/cgcpu.pas

+ 96 - 3
compiler/xtensa/cgcpu.pas

@@ -36,6 +36,8 @@ interface
 
     type
       tcgcpu=class(tcg)
+      private
+       procedure fixref(list : TAsmList; var ref : treference);
       public
         procedure init_register_allocators;override;
         procedure done_register_allocators;override;
@@ -244,7 +246,6 @@ implementation
 
             current_asmdata.getjumplabel(l);
             cg.a_label(current_procinfo.aktlocaldata,l);
-//            hr.symboldata:=current_procinfo.aktlocaldata.last;
             current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
 
             hr.symbol:=l;
@@ -253,10 +254,102 @@ implementation
       end;
 
 
+    procedure tcgcpu.fixref(list : TAsmList;var ref : treference);
+      var
+        tmpreg, tmpreg2 : tregister;
+        tmpref : treference;
+        l : tasmlabel;
+      begin
+        { absolute symbols can't be handled directly, we've to store the symbol reference
+          in the text segment and access it pc relative
+
+          For now, we assume that references where base or index equals to PC are already
+          relative, all other references are assumed to be absolute and thus they need
+          to be handled extra.
+
+          A proper solution would be to change refoptions to a set and store the information
+          if the symbol is absolute or relative there.
+        }
+        { create consts entry }
+        reference_reset(tmpref,4,[]);
+        current_asmdata.getjumplabel(l);
+        cg.a_label(current_procinfo.aktlocaldata,l);
+        tmpreg:=NR_NO;
+
+        if assigned(ref.symbol) then
+          current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
+        else
+          current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
+
+        { load consts entry }
+        tmpreg:=getintregister(list,OS_INT);
+        tmpref.symbol:=l;
+        list.concat(taicpu.op_reg_ref(A_L32R,tmpreg,tmpref));
+
+        if ref.base<>NR_NO then
+          begin
+            if ref.index<>NR_NO then
+              begin
+                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+                ref.base:=tmpreg;
+              end
+            else
+              ref.base:=tmpreg;
+          end
+        else
+          ref.base:=tmpreg;
+        if ref.index<>NR_NO then
+          begin
+            list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
+            ref.index:=NR_NO;
+          end;
+        ref.offset:=0;
+        ref.symbol:=nil;
+      end;
+
+
     procedure tcgcpu.a_loadaddr_ref_reg(list : TAsmList;
-     const ref : TReference; r : tregister);
+      const ref : TReference; r : tregister);
+       var
+        b : byte;
+        tmpref : treference;
+        instr : taicpu;
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        tmpref:=ref;
+        { Be sure to have a base register }
+        if tmpref.base=NR_NO then
+          begin
+            tmpref.base:=tmpref.index;
+            tmpref.index:=NR_NO;
+          end;
+
+        if assigned(tmpref.symbol) then
+          fixref(list,tmpref);
+
+        { expect a base here if there is an index }
+        if (tmpref.base=NR_NO) and (tmpref.index<>NR_NO) then
+          internalerror(200312022);
+
+        if tmpref.index<>NR_NO then
+          begin
+            a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
+            if tmpref.offset<>0 then
+              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
+          end
+        else
+          begin
+            if tmpref.base=NR_NO then
+              a_load_const_reg(list,OS_ADDR,tmpref.offset,r)
+            else
+              if tmpref.offset<>0 then
+                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
+              else
+                begin
+                  instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
+                  list.concat(instr);
+                  add_move_instruction(instr);
+                end;
+          end;
       end;