|
@@ -33,9 +33,8 @@ interface
|
|
|
procedure pass_2;override;
|
|
|
end;
|
|
|
|
|
|
- ti386shlshrnode = class(tshlshrnode)
|
|
|
- procedure pass_2;override;
|
|
|
- { everything will be handled in pass_2 }
|
|
|
+ ti386shlshrnode = class(tcgshlshrnode)
|
|
|
+ procedure second_64bit;override;
|
|
|
function first_shlshr64bitint: tnode; override;
|
|
|
end;
|
|
|
|
|
@@ -165,7 +164,7 @@ implementation
|
|
|
m_high:=m_high shr 1;
|
|
|
dec(l);
|
|
|
end;
|
|
|
- m:=m_high;
|
|
|
+ m:=dword(m_high);
|
|
|
s:=l;
|
|
|
if (m_high shr 31)<>0 then
|
|
|
a:=1
|
|
@@ -223,7 +222,7 @@ implementation
|
|
|
d:=tordconstnode(right).value;
|
|
|
if d>=$80000000 then
|
|
|
begin
|
|
|
- emit_const_reg(A_CMP,S_L,d,hreg1);
|
|
|
+ emit_const_reg(A_CMP,S_L,aint(d),hreg1);
|
|
|
location.register:=cg.getintregister(exprasmlist,OS_INT);
|
|
|
emit_const_reg(A_MOV,S_L,0,location.register);
|
|
|
emit_const_reg(A_SBB,S_L,-1,location.register);
|
|
@@ -359,147 +358,111 @@ implementation
|
|
|
|
|
|
|
|
|
function ti386shlshrnode.first_shlshr64bitint: tnode;
|
|
|
+ begin
|
|
|
+ result := nil;
|
|
|
+ end;
|
|
|
|
|
|
- begin
|
|
|
- result := nil;
|
|
|
- end;
|
|
|
-
|
|
|
- procedure ti386shlshrnode.pass_2;
|
|
|
-
|
|
|
- var hreg64hi,hreg64lo:Tregister;
|
|
|
- op:Tasmop;
|
|
|
+ procedure ti386shlshrnode.second_64bit;
|
|
|
+ var
|
|
|
+ hreg64hi,hreg64lo:Tregister;
|
|
|
v : TConstExprInt;
|
|
|
l1,l2,l3:Tasmlabel;
|
|
|
+ begin
|
|
|
+ location_reset(location,LOC_REGISTER,OS_64);
|
|
|
+
|
|
|
+ { load left operator in a register }
|
|
|
+ location_force_reg(exprasmlist,left.location,OS_64,false);
|
|
|
+ hreg64hi:=left.location.register64.reghi;
|
|
|
+ hreg64lo:=left.location.register64.reglo;
|
|
|
|
|
|
- begin
|
|
|
- secondpass(left);
|
|
|
- secondpass(right);
|
|
|
-
|
|
|
- { determine operator }
|
|
|
- if nodetype=shln then
|
|
|
- op:=A_SHL
|
|
|
- else
|
|
|
- op:=A_SHR;
|
|
|
-
|
|
|
- if is_64bitint(left.resulttype.def) then
|
|
|
- begin
|
|
|
- location_reset(location,LOC_REGISTER,OS_64);
|
|
|
-
|
|
|
- { load left operator in a register }
|
|
|
- location_force_reg(exprasmlist,left.location,OS_64,false);
|
|
|
- hreg64hi:=left.location.register64.reghi;
|
|
|
- hreg64lo:=left.location.register64.reglo;
|
|
|
-
|
|
|
- { shifting by a constant directly coded: }
|
|
|
- if (right.nodetype=ordconstn) then
|
|
|
- begin
|
|
|
- v:=Tordconstnode(right).value and 63;
|
|
|
- if v>31 then
|
|
|
- begin
|
|
|
- if nodetype=shln then
|
|
|
- begin
|
|
|
- emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
|
|
|
- if ((v and 31) <> 0) then
|
|
|
- emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
|
|
|
- if ((v and 31) <> 0) then
|
|
|
- emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
|
|
|
- end;
|
|
|
- location.register64.reghi:=hreg64lo;
|
|
|
- location.register64.reglo:=hreg64hi;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if nodetype=shln then
|
|
|
- begin
|
|
|
- emit_const_reg_reg(A_SHLD,S_L,v and 31,hreg64lo,hreg64hi);
|
|
|
+ { shifting by a constant directly coded: }
|
|
|
+ if (right.nodetype=ordconstn) then
|
|
|
+ begin
|
|
|
+ v:=Tordconstnode(right).value and 63;
|
|
|
+ if v>31 then
|
|
|
+ begin
|
|
|
+ if nodetype=shln then
|
|
|
+ begin
|
|
|
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
|
|
|
+ if ((v and 31) <> 0) then
|
|
|
emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- emit_const_reg_reg(A_SHRD,S_L,v and 31,hreg64hi,hreg64lo);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
|
|
|
+ if ((v and 31) <> 0) then
|
|
|
emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
|
|
|
- end;
|
|
|
- location.register64.reglo:=hreg64lo;
|
|
|
- location.register64.reghi:=hreg64hi;
|
|
|
- end;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- { load right operators in a register }
|
|
|
- cg.getcpuregister(exprasmlist,NR_ECX);
|
|
|
- cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
|
|
|
-
|
|
|
- { left operator is already in a register }
|
|
|
- { hence are both in a register }
|
|
|
- { is it in the case ECX ? }
|
|
|
-
|
|
|
- { the damned shift instructions work only til a count of 32 }
|
|
|
- { so we've to do some tricks here }
|
|
|
- objectlibrary.getjumplabel(l1);
|
|
|
- objectlibrary.getjumplabel(l2);
|
|
|
- objectlibrary.getjumplabel(l3);
|
|
|
- emit_const_reg(A_CMP,S_L,64,NR_ECX);
|
|
|
- cg.a_jmp_flags(exprasmlist,F_L,l1);
|
|
|
- emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
|
|
|
- emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
|
|
|
- cg.a_jmp_always(exprasmlist,l3);
|
|
|
- cg.a_label(exprasmlist,l1);
|
|
|
- emit_const_reg(A_CMP,S_L,32,NR_ECX);
|
|
|
- cg.a_jmp_flags(exprasmlist,F_L,l2);
|
|
|
- emit_const_reg(A_SUB,S_L,32,NR_ECX);
|
|
|
- if nodetype=shln then
|
|
|
- begin
|
|
|
- emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
|
|
|
- emit_reg_reg(A_MOV,S_L,hreg64lo,hreg64hi);
|
|
|
- emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
|
|
|
- cg.a_jmp_always(exprasmlist,l3);
|
|
|
- cg.a_label(exprasmlist,l2);
|
|
|
- emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hreg64lo,hreg64hi);
|
|
|
- emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
|
|
|
- emit_reg_reg(A_MOV,S_L,hreg64hi,hreg64lo);
|
|
|
- emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
|
|
|
- cg.a_jmp_always(exprasmlist,l3);
|
|
|
- cg.a_label(exprasmlist,l2);
|
|
|
- emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hreg64hi,hreg64lo);
|
|
|
- emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
|
|
|
- end;
|
|
|
- cg.a_label(exprasmlist,l3);
|
|
|
-
|
|
|
- cg.ungetcpuregister(exprasmlist,NR_ECX);
|
|
|
- location.register64.reglo:=hreg64lo;
|
|
|
- location.register64.reghi:=hreg64hi;
|
|
|
- end;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- { load left operators in a register }
|
|
|
- location_copy(location,left.location);
|
|
|
- location_force_reg(exprasmlist,location,OS_INT,false);
|
|
|
-
|
|
|
- { shifting by a constant directly coded: }
|
|
|
- if (right.nodetype=ordconstn) then
|
|
|
- { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
|
|
|
- emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
|
|
|
- else
|
|
|
- begin
|
|
|
- { load right operators in a ECX }
|
|
|
- cg.getcpuregister(exprasmlist,NR_ECX);
|
|
|
- cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
|
|
|
-
|
|
|
- { right operand is in ECX }
|
|
|
- cg.ungetcpuregister(exprasmlist,NR_ECX);
|
|
|
- emit_reg_reg(op,S_L,NR_CL,location.register);
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
+ end;
|
|
|
+ location.register64.reghi:=hreg64lo;
|
|
|
+ location.register64.reglo:=hreg64hi;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if nodetype=shln then
|
|
|
+ begin
|
|
|
+ emit_const_reg_reg(A_SHLD,S_L,v and 31,hreg64lo,hreg64hi);
|
|
|
+ emit_const_reg(A_SHL,S_L,v and 31,hreg64lo);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ emit_const_reg_reg(A_SHRD,S_L,v and 31,hreg64hi,hreg64lo);
|
|
|
+ emit_const_reg(A_SHR,S_L,v and 31,hreg64hi);
|
|
|
+ end;
|
|
|
+ location.register64.reglo:=hreg64lo;
|
|
|
+ location.register64.reghi:=hreg64hi;
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ { load right operators in a register }
|
|
|
+ cg.getcpuregister(exprasmlist,NR_ECX);
|
|
|
+ cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
|
|
|
+
|
|
|
+ { left operator is already in a register }
|
|
|
+ { hence are both in a register }
|
|
|
+ { is it in the case ECX ? }
|
|
|
+
|
|
|
+ { the damned shift instructions work only til a count of 32 }
|
|
|
+ { so we've to do some tricks here }
|
|
|
+ objectlibrary.getjumplabel(l1);
|
|
|
+ objectlibrary.getjumplabel(l2);
|
|
|
+ objectlibrary.getjumplabel(l3);
|
|
|
+ emit_const_reg(A_CMP,S_L,64,NR_ECX);
|
|
|
+ cg.a_jmp_flags(exprasmlist,F_L,l1);
|
|
|
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
|
|
|
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
|
|
|
+ cg.a_jmp_always(exprasmlist,l3);
|
|
|
+ cg.a_label(exprasmlist,l1);
|
|
|
+ emit_const_reg(A_CMP,S_L,32,NR_ECX);
|
|
|
+ cg.a_jmp_flags(exprasmlist,F_L,l2);
|
|
|
+ emit_const_reg(A_SUB,S_L,32,NR_ECX);
|
|
|
+ if nodetype=shln then
|
|
|
+ begin
|
|
|
+ emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
|
|
|
+ emit_reg_reg(A_MOV,S_L,hreg64lo,hreg64hi);
|
|
|
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
|
|
|
+ cg.a_jmp_always(exprasmlist,l3);
|
|
|
+ cg.a_label(exprasmlist,l2);
|
|
|
+ emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hreg64lo,hreg64hi);
|
|
|
+ emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
|
|
|
+ emit_reg_reg(A_MOV,S_L,hreg64hi,hreg64lo);
|
|
|
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
|
|
|
+ cg.a_jmp_always(exprasmlist,l3);
|
|
|
+ cg.a_label(exprasmlist,l2);
|
|
|
+ emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hreg64hi,hreg64lo);
|
|
|
+ emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
|
|
|
+ end;
|
|
|
+ cg.a_label(exprasmlist,l3);
|
|
|
+
|
|
|
+ cg.ungetcpuregister(exprasmlist,NR_ECX);
|
|
|
+ location.register64.reglo:=hreg64lo;
|
|
|
+ location.register64.reghi:=hreg64hi;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
|
|
|
|
|
|
begin
|