diff options
author | nickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-04-26 16:37:53 +0000 |
---|---|---|
committer | nickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-04-26 16:37:53 +0000 |
commit | 9c6d5bd346ffffffa3c7f169ac96456564855e98 (patch) | |
tree | b684773c93a6c6018fdc97e9024e50697fd01978 | |
parent | b2f2ffc1f39fd9d6ca5e2485918542cbfbd81376 (diff) | |
download | fpc-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.pas | 84 |
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; |