mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 12:09:30 +02:00
* TCGMIPS.a_load_reg_reg: reduce code duplication, and don't generate same register move for OS_32->OS_S32 and vice versa. Such moves explode into at least 4 instructions if register needs spilling, after which they are no longer recognized and cannot be removed by reg.allocator. So it's much better not to generate them in first place.
* Implemented overflow checking for multiplication, no longer generate MULO and MULOU macros. git-svn-id: trunk@24894 -
This commit is contained in:
parent
7e0ae2e984
commit
fb88cc4257
@ -668,6 +668,7 @@ end;
|
|||||||
procedure TCGMIPS.a_load_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
|
procedure TCGMIPS.a_load_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
|
||||||
var
|
var
|
||||||
instr: taicpu;
|
instr: taicpu;
|
||||||
|
done: boolean;
|
||||||
begin
|
begin
|
||||||
if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
|
if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
|
||||||
(
|
(
|
||||||
@ -675,6 +676,7 @@ begin
|
|||||||
) or ((fromsize = OS_S8) and
|
) or ((fromsize = OS_S8) and
|
||||||
(tosize = OS_16)) then
|
(tosize = OS_16)) then
|
||||||
begin
|
begin
|
||||||
|
done:=true;
|
||||||
case tosize of
|
case tosize of
|
||||||
OS_8:
|
OS_8:
|
||||||
list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ff));
|
list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ff));
|
||||||
@ -682,13 +684,7 @@ begin
|
|||||||
list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ffff));
|
list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ffff));
|
||||||
OS_32,
|
OS_32,
|
||||||
OS_S32:
|
OS_S32:
|
||||||
begin
|
done:=false;
|
||||||
instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
|
|
||||||
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:
|
OS_S8:
|
||||||
begin
|
begin
|
||||||
list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 24));
|
list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 24));
|
||||||
@ -704,17 +700,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
done:=false;
|
||||||
if reg1 <> reg2 then
|
|
||||||
begin
|
|
||||||
{ same size, only a register mov required }
|
|
||||||
instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
|
|
||||||
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);
|
if (not done) and (reg1 <> reg2) then
|
||||||
end;
|
begin
|
||||||
|
{ same size, only a register mov required }
|
||||||
|
instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
|
||||||
|
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;
|
end;
|
||||||
|
|
||||||
@ -880,7 +875,6 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
ops_mul_ovf: array[boolean] of TAsmOp = (A_MULOU, A_MULO);
|
|
||||||
ops_mul: array[boolean] of TAsmOp = (A_MULTU,A_MULT);
|
ops_mul: array[boolean] of TAsmOp = (A_MULTU,A_MULT);
|
||||||
ops_add: array[boolean] of TAsmOp = (A_ADDU, A_ADD);
|
ops_add: array[boolean] of TAsmOp = (A_ADDU, A_ADD);
|
||||||
ops_sub: array[boolean] of TAsmOp = (A_SUBU, A_SUB);
|
ops_sub: array[boolean] of TAsmOp = (A_SUBU, A_SUB);
|
||||||
@ -1024,7 +1018,8 @@ end;
|
|||||||
procedure TCGMIPS.a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
|
procedure TCGMIPS.a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
|
||||||
var
|
var
|
||||||
signed: boolean;
|
signed: boolean;
|
||||||
hreg: TRegister;
|
hreg,hreg2: TRegister;
|
||||||
|
hl: tasmlabel;
|
||||||
begin
|
begin
|
||||||
ovloc.loc := LOC_VOID;
|
ovloc.loc := LOC_VOID;
|
||||||
signed:=(size in [OS_S8,OS_S16,OS_S32]);
|
signed:=(size in [OS_S8,OS_S16,OS_S32]);
|
||||||
@ -1049,14 +1044,24 @@ begin
|
|||||||
end;
|
end;
|
||||||
OP_MUL,OP_IMUL:
|
OP_MUL,OP_IMUL:
|
||||||
begin
|
begin
|
||||||
|
list.concat(taicpu.op_reg_reg(ops_mul[op=OP_IMUL], src2, src1));
|
||||||
|
list.concat(taicpu.op_reg(A_MFLO, dst));
|
||||||
if setflags then
|
if setflags then
|
||||||
{ TODO: still uses a macro }
|
begin
|
||||||
list.concat(taicpu.op_reg_reg_reg(ops_mul_ovf[op=OP_IMUL], dst, src2, src1))
|
current_asmdata.getjumplabel(hl);
|
||||||
else
|
hreg:=GetIntRegister(list,OS_INT);
|
||||||
begin
|
list.concat(taicpu.op_reg(A_MFHI,hreg));
|
||||||
list.concat(taicpu.op_reg_reg(ops_mul[op=OP_IMUL], src2, src1));
|
if (op=OP_IMUL) then
|
||||||
list.concat(taicpu.op_reg(A_MFLO, dst));
|
begin
|
||||||
end;
|
hreg2:=GetIntRegister(list,OS_INT);
|
||||||
|
list.concat(taicpu.op_reg_reg_const(A_SRA,hreg2,dst,31));
|
||||||
|
a_cmp_reg_reg_label(list,OS_INT,OC_EQ,hreg2,hreg,hl);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
a_cmp_reg_reg_label(list,OS_INT,OC_EQ,hreg,NR_R0,hl);
|
||||||
|
list.concat(taicpu.op_const(A_BREAK,6));
|
||||||
|
a_label(list,hl);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
OP_AND,OP_OR,OP_XOR:
|
OP_AND,OP_OR,OP_XOR:
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user