2
0
Эх сурвалжийг харах

* Fixed int to int conversion in ARM code generator.
+ Added new test to detect more bugs in int to int conversion.

git-svn-id: trunk@10691 -

yury 17 жил өмнө
parent
commit
95ea5d87dd

+ 1 - 0
.gitattributes

@@ -7038,6 +7038,7 @@ tests/test/cg/tcnvint2.pp svneol=native#text/plain
 tests/test/cg/tcnvint3.pp svneol=native#text/plain
 tests/test/cg/tcnvint4.pp svneol=native#text/plain
 tests/test/cg/tcnvint5.pp svneol=native#text/plain
+tests/test/cg/tcnvint6.pp svneol=native#text/plain
 tests/test/cg/tcnvptr.pp svneol=native#text/plain
 tests/test/cg/tcnvset.pp svneol=native#text/plain
 tests/test/cg/tcnvstr1.pp svneol=native#text/plain

+ 35 - 30
compiler/arm/cgcpu.pas

@@ -970,6 +970,9 @@ unit cgcpu;
            end
          else
            handle_load_store(list,A_LDR,oppostfix,reg,ref);
+
+         if (fromsize=OS_S8) and (tosize = OS_16) then
+           a_load_reg_reg(list,OS_16,OS_32,reg,reg);
        end;
 
 
@@ -1021,7 +1024,6 @@ unit cgcpu;
      procedure tcgarm.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
        var
          so : tshifterop;
-         conv_done: boolean;
 
        procedure do_shift(shiftmode : tshiftmode; shiftimm : byte; reg : tregister);
          begin
@@ -1030,43 +1032,46 @@ unit cgcpu;
            list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg,so));
          end;
 
-       function do_conv(size : tcgsize) : boolean;
-         begin
-           result:=true;
-           case size of
-             OS_8:
-               list.concat(taicpu.op_reg_reg_const(A_AND,reg2,reg1,$ff));
-             OS_S8:
-               begin
-                 do_shift(SM_LSL,24,reg1);
-                 do_shift(SM_ASR,24,reg2);
-               end;
-             OS_16,OS_S16:
-               begin
-                 do_shift(SM_LSL,16,reg1);
-                 if size=OS_S16 then
-                   do_shift(SM_ASR,16,reg2)
-                 else
-                   do_shift(SM_LSR,16,reg2);
-               end;
-             else
-               result:=false;
-           end;
-           conv_done:=result;
-         end;
-
        var
          instr: taicpu;
+         conv_done: boolean;
        begin
+         if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) then
+           internalerror(2002090901);
+
          conv_done:=false;
          if tosize<>fromsize then
            begin
              shifterop_reset(so);
-             if not do_conv(tosize) then
-               if tosize in [OS_32,OS_S32] then
-                 do_conv(fromsize)
+             conv_done:=true;
+             if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
+               fromsize:=tosize;
+             case fromsize of
+               OS_8:
+                 list.concat(taicpu.op_reg_reg_const(A_AND,reg2,reg1,$ff));
+               OS_S8:
+                 begin
+                   do_shift(SM_LSL,24,reg1);
+                   do_shift(SM_ASR,24,reg2);
+                   if tosize=OS_16 then
+                     begin
+                       do_shift(SM_LSL,16,reg1);
+                       do_shift(SM_LSR,16,reg2);
+                     end;
+                 end;
+               OS_16:
+                 begin
+                   do_shift(SM_LSL,16,reg1);
+                   do_shift(SM_LSR,16,reg2);
+                 end;
+               OS_S16:
+                 begin
+                   do_shift(SM_LSL,16,reg1);
+                   do_shift(SM_ASR,16,reg2)
+                 end;
                else
-                 internalerror(2002090901);
+                 conv_done:=false;
+             end;
            end;
          if not conv_done and (reg1<>reg2) then
            begin

+ 87 - 0
tests/test/cg/tcnvint6.pp

@@ -0,0 +1,87 @@
+
+procedure error(n: longint);
+begin
+  writeln('Test failed: ', n);
+  Halt(n);
+end;
+
+var
+  b: byte;
+  w: word;
+  c: cardinal;
+  shi: shortint;
+  si: smallint;
+begin
+  b:=$ff;
+  Inc(b,$ff);
+  if shortint(b)<>-2 then
+    error(1);
+  if smallint(b)<>$fe then
+    error(2);
+  if word(b)<>$fe then
+    error(3);
+  if longint(b)<>$fe then
+    error(4);
+  if cardinal(b)<>$fe then
+    error(5);
+  if int64(b)<>$fe then
+    error(6);
+{$ifdef FPC}
+  if qword(b)<>$fe then
+    error(7);
+{$endif FPC}
+
+  w:=$8000;
+  if shortint(w)<>0 then
+    error(8);
+
+  w:=$ffff;
+  Inc(w,$ffff);
+  if shortint(w)<>-2 then
+    error(11);
+  if byte(w)<>$fe then
+    error(12);
+  if smallint(w)<>-2 then
+    error(13);
+  if longint(w)<>$fffe then
+    error(14);
+  if cardinal(w)<>$fffe then
+    error(15);
+  if int64(w)<>$fffe then
+    error(16);
+{$ifdef FPC}
+  if qword(w)<>$fffe then
+    error(17);
+{$endif FPC}
+
+  c:=$ffffffff;
+  Inc(c,$ffffffff);
+  if int64(c)<>$fffffffe then
+    error(21);
+{$ifdef FPC}
+  if qword(c)<>$fffffffe then
+    error(22);
+{$endif FPC}
+
+  shi:=-1;
+  if word(shi)<>$ffff then
+    error(31);
+  if cardinal(shi)<>$ffffffff then
+    error(32);
+{$ifdef FPC}
+  if qword(shi)<>$ffffffffffffffff then
+    error(33);
+{$endif FPC}
+
+  si:=-1;
+  if word(si)<>$ffff then
+    error(34);
+  if cardinal(si)<>$ffffffff then
+    error(35);
+{$ifdef FPC}
+  if qword(si)<>$ffffffffffffffff then
+    error(36);
+{$endif FPC}
+
+  writeln('Test OK.');
+end.