Browse Source

Merged revisions 7054,7062,7088,7090-7091,7120-7121,7424,7426-7427,7431 via svnmerge from
svn+ssh://[email protected]/FPC/svn/fpc/trunk

........
r7054 | florian | 2007-04-01 21:16:18 +0200 (Sun, 01 Apr 2007) | 2 lines

+ unused so far and untested implementation of a_load_*_unaligned

........
r7062 | florian | 2007-04-05 14:49:12 +0200 (Thu, 05 Apr 2007) | 2 lines

* support for unaligned loads/stores on sparc

........
r7088 | florian | 2007-04-11 21:38:04 +0200 (Wed, 11 Apr 2007) | 2 lines

* fix for tcnvint5 on sparc

........
r7090 | peter | 2007-04-12 09:11:24 +0200 (Thu, 12 Apr 2007) | 3 lines

* patch from mazen to fix zero extending of register moves where the destination
size is larger than the source size

........
r7091 | peter | 2007-04-12 11:58:21 +0200 (Thu, 12 Apr 2007) | 2 lines

* fix shift for 16bit from mazen

........
r7120 | jonas | 2007-04-17 15:35:16 +0200 (Tue, 17 Apr 2007) | 3 lines

* fixed register and operation sizes of a_load_ref_reg_unaligned()
and a_load_reg_ref_unaligned()

........
r7121 | jonas | 2007-04-17 15:35:42 +0200 (Tue, 17 Apr 2007) | 2 lines

* simplified and fixed a_load_reg_reg()

........
r7424 | jonas | 2007-05-23 11:32:48 +0200 (Wed, 23 May 2007) | 3 lines

* shl/shr count on sparc is "mod <bitsize>" -> fix subsetref routines to
take that behaviour into account

........
r7426 | jonas | 2007-05-23 13:45:26 +0200 (Wed, 23 May 2007) | 3 lines

* fixed a_load_reg_ref_unaligned() so it doesn't destroy the source
register anymore

........
r7427 | jonas | 2007-05-23 14:03:42 +0200 (Wed, 23 May 2007) | 3 lines

+ support for unaligned stores
* avoid some unnecessary unaligned load sequences

........
r7431 | jonas | 2007-05-23 16:05:27 +0200 (Wed, 23 May 2007) | 3 lines

* don't destroy source register when performing division of signed
number by constant power of two

........

git-svn-id: branches/fixes_2_2@7450 -

Jonas Maebe 18 years ago
parent
commit
f1459c8cb5
3 changed files with 256 additions and 86 deletions
  1. 145 2
      compiler/cgobj.pas
  2. 109 82
      compiler/sparc/cgcpu.pas
  3. 2 2
      compiler/sparc/ncpumat.pas

+ 145 - 2
compiler/cgobj.pas

@@ -207,9 +207,11 @@ unit cgobj;
           procedure a_load_const_ref(list : TAsmList;size : tcgsize;a : aint;const ref : treference);virtual;
           procedure a_load_const_ref(list : TAsmList;size : tcgsize;a : aint;const ref : treference);virtual;
           procedure a_load_const_loc(list : TAsmList;a : aint;const loc : tlocation);
           procedure a_load_const_loc(list : TAsmList;a : aint;const loc : tlocation);
           procedure a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);virtual; abstract;
           procedure a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);virtual; abstract;
+          procedure a_load_reg_ref_unaligned(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);virtual;
           procedure a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);virtual; abstract;
           procedure a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);virtual; abstract;
           procedure a_load_reg_loc(list : TAsmList;fromsize : tcgsize;reg : tregister;const loc: tlocation);
           procedure a_load_reg_loc(list : TAsmList;fromsize : tcgsize;reg : tregister;const loc: tlocation);
           procedure a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);virtual; abstract;
           procedure a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);virtual; abstract;
+          procedure a_load_ref_reg_unaligned(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);virtual;
           procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);virtual;
           procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);virtual;
           procedure a_load_loc_reg(list : TAsmList;tosize: tcgsize; const loc: tlocation; reg : tregister);
           procedure a_load_loc_reg(list : TAsmList;tosize: tcgsize; const loc: tlocation; reg : tregister);
           procedure a_load_loc_ref(list : TAsmList;tosize: tcgsize; const loc: tlocation; const ref : treference);
           procedure a_load_loc_ref(list : TAsmList;tosize: tcgsize; const loc: tlocation; const ref : treference);
@@ -1150,7 +1152,7 @@ implementation
       begin
       begin
         intloadsize := packedbitsloadsize(sref.bitlen);
         intloadsize := packedbitsloadsize(sref.bitlen);
 
 
-{$if defined(cpurequiresproperalignment) and not defined(arm)}
+{$if defined(cpurequiresproperalignment) and not defined(arm) and not(defined(sparc))}
         { may need to be split into several smaller loads/stores }
         { may need to be split into several smaller loads/stores }
         if intloadsize <> sref.ref.alignment then
         if intloadsize <> sref.ref.alignment then
            internalerror(2006082011);
            internalerror(2006082011);
@@ -1255,6 +1257,19 @@ implementation
             { < loadsize-sref.bitlen, and therefore tmpreg will now be >= loadsize }
             { < loadsize-sref.bitlen, and therefore tmpreg will now be >= loadsize }
             { => extra_value_reg is now 0                                          }
             { => extra_value_reg is now 0                                          }
 
 
+{$ifdef sparc}
+            { except on sparc, where "shr X" = "shr (X and (bitsize-1))" }
+            if (loadbitsize = AIntBits) then
+              begin
+                { if (tmpreg >= cpu_bit_size) then tmpreg := 1 else tmpreg := 0 }
+                a_op_const_reg(list,OP_SHR,OS_INT,{$ifdef cpu64bit}6{$else}5{$endif},tmpreg);
+                { if (tmpreg = cpu_bit_size) then tmpreg := 0 else tmpreg := -1 }
+                a_op_const_reg(list,OP_SUB,OS_INT,1,tmpreg);
+                { if (tmpreg = cpu_bit_size) then extra_value_reg := 0 }
+                a_op_reg_reg(list,OP_AND,OS_INT,tmpreg,extra_value_reg);
+              end;
+{$endif sparc}
+
             { merge }
             { merge }
             a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
             a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
             { no need to mask, necessary masking happened earlier on }
             { no need to mask, necessary masking happened earlier on }
@@ -1631,6 +1646,20 @@ implementation
                         a_op_reg_reg(list,OP_NEG,OS_INT,tmpindexreg,tmpindexreg);
                         a_op_reg_reg(list,OP_NEG,OS_INT,tmpindexreg,tmpindexreg);
                         a_load_const_reg(list,OS_INT,aint((aword(1) shl sref.bitlen)-1),maskreg);
                         a_load_const_reg(list,OS_INT,aint((aword(1) shl sref.bitlen)-1),maskreg);
                         a_op_reg_reg(list,OP_SHL,OS_INT,tmpindexreg,maskreg);
                         a_op_reg_reg(list,OP_SHL,OS_INT,tmpindexreg,maskreg);
+{$ifdef sparc}
+                        {  on sparc, "shr X" = "shr (X and (bitsize-1))" -> fix so shr (x>32) = 0 }
+                        if (loadbitsize = AIntBits) then
+                          begin
+                            { if (tmpindexreg >= cpu_bit_size) then tmpreg := 1 else tmpreg := 0 }
+                            a_op_const_reg_reg(list,OP_SHR,OS_INT,{$ifdef cpu64bit}6{$else}5{$endif},tmpindexreg,valuereg);
+                            { if (tmpindexreg = cpu_bit_size) then maskreg := 0 else maskreg := -1 }
+                            a_op_const_reg(list,OP_SUB,OS_INT,1,valuereg);
+                            { if (tmpindexreg = cpu_bit_size) then maskreg := 0 }
+                            if (slopt <> SL_SETZERO) then
+                              a_op_reg_reg(list,OP_AND,OS_INT,valuereg,tmpreg);
+                            a_op_reg_reg(list,OP_AND,OS_INT,valuereg,maskreg);
+                          end;
+{$endif sparc}
                       end
                       end
                     else
                     else
                       begin
                       begin
@@ -1717,7 +1746,7 @@ implementation
         { perform masking of the source value in advance }
         { perform masking of the source value in advance }
         slopt := SL_REGNOSRCMASK;
         slopt := SL_REGNOSRCMASK;
         if (sref.bitlen <> AIntBits) then
         if (sref.bitlen <> AIntBits) then
-          aword(a) := aword(a) and ((aword(1) shl sref.bitlen) -1); 
+          aword(a) := aword(a) and ((aword(1) shl sref.bitlen) -1);
         if (
         if (
             { broken x86 "x shl regbitsize = x" }
             { broken x86 "x shl regbitsize = x" }
             ((sref.bitlen <> AIntBits) and
             ((sref.bitlen <> AIntBits) and
@@ -1782,6 +1811,120 @@ implementation
 {$undef overflowon}
 {$undef overflowon}
 {$endif}
 {$endif}
 
 
+    procedure tcg.a_load_reg_ref_unaligned(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
+      var
+        tmpref : treference;
+        tmpreg : tregister;
+        i : longint;
+      begin
+        if ref.alignment<>0 then
+          begin
+            tmpref:=ref;
+            { we take care of the alignment now }
+            tmpref.alignment:=0;
+            case FromSize of
+              OS_16,OS_S16:
+                begin
+                  tmpreg:=getintregister(list,OS_16);
+                  a_load_reg_reg(list,fromsize,OS_16,register,tmpreg);
+                  if target_info.endian=endian_big then
+                    inc(tmpref.offset);
+                  tmpreg:=makeregsize(list,tmpreg,OS_8);
+                  a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+                  tmpreg:=makeregsize(list,tmpreg,OS_16);
+                  a_op_const_reg(list,OP_SHR,OS_16,8,tmpreg);
+                  if target_info.endian=endian_big then
+                    dec(tmpref.offset)
+                  else
+                    inc(tmpref.offset);
+                  tmpreg:=makeregsize(list,tmpreg,OS_8);
+                  a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+                end;
+              OS_32,OS_S32:
+                begin
+                  tmpreg:=getintregister(list,OS_32);
+                  a_load_reg_reg(list,fromsize,OS_32,register,tmpreg);
+                  if target_info.endian=endian_big then
+                    inc(tmpref.offset,3);
+                  tmpreg:=makeregsize(list,tmpreg,OS_8);
+                  a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+                  tmpreg:=makeregsize(list,tmpreg,OS_32);
+                  for i:=1 to 3 do
+                    begin
+                      a_op_const_reg(list,OP_SHR,OS_32,8,tmpreg);
+                      if target_info.endian=endian_big then
+                        dec(tmpref.offset)
+                      else
+                        inc(tmpref.offset);
+                      tmpreg:=makeregsize(list,tmpreg,OS_8);
+                      a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+                      tmpreg:=makeregsize(list,tmpreg,OS_32);
+                    end;
+                end
+              else
+                a_load_reg_ref(list,fromsize,tosize,register,tmpref);
+            end;
+          end
+        else
+          a_load_reg_ref(list,fromsize,tosize,register,ref);
+      end;
+
+
+    procedure tcg.a_load_ref_reg_unaligned(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
+      var
+        tmpref : treference;
+        tmpreg : tregister;
+        i : longint;
+      begin
+        if ref.alignment<>0 then
+          begin
+            tmpref:=ref;
+            { we take care of the alignment now }
+            tmpref.alignment:=0;
+            case FromSize of
+              OS_16,OS_S16:
+                begin
+                  if target_info.endian=endian_little then
+                    inc(tmpref.offset);
+                  register:=makeregsize(list,register,OS_8);
+                  a_load_ref_reg(list,OS_8,OS_8,tmpref,register);
+                  register:=makeregsize(list,register,OS_16);
+                  a_op_const_reg(list,OP_SHL,OS_16,8,register);
+                  if target_info.endian=endian_little then
+                    dec(tmpref.offset)
+                  else
+                    inc(tmpref.offset);
+                  tmpreg:=getintregister(list,OS_16);
+                  a_load_ref_reg(list,OS_8,OS_16,tmpref,tmpreg);
+                  a_op_reg_reg(list,OP_OR,OS_16,tmpreg,register);
+                end;
+              OS_32,OS_S32:
+                begin
+                  if target_info.endian=endian_little then
+                    inc(tmpref.offset,3);
+                  register:=makeregsize(list,register,OS_8);
+                  a_load_ref_reg(list,OS_8,OS_8,tmpref,register);
+                  register:=makeregsize(list,register,OS_32);
+                  for i:=1 to 3 do
+                    begin
+                      a_op_const_reg(list,OP_SHL,OS_32,8,register);
+                      if target_info.endian=endian_little then
+                        dec(tmpref.offset)
+                      else
+                        inc(tmpref.offset);
+                      tmpreg:=getintregister(list,OS_32);
+                      a_load_ref_reg(list,OS_8,OS_32,tmpref,tmpreg);
+                      a_op_reg_reg(list,OP_OR,OS_32,tmpreg,register);
+                    end;
+                end
+              else
+                a_load_ref_reg(list,fromsize,tosize,tmpref,register);
+            end;
+          end
+        else
+          a_load_ref_reg(list,fromsize,tosize,ref,register);
+      end;
+
 
 
     procedure tcg.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
     procedure tcg.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
       var
       var

+ 109 - 82
compiler/sparc/cgcpu.pas

@@ -54,6 +54,7 @@ interface
         procedure a_call_name(list:TAsmList;const s:string);override;
         procedure a_call_name(list:TAsmList;const s:string);override;
         procedure a_call_reg(list:TAsmList;Reg:TRegister);override;
         procedure a_call_reg(list:TAsmList;Reg:TRegister);override;
         { General purpose instructions }
         { General purpose instructions }
+        procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
         procedure a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:aint;reg:TRegister);override;
         procedure a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:aint;reg:TRegister);override;
         procedure a_op_reg_reg(list:TAsmList;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
         procedure a_op_reg_reg(list:TAsmList;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
         procedure a_op_const_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;a:aint;src, dst:tregister);override;
         procedure a_op_const_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;a:aint;src, dst:tregister);override;
@@ -481,21 +482,29 @@ implementation
       begin
       begin
         if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
         if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
           fromsize := tosize;
           fromsize := tosize;
-        case fromsize of
-          { signed integer registers }
-          OS_8,
-          OS_S8:
-            Op:=A_STB;
-          OS_16,
-          OS_S16:
-            Op:=A_STH;
-          OS_32,
-          OS_S32:
-            Op:=A_ST;
-          else
-            InternalError(2002122100);
-        end;
-        handle_load_store(list,true,op,reg,ref);
+        if (ref.alignment<>0) and
+           (ref.alignment<tcgsize2size[tosize]) then
+          begin
+            a_load_reg_ref_unaligned(list,FromSize,ToSize,reg,ref);
+          end
+        else
+          begin
+            case fromsize of
+              { signed integer registers }
+              OS_8,
+              OS_S8:
+                Op:=A_STB;
+              OS_16,
+              OS_S16:
+                Op:=A_STH;
+              OS_32,
+              OS_S32:
+                Op:=A_ST;
+              else
+                InternalError(2002122100);
+            end;
+            handle_load_store(list,true,op,reg,ref);
+          end;
       end;
       end;
 
 
 
 
@@ -505,25 +514,33 @@ implementation
       begin
       begin
         if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
         if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
           fromsize := tosize;
           fromsize := tosize;
-        case fromsize of
-          OS_S8:
-            Op:=A_LDSB;{Load Signed Byte}
-          OS_8:
-            Op:=A_LDUB;{Load Unsigned Byte}
-          OS_S16:
-            Op:=A_LDSH;{Load Signed Halfword}
-          OS_16:
-            Op:=A_LDUH;{Load Unsigned Halfword}
-          OS_S32,
-          OS_32:
-            Op:=A_LD;{Load Word}
-          OS_S64,
-          OS_64:
-            Op:=A_LDD;{Load a Long Word}
-          else
-            InternalError(2002122101);
-        end;
-        handle_load_store(list,false,op,reg,ref);
+        if (ref.alignment<>0) and
+           (ref.alignment<tcgsize2size[fromsize]) then
+           begin
+             a_load_ref_reg_unaligned(list,FromSize,ToSize,ref,reg);
+           end
+         else
+           begin
+             case fromsize of
+               OS_S8:
+                 Op:=A_LDSB;{Load Signed Byte}
+               OS_8:
+                 Op:=A_LDUB;{Load Unsigned Byte}
+               OS_S16:
+                 Op:=A_LDSH;{Load Signed Halfword}
+               OS_16:
+                 Op:=A_LDUH;{Load Unsigned Halfword}
+               OS_S32,
+               OS_32:
+                 Op:=A_LD;{Load Word}
+               OS_S64,
+               OS_64:
+                 Op:=A_LDD;{Load a Long Word}
+               else
+                 InternalError(2002122101);
+             end;
+             handle_load_store(list,false,op,reg,ref);
+           end;
       end;
       end;
 
 
 
 
@@ -531,53 +548,47 @@ implementation
       var
       var
         instr : taicpu;
         instr : taicpu;
       begin
       begin
-        if (tcgsize2size[tosize]<tcgsize2size[fromsize]) or
-           (
-            (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
-            (tosize <> fromsize) and
-            not(fromsize in [OS_32,OS_S32])
-           ) then
-          begin
-            case tosize of
-              OS_8 :
-                a_op_const_reg_reg(list,OP_AND,tosize,$ff,reg1,reg2);
-              OS_16 :
-                a_op_const_reg_reg(list,OP_AND,tosize,$ffff,reg1,reg2);
-              OS_32,
-              OS_S32 :
-                begin
-                  instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
-                  list.Concat(instr);
-                  { Notify the register allocator that we have written a move instruction so
-                   it can try to eliminate it. }
-                  add_move_instruction(instr);
-                end;
-              OS_S8 :
-                begin
-                  list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,24,reg2));
-                  list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,24,reg2));
-                end;
-              OS_S16 :
-                begin
-                  list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
-                  list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,16,reg2));
-                end;
-              else
-                internalerror(2002090901);
-            end;
-          end
-        else
-          begin
-            if reg1<>reg2 then
-              begin
-                { same size, only a register mov required }
-                instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
-                list.Concat(instr);
-                { Notify the register allocator that we have written a move instruction so
+         if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
+            ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
+             (fromsize <> tosize)) or
+            { needs to mask out the sign in the top 16 bits }
+            ((fromsize = OS_S8) and
+             (tosize = OS_16)) then
+           case tosize of
+             OS_8 :
+               a_op_const_reg_reg(list,OP_AND,tosize,$ff,reg1,reg2);
+             OS_16 :
+               a_op_const_reg_reg(list,OP_AND,tosize,$ffff,reg1,reg2);
+             OS_32,
+             OS_S32 :
+               begin
+                 instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
+                 list.Concat(instr);
+                 { Notify the register allocator that we have written a move instruction so
                   it can try to eliminate it. }
                   it can try to eliminate it. }
-                add_move_instruction(instr);
-              end;
-          end;
+                 add_move_instruction(instr);
+               end;
+             OS_S8 :
+               begin
+                 list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,24,reg2));
+                 list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,24,reg2));
+               end;
+             OS_S16 :
+               begin
+                 list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
+                 list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,16,reg2));
+               end;
+             else
+               internalerror(2002090901);
+           end
+         else
+           begin
+             instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
+             list.Concat(instr);
+             { Notify the register allocator that we have written a move instruction so
+              it can try to eliminate it. }
+             add_move_instruction(instr);
+           end;
       end;
       end;
 
 
 
 
@@ -732,6 +743,16 @@ implementation
        end;
        end;
 
 
 
 
+    procedure tcgsparc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+      const
+        overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+      begin
+        if (op in overflowops) and
+           (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+          a_load_reg_reg(list,OS_32,size,dst,dst);
+      end;
+
+
     procedure TCgSparc.a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:aint;reg:TRegister);
     procedure TCgSparc.a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:aint;reg:TRegister);
       begin
       begin
         if Op in [OP_NEG,OP_NOT] then
         if Op in [OP_NEG,OP_NOT] then
@@ -740,6 +761,7 @@ implementation
           list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],reg,NR_G0,reg))
           list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],reg,NR_G0,reg))
         else
         else
           handle_reg_const_reg(list,TOpCG2AsmOp[op],reg,a,reg);
           handle_reg_const_reg(list,TOpCG2AsmOp[op],reg,a,reg);
+        maybeadjustresult(list,op,size,reg);
       end;
       end;
 
 
 
 
@@ -765,6 +787,7 @@ implementation
           else
           else
             list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
             list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
         end;
         end;
+        maybeadjustresult(list,op,size,dst);
       end;
       end;
 
 
 
 
@@ -794,12 +817,14 @@ implementation
             end;
             end;
         end;
         end;
         handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
         handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
+        maybeadjustresult(list,op,size,dst);
       end;
       end;
 
 
 
 
     procedure TCgSparc.a_op_reg_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);
     procedure TCgSparc.a_op_reg_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);
       begin
       begin
         list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
         list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
+        maybeadjustresult(list,op,size,dst);
       end;
       end;
 
 
 
 
@@ -845,7 +870,8 @@ implementation
             end;
             end;
           end
           end
         else
         else
-          handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst)
+          handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
+        maybeadjustresult(list,op,size,dst);
       end;
       end;
 
 
 
 
@@ -879,7 +905,8 @@ implementation
             end;
             end;
           end
           end
         else
         else
-          list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst))
+          list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
+        maybeadjustresult(list,op,size,dst);
       end;
       end;
 
 
 
 

+ 2 - 2
compiler/sparc/ncpumat.pas

@@ -107,8 +107,8 @@ implementation
                  { if signed, tmpreg=right value-1, otherwise 0 }
                  { if signed, tmpreg=right value-1, otherwise 0 }
                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,tordconstnode(right).value-1,tmpreg);
                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,tordconstnode(right).value-1,tmpreg);
                  { add to the left value }
                  { add to the left value }
-                 cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,tmpreg,numerator);
-                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,aword(power),numerator,resultreg);
+                 cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,numerator,tmpreg);
+                 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,aword(power),tmpreg,resultreg);
                end
                end
              else
              else
                cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,aword(power),numerator,resultreg);
                cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,aword(power),numerator,resultreg);