浏览代码

* fixed support for access from inline asm to absolute vars, pointing to an
array element (previously, it would always point to the start of the array)

git-svn-id: trunk@37558 -

nickysn 7 年之前
父节点
当前提交
24d447716e
共有 3 个文件被更改,包括 91 次插入5 次删除
  1. 1 0
      .gitattributes
  2. 46 5
      compiler/rautils.pas
  3. 44 0
      tests/test/cpu16/i8086/tasmabs3.pp

+ 1 - 0
.gitattributes

@@ -12129,6 +12129,7 @@ tests/test/cpu16/i8086/tasm16_32_3.pp svneol=native#text/pascal
 tests/test/cpu16/i8086/tasm16_32_4.pp svneol=native#text/pascal
 tests/test/cpu16/i8086/tasmabs1.pp svneol=native#text/pascal
 tests/test/cpu16/i8086/tasmabs2.pp svneol=native#text/pascal
+tests/test/cpu16/i8086/tasmabs3.pp svneol=native#text/pascal
 tests/test/cpu16/i8086/tasmseg1.pp svneol=native#text/pascal
 tests/test/cpu16/i8086/tfarcal1.pp svneol=native#text/pascal
 tests/test/cpu16/i8086/tfarcal2.pp svneol=native#text/pascal

+ 46 - 5
compiler/rautils.pas

@@ -28,7 +28,7 @@ Interface
 Uses
   cutils,cclasses,
   globtype,aasmbase,aasmtai,aasmdata,cpubase,cpuinfo,cgbase,cgutils,
-  symconst,symbase,symtype,symdef,symsym,symcpu;
+  symconst,symbase,symtype,symdef,symsym,constexp,symcpu;
 
 Const
   RPNMax = 10;             { I think you only need 4, but just to be safe }
@@ -812,6 +812,10 @@ var
   indexreg : tregister;
   plist : ppropaccesslistitem;
   size_set_from_absolute : boolean = false;
+  { offset fixup (in bytes), coming from an absolute declaration with an index
+    (e.g. var tralala: word absolute moo[5]; ) }
+  absoffset: asizeint=0;
+  harrdef: tarraydef;
 Begin
   SetupVar:=false;
   asmsearchsym(s,sym,srsymtable);
@@ -830,6 +834,40 @@ Begin
                 setvarsize(tabstractvarsym(sym));
                 size_set_from_absolute:=true;
                 sym:=plist^.sym;
+                { resolve the chain of array indexes (if there are any) }
+                harrdef:=nil;
+                while assigned(plist^.next) do
+                  begin
+                    plist:=plist^.next;
+                    if (plist^.sltype=sl_vec) and (tabstractvarsym(sym).vardef.typ=arraydef) then
+                      begin
+                        if harrdef=nil then
+                          harrdef:=tarraydef(tabstractvarsym(sym).vardef)
+                        else if harrdef.elementdef.typ=arraydef then
+                          harrdef:=tarraydef(harrdef.elementdef)
+                        else
+                          begin
+                            Message(asmr_e_unsupported_symbol_type);
+                            exit;
+                          end;
+                        if is_special_array(harrdef) then
+                          begin
+                            Message(asmr_e_unsupported_symbol_type);
+                            exit;
+                          end;
+                        if not is_packed_array(harrdef) then
+                          Inc(absoffset,asizeint(Int64(plist^.value-harrdef.lowrange))*harrdef.elesize)
+                        else if (Int64(plist^.value-harrdef.lowrange)*harrdef.elepackedbitsize mod 8)=0 then
+                          Inc(absoffset,asizeint(Int64(plist^.value-harrdef.lowrange)*harrdef.elepackedbitsize div 8))
+                        else
+                          Message(asmr_e_packed_element);
+                      end
+                    else
+                      begin
+                        Message(asmr_e_unsupported_symbol_type);
+                        exit;
+                      end;
+                  end;
               end
             else
               begin
@@ -858,9 +896,9 @@ Begin
     fieldvarsym :
       begin
         if not tabstractrecordsymtable(sym.owner).is_packed then
-          setconst(tfieldvarsym(sym).fieldoffset)
+          setconst(absoffset+tfieldvarsym(sym).fieldoffset)
         else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
-          setconst(tfieldvarsym(sym).fieldoffset div 8)
+          setconst(absoffset+tfieldvarsym(sym).fieldoffset div 8)
         else
           Message(asmr_e_packed_element);
         if not size_set_from_absolute then
@@ -885,6 +923,7 @@ Begin
             begin
               initref;
               opr.ref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(sym).mangledname,AT_DATA);
+              Inc(opr.ref.offset,absoffset);
             end;
           paravarsym,
           localvarsym :
@@ -911,7 +950,7 @@ Begin
                  symtable_has_localvarsyms(current_procinfo.procdef.localst) then
                 message1(asmr_e_local_para_unreachable,s);
               opr.localsym:=tabstractnormalvarsym(sym);
-              opr.localsymofs:=0;
+              opr.localsymofs:=absoffset;
               opr.localindexreg:=indexreg;
               opr.localscale:=0;
               opr.localgetoffset:=GetOffset;
@@ -951,6 +990,7 @@ Begin
           OPR_REFERENCE:
             begin
               opr.ref.symbol:=current_asmdata.RefAsmSymbol(tprocdef(tprocsym(sym).ProcdefList[0]).mangledname,AT_FUNCTION);
+              Inc(opr.ref.offset,absoffset);
 {$ifdef i8086}
               opr.ref_farproc_entry:=is_proc_far(tprocdef(tprocsym(sym).ProcdefList[0]))
                         and not (po_interrupt in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions);
@@ -964,7 +1004,7 @@ Begin
               opr.sym_farproc_entry:=is_proc_far(tprocdef(tprocsym(sym).ProcdefList[0]))
                         and not (po_interrupt in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions);
 {$endif i8086}
-              opr.symofs:=0;
+              opr.symofs:=absoffset;
             end;
         else
           Message(asmr_e_invalid_operand_type);
@@ -981,6 +1021,7 @@ Begin
           OPR_REFERENCE:
             begin
               opr.ref.symbol:=current_asmdata.RefAsmSymbol(tlabelsym(sym).mangledname,AT_FUNCTION);
+              Inc(opr.ref.offset,absoffset);
               if opr.ref.segment=NR_NO then
                 opr.ref.segment:=NR_CS;
             end;

+ 44 - 0
tests/test/cpu16/i8086/tasmabs3.pp

@@ -0,0 +1,44 @@
+program tasmabs3;
+
+{ NOT TP7 compatible (TP7 doesn't support absolute with an index) }
+
+{$ASMMODE INTEL}
+{$ASMCPU 80386}
+
+var
+  barr: array [-7..100] of byte;
+  l: longint absolute barr[17];
+  w: word absolute barr[53];
+  b: byte absolute barr[62];
+begin
+  FillChar(barr, SizeOf(barr), $ff);
+  asm
+    mov l, 4
+  end;
+  if (barr[17+0] <> 4) or (barr[17+1] <> 0) or (barr[17+2] <> 0) or
+     (barr[17+3] <> 0) or (barr[17+4] <> 255) or (barr[17-1] <> 255) then
+  begin
+    Writeln('Error!');
+    Halt(1);
+  end;
+  FillChar(barr, SizeOf(barr), $ff);
+  asm
+    mov w, 2
+  end;
+  if (barr[53] <> 2) or (barr[54] <> 0) or (barr[55] <> 255) or
+     (barr[52] <> 255) then
+  begin
+    Writeln('Error!');
+    Halt(1);
+  end;
+  FillChar(barr, SizeOf(barr), $ff);
+  asm
+    mov b, 1
+  end;
+  if (barr[62] <> 1) or (barr[63] <> 255) or (barr[61] <> 255) then
+  begin
+    Writeln('Error!');
+    Halt(1);
+  end;
+  Writeln('Ok!');
+end.