summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2>2020-04-26 16:37:53 +0000
committernickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2>2020-04-26 16:37:53 +0000
commit9c6d5bd346ffffffa3c7f169ac96456564855e98 (patch)
treeb684773c93a6c6018fdc97e9024e50697fd01978
parentb2f2ffc1f39fd9d6ca5e2485918542cbfbd81376 (diff)
downloadfpc-9c6d5bd346ffffffa3c7f169ac96456564855e98.tar.gz
+ implemented OP_MUL/OP_IMUL in tcgz80.a_op_reg_reg_internal
git-svn-id: https://svn.freepascal.org/svn/fpc/branches/z80@45105 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--compiler/z80/cgcpu.pas84
1 files changed, 80 insertions, 4 deletions
diff --git a/compiler/z80/cgcpu.pas b/compiler/z80/cgcpu.pas
index cc5f5eaa6a..b76870483e 100644
--- a/compiler/z80/cgcpu.pas
+++ b/compiler/z80/cgcpu.pas
@@ -119,6 +119,7 @@ unit cgcpu;
protected
procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
+ procedure gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean);
procedure maybegetcpuregister(list : tasmlist; reg : tregister);
end;
@@ -848,10 +849,13 @@ unit cgcpu;
OP_MUL,OP_IMUL:
begin
- { special stuff, needs separate handling inside code
- generator }
- list.Concat(tai_comment.Create(strpnew('WARNING! not implemented: a_op_reg_reg_internal OP_MUL/OP_IMUL')));
- {internalerror(2017032604);}
+ tmpreg:=dst;
+ if size in [OS_16,OS_S16] then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,dst,tmpreg);
+ end;
+ gen_multiply(list,op,size,src,tmpreg,dst,false);
end;
OP_DIV,OP_IDIV:
@@ -1260,6 +1264,78 @@ unit cgcpu;
end;
+ procedure tcgz80.gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean);
+ var
+ pd: tprocdef;
+ paraloc1, paraloc2: tcgpara;
+ ai: taicpu;
+ hl, no_overflow: TAsmLabel;
+ name: String;
+ begin
+ if size in [OS_8,OS_S8] then
+ begin
+ if size=OS_8 then
+ name:='fpc_mul_byte'
+ else
+ name:='fpc_mul_shortint';
+
+ if check_overflow then
+ name:=name+'_checkoverflow';
+
+ pd:=search_system_proc(name);
+ paraloc1.init;
+ paraloc2.init;
+ paramanager.getcgtempparaloc(list,pd,1,paraloc1);
+ paramanager.getcgtempparaloc(list,pd,2,paraloc2);
+ a_load_reg_cgpara(list,OS_8,src1,paraloc2);
+ a_load_reg_cgpara(list,OS_8,src2,paraloc1);
+ paramanager.freecgpara(list,paraloc2);
+ paramanager.freecgpara(list,paraloc1);
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ a_call_name(list,upper(name),false);
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ cg.a_reg_alloc(list,NR_L);
+ cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
+ cg.a_reg_dealloc(list,NR_L);
+ paraloc2.done;
+ paraloc1.done;
+ end
+ else if size in [OS_16,OS_S16] then
+ begin
+ if size=OS_16 then
+ name:='fpc_mul_word'
+ else
+ name:='fpc_mul_integer';
+
+ if check_overflow then
+ name:=name+'_checkoverflow';
+
+ pd:=search_system_proc(name);
+ paraloc1.init;
+ paraloc2.init;
+ paramanager.getcgtempparaloc(list,pd,1,paraloc1);
+ paramanager.getcgtempparaloc(list,pd,2,paraloc2);
+ a_load_reg_cgpara(list,OS_16,src1,paraloc2);
+ a_load_reg_cgpara(list,OS_16,src2,paraloc1);
+ paramanager.freecgpara(list,paraloc2);
+ paramanager.freecgpara(list,paraloc1);
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ a_call_name(list,upper(name),false);
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ cg.a_reg_alloc(list,NR_L);
+ cg.a_reg_alloc(list,NR_H);
+ cg.a_load_reg_reg(list,OS_8,OS_8,NR_L,dst);
+ cg.a_reg_dealloc(list,NR_L);
+ cg.a_load_reg_reg(list,OS_8,OS_8,NR_H,GetNextReg(dst));
+ cg.a_reg_dealloc(list,NR_H);
+ paraloc2.done;
+ paraloc1.done;
+ end
+ else
+ internalerror(2011022002);
+ end;
+
+
procedure tcgz80.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
var
mask : qword;