From a9d9a15e208b3fbeb06fd70c0e81ca536c893303 Mon Sep 17 00:00:00 2001 From: florian <florian@freepascal.org> Date: Sun, 2 Nov 2003 14:30:03 +0000 Subject: [PATCH] * fixed ARM for new reg. allocation scheme --- compiler/arm/aasmcpu.pas | 28 ++-- compiler/arm/agarmgas.pas | 10 +- compiler/arm/cgcpu.pas | 243 +++++++++++++++++++++++--------- compiler/arm/cpubase.pas | 46 ++----- compiler/arm/cpupara.pas | 282 ++++++++++++++++++++------------------ compiler/arm/cpupi.pas | 15 +- compiler/arm/itarmgas.pas | 7 +- compiler/arm/narmadd.pas | 11 +- compiler/arm/narmcal.pas | 11 +- compiler/arm/narmcnv.pas | 9 +- compiler/arm/narminl.pas | 9 +- compiler/arm/narmmat.pas | 7 +- compiler/arm/radirect.pas | 21 ++- compiler/arm/rgcpu.pas | 7 +- 14 files changed, 421 insertions(+), 285 deletions(-) diff --git a/compiler/arm/aasmcpu.pas b/compiler/arm/aasmcpu.pas index af4ee1911c..2626159cad 100644 --- a/compiler/arm/aasmcpu.pas +++ b/compiler/arm/aasmcpu.pas @@ -29,7 +29,7 @@ interface uses cclasses,aasmtai, aasmbase,globals,verbose, - cpubase,cpuinfo,cginfo; + cpubase,cpuinfo,cgbase; const { "mov reg,reg" source operand number } @@ -42,7 +42,7 @@ uses oppostfix : TOpPostfix; roundingmode : troundingmode; procedure loadshifterop(opidx:longint;const so:tshifterop); - procedure loadregset(opidx:longint;const s:tsuperregisterset); + procedure loadregset(opidx:longint;const s:tcpuregisterset); constructor op_none(op : tasmop); constructor op_reg(op : tasmop;_op1 : tregister); @@ -52,7 +52,7 @@ uses constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference); constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint); - constructor op_ref_regset(op:tasmop; _op1: treference; _op2: tsuperregisterset); + constructor op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset); constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister); constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: Longint); @@ -98,9 +98,8 @@ implementation procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop); begin - if opidx>=ops then - ops:=opidx+1; - with oper[opidx] do + allocate_oper(opidx+1); + with oper[opidx]^ do begin if typ<>top_shifterop then begin @@ -113,15 +112,15 @@ implementation end; - procedure taicpu.loadregset(opidx:longint;const s:tsuperregisterset); + procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset); begin - if opidx>=ops then - ops:=opidx+1; - with oper[opidx] do + allocate_oper(opidx+1); + with oper[opidx]^ do begin if typ<>top_regset then clearop(opidx); - regset:=s; + new(regset); + regset^:=s; typ:=top_regset; end; end; @@ -171,7 +170,7 @@ implementation end; - constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; _op2: tsuperregisterset); + constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset); begin inherited create(op); ops:=2; @@ -366,7 +365,10 @@ implementation end. { $Log$ - Revision 1.12 2003-09-11 11:54:59 florian + Revision 1.13 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.12 2003/09/11 11:54:59 florian * improved arm code generation * move some protected and private field around * the temp. register for register parameters/arguments are now released diff --git a/compiler/arm/agarmgas.pas b/compiler/arm/agarmgas.pas index a7b2626a6d..bc048f9839 100644 --- a/compiler/arm/agarmgas.pas +++ b/compiler/arm/agarmgas.pas @@ -32,8 +32,7 @@ unit agarmgas; uses aasmtai, aggas, - cpubase, - cginfo; + cpubase; type PARMGNUAssembler=^TARMGNUAssembler; @@ -161,7 +160,7 @@ unit agarmgas; getopstr:='{'; first:=true; for r:=RS_R0 to RS_R15 do - if r in o.regset then + if r in o.regset^ then begin if not(first) then getopstr:=getopstr+','; @@ -226,7 +225,10 @@ begin end. { $Log$ - Revision 1.11 2003-09-06 11:21:49 florian + Revision 1.12 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.11 2003/09/06 11:21:49 florian * fixed stm and ldm to be usable with preindex operand Revision 1.10 2003/09/05 23:57:01 florian diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index ba2a41497f..276f14e8bf 100644 --- a/compiler/arm/cgcpu.pas +++ b/compiler/arm/cgcpu.pas @@ -32,21 +32,33 @@ unit cgcpu; symtype, cgbase,cgobj, aasmbase,aasmcpu,aasmtai, - cpubase,cpuinfo,node,cg64f32,cginfo; + cpubase,cpuinfo,node,cg64f32,rgcpu; type tcgarm = class(tcg) + rgint, + rgmm, + rgfpu : trgcpu; procedure init_register_allocators;override; procedure done_register_allocators;override; + function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;override; + function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override; + function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;override; + procedure getexplicitregister(list:Taasmoutput;r:Tregister);override; + procedure ungetregister(list:Taasmoutput;r:Tregister);override; + procedure add_move_instruction(instr:Taicpu);override; + procedure do_register_allocation(list:Taasmoutput;headertai:tai);override; + procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override; + procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override; + procedure a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);override; procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);override; procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);override; procedure a_call_name(list : taasmoutput;const s : string);override; procedure a_call_reg(list : taasmoutput;reg: tregister); override; - procedure a_call_ref(list : taasmoutput;const ref : treference);override; procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister); override; procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override; @@ -88,8 +100,8 @@ unit cgcpu; procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef); override; - procedure g_save_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset);override; - procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset);override; + procedure g_save_standard_registers(list : taasmoutput);override; + procedure g_restore_standard_registers(list : taasmoutput);override; procedure g_save_all_registers(list : taasmoutput);override; procedure g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);override; @@ -115,18 +127,130 @@ unit cgcpu; uses - globtype,globals,verbose,systems,cutils,symconst,symdef,symsym,rgobj,rgcpu,tgobj,cpupi; + globtype,globals,verbose,systems,cutils, + symconst,symdef,symsym, + tgobj, + procinfo,cpupi; procedure tcgarm.init_register_allocators; begin - rg:=trgcpu.create(11,#0#1#2#3#4#5#6#7#8#9#10); + rgint:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE, + [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8, + RS_R9,RS_R10,RS_R12],first_int_imreg,[]); + rgfpu:=trgcpu.create(R_FPUREGISTER,R_SUBNONE, + [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]); + rgmm:=trgcpu.create(R_MMREGISTER,R_SUBNONE, + [RS_S0..RS_S31],first_mm_imreg,[]); end; procedure tcgarm.done_register_allocators; begin - rg.free; + rgint.free; + rgfpu.free; + rgmm.free; + end; + + + function tcgarm.getintregister(list:Taasmoutput;size:Tcgsize):Tregister; + begin + result:=rgint.getregister(list,cgsize2subreg(size)); + end; + + + function tcgarm.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister; + begin + result:=rgfpu.getregister(list,R_SUBWHOLE); + end; + + + function tcgarm.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister; + begin + result:=rgmm.getregister(list,R_SUBNONE); + end; + + + procedure tcgarm.getexplicitregister(list:Taasmoutput;r:Tregister); + begin + case getregtype(r) of + R_INTREGISTER : + rgint.getexplicitregister(list,r); + R_MMREGISTER : + rgmm.getexplicitregister(list,r); + R_FPUREGISTER : + rgfpu.getexplicitregister(list,r); + else + internalerror(200310091); + end; + end; + + + procedure tcgarm.ungetregister(list:Taasmoutput;r:Tregister); + begin + case getregtype(r) of + R_INTREGISTER : + rgint.ungetregister(list,r); + R_FPUREGISTER : + rgfpu.ungetregister(list,r); + R_MMREGISTER : + rgmm.ungetregister(list,r); + else + internalerror(200310091); + end; + end; + + + procedure tcgarm.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset); + begin + case rt of + R_INTREGISTER : + rgint.allocexplicitregisters(list,r); + R_FPUREGISTER : + rgfpu.allocexplicitregisters(list,r); + R_MMREGISTER : + rgmm.allocexplicitregisters(list,r); + else + internalerror(200310092); + end; + end; + + + procedure tcgarm.deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset); + begin + case rt of + R_INTREGISTER : + rgint.deallocexplicitregisters(list,r); + R_FPUREGISTER : + rgfpu.deallocexplicitregisters(list,r); + R_MMREGISTER : + rgmm.deallocexplicitregisters(list,r); + else + internalerror(200310093); + end; + end; + + + procedure tcgarm.add_move_instruction(instr:Taicpu); + begin + rgint.add_move_instruction(instr); + end; + + + procedure tcgarm.do_register_allocation(list:Taasmoutput;headertai:tai); + begin + { Int } + rgint.check_unreleasedregs; + rgint.do_register_allocation(list,headertai); + rgint.translate_registers(list); + { FPU } + rgfpu.check_unreleasedregs; + rgfpu.do_register_allocation(list,headertai); + rgfpu.translate_registers(list); + { MM } + rgmm.check_unreleasedregs; + rgmm.do_register_allocation(list,headertai); + rgmm.translate_registers(list); end; @@ -147,7 +271,7 @@ unit cgcpu; else internalerror(2002081101); end; - if locpara.sp_fixup<>0 then + if locpara.alignment<>0 then internalerror(2002081102); end; @@ -165,10 +289,10 @@ unit cgcpu; reference_reset(ref); ref.base:=locpara.reference.index; ref.offset:=locpara.reference.offset; - tmpreg := rg.getregisterint(list,size); + tmpreg := getintregister(list,size); a_load_ref_reg(list,size,size,r,tmpreg); a_load_reg_ref(list,size,size,tmpreg,ref); - rg.ungetregisterint(list,tmpreg); + ungetregister(list,tmpreg); end; LOC_FPUREGISTER,LOC_CFPUREGISTER: case size of @@ -180,7 +304,7 @@ unit cgcpu; else internalerror(2002081103); end; - if locpara.sp_fixup<>0 then + if locpara.alignment<>0 then internalerror(2002081104); end; @@ -198,10 +322,10 @@ unit cgcpu; reference_reset(ref); ref.base := locpara.reference.index; ref.offset := locpara.reference.offset; - tmpreg := rg.getregisterint(list,OS_ADDR); + tmpreg := getintregister(list,OS_ADDR); a_loadaddr_ref_reg(list,r,tmpreg); a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref); - rg.ungetregisterint(list,tmpreg); + ungetregister(list,tmpreg); end; else internalerror(2002080701); @@ -227,16 +351,6 @@ unit cgcpu; end; - procedure tcgarm.a_call_ref(list : taasmoutput;const ref : treference); - var - r : tregister; - begin - a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_PC); - if not(pi_do_call in current_procinfo.flags) then - internalerror(2003060705); - end; - - procedure tcgarm.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister); begin a_op_const_reg_reg(list,op,size,a,reg,reg); @@ -315,10 +429,10 @@ unit cgcpu; a_op_reg_reg(list,OP_NEG,size,src,dst) else begin - tmpreg:=rg.getregisterint(list,size); + tmpreg:=getintregister(list,size); a_load_const_reg(list,size,a,tmpreg); a_op_reg_reg_reg(list,op,size,tmpreg,src,dst); - rg.ungetregisterint(list,tmpreg); + ungetregister(list,tmpreg); end; end; end; @@ -363,21 +477,21 @@ unit cgcpu; begin if dst<>src1 then begin - rg.add_edge(dst,src1); + rgint.add_edge(dst,src1); list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2)); end else begin - tmpreg:=rg.getregisterint(list,size); + tmpreg:=getintregister(list,size); a_load_reg_reg(list,size,size,src2,dst); - rg.add_edge(dst,tmpreg); - rg.ungetregister(list,tmpreg); + rgint.add_edge(dst,tmpreg); + ungetregister(list,tmpreg); list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1)); end; end else begin - rg.add_edge(dst,src2); + rgint.add_edge(dst,src2); list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1)); end; end; @@ -486,7 +600,7 @@ unit cgcpu; current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset)); { load consts entry } - tmpreg:=rg.getregisterint(list,OS_INT); + tmpreg:=getintregister(list,OS_INT); reference_reset(tmpref); tmpref.symbol:=l; tmpref.base:=NR_R15; @@ -541,7 +655,7 @@ unit cgcpu; end else begin - tmpreg:=rg.getregisterint(list,OS_INT); + tmpreg:=getintregister(list,OS_INT); list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index)); ref.base:=tmpreg; ref.index:=NR_NO; @@ -549,7 +663,7 @@ unit cgcpu; end; list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix)); if (tmpreg<>NR_NO) then - rg.ungetregisterint(list,tmpreg); + ungetregister(list,tmpreg); end; @@ -645,7 +759,7 @@ unit cgcpu; OS_32,OS_S32: begin instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1); - rg.add_move_instruction(instr); + add_move_instruction(instr); list.concat(instr); end; else internalerror(2002090901); @@ -711,10 +825,10 @@ unit cgcpu; list.concat(taicpu.op_reg_const(A_CMN,reg,not(a))) else begin - tmpreg:=rg.getregisterint(list,size); + tmpreg:=getintregister(list,size); a_load_const_reg(list,size,a,tmpreg); list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg)); - rg.ungetregisterint(list,tmpreg); + ungetregister(list,tmpreg); end; a_jmp_cond(list,cmp_op,l); end; @@ -772,10 +886,10 @@ unit cgcpu; reference_reset(ref); ref.index:=NR_STACK_POINTER_REG; ref.addressmode:=AM_PREINDEXED; - list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,rg.used_in_proc_int-[RS_R0..RS_R3]+[RS_R11,RS_R12,RS_R15]),PF_FD)); + list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R12,RS_R15]),PF_FD)); list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4)); - a_reg_alloc(list,NR_R12); + a_reg_dealloc(list,NR_R12); { allocate necessary stack size } list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize)); @@ -793,7 +907,7 @@ unit cgcpu; { restore int registers and return } reference_reset(ref); ref.index:=NR_FRAME_POINTER_REG; - list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rg.used_in_proc_int-[RS_R0..RS_R3]+[RS_R11,RS_R13,RS_R15]),PF_EA)); + list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R13,RS_R15]),PF_EA)); end; end; @@ -840,7 +954,7 @@ unit cgcpu; else begin instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base); - rg.add_move_instruction(instr); + add_move_instruction(instr); list.concat(instr); end; end; @@ -878,7 +992,7 @@ unit cgcpu; { load consts entry } reference_reset(tmpref); - tmpreg:=rg.getregisterint(list,OS_INT); + tmpreg:=getintregister(list,OS_INT); tmpref.symbol:=l; tmpref.base:=NR_PC; list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref)); @@ -927,10 +1041,10 @@ unit cgcpu; dstref.addressmode:=AM_POSTINDEXED; srcref.offset:=size; dstref.offset:=size; - r:=rg.getregisterint(list,size2opsize[size]); + r:=getintregister(list,size2opsize[size]); a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r); a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref); - rg.ungetregisterint(list,r); + ungetregister(list,r); list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S)); list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE)); end; @@ -958,30 +1072,30 @@ unit cgcpu; cgsize:=OS_16; end; dec(len,copysize); - r:=rg.getregisterint(list,cgsize); + r:=getintregister(list,cgsize); a_load_ref_reg(list,cgsize,cgsize,srcref,r); if (len=0) and delsource then reference_release(list,source); a_load_reg_ref(list,cgsize,cgsize,r,dstref); inc(srcref.offset,copysize); inc(dstref.offset,copysize); - rg.ungetregisterint(list,r); + ungetregister(list,r); end; end else begin - destreg:=rg.getregisterint(list,OS_ADDR); + destreg:=getintregister(list,OS_ADDR); a_loadaddr_ref_reg(list,dest,destreg); if delsource then reference_release(list,srcref); - srcreg:=rg.getregisterint(list,OS_ADDR); + srcreg:=getintregister(list,OS_ADDR); if loadref then a_load_ref_reg(list,OS_ADDR,OS_ADDR,source,srcreg) else a_loadaddr_ref_reg(list,source,srcreg); - srcref. + // srcref. - countreg:=rg.getregisterint(list,OS_32); + countreg:=getintregister(list,OS_32); // if cs_littlesize in aktglobalswitches then genloop(len,1); @@ -1006,9 +1120,9 @@ unit cgcpu; list.concat(Taicpu.op_none(A_MOVSB,S_NO)); end; } - rg.ungetregisterint(list,countreg); - rg.ungetregisterint(list,srcreg); - rg.ungetregisterint(list,destreg); + ungetregister(list,countreg); + ungetregister(list,srcreg); + ungetregister(list,destreg); end; if delsource then tg.ungetiftemp(list,source); @@ -1020,13 +1134,13 @@ unit cgcpu; end; - procedure tcgarm.g_save_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset); + procedure tcgarm.g_save_standard_registers(list : taasmoutput); begin { we support only ARM standard calling conventions so this procedure has no use on the ARM } end; - procedure tcgarm.g_restore_standard_registers(list : taasmoutput; usedinproc : tsuperregisterset); + procedure tcgarm.g_restore_standard_registers(list : taasmoutput); begin { we support only ARM standard calling conventions so this procedure has no use on the ARM } end; @@ -1094,20 +1208,20 @@ unit cgcpu; list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S)) else begin - tmpreg:=rg.getregisterint(list,OS_32); + tmpreg:=cg.getintregister(list,OS_32); cg.a_load_const_reg(list,OS_32,lo(value),tmpreg); list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S)); - rg.ungetregisterint(list,tmpreg); + cg.ungetregister(list,tmpreg); end; if is_shifter_const(hi(value),b) then list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value))) else begin - tmpreg:=rg.getregisterint(list,OS_32); + tmpreg:=cg.getintregister(list,OS_32); cg.a_load_const_reg(list,OS_32,hi(value),tmpreg); list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg)); - rg.ungetregisterint(list,tmpreg); + cg.ungetregister(list,tmpreg); end; end; OP_SUB: @@ -1116,20 +1230,20 @@ unit cgcpu; list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S)) else begin - tmpreg:=rg.getregisterint(list,OS_32); + tmpreg:=cg.getintregister(list,OS_32); cg.a_load_const_reg(list,OS_32,lo(value),tmpreg); list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S)); - rg.ungetregisterint(list,tmpreg); + cg.ungetregister(list,tmpreg); end; if is_shifter_const(hi(value),b) then list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value))) else begin - tmpreg:=rg.getregisterint(list,OS_32); + tmpreg:=cg.getintregister(list,OS_32); cg.a_load_const_reg(list,OS_32,hi(value),tmpreg); list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg)); - rg.ungetregisterint(list,tmpreg); + cg.ungetregister(list,tmpreg); end; end; else @@ -1168,7 +1282,10 @@ begin end. { $Log$ - Revision 1.20 2003-10-11 16:06:42 florian + Revision 1.21 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.20 2003/10/11 16:06:42 florian * fixed some MMX<->SSE * started to fix ppc, needs an overhaul + stabs info improve for spilling, not sure if it works correctly/completly diff --git a/compiler/arm/cpubase.pas b/compiler/arm/cpubase.pas index 6ea5df7a9b..f4f9c2c028 100644 --- a/compiler/arm/cpubase.pas +++ b/compiler/arm/cpubase.pas @@ -35,7 +35,7 @@ unit cpubase; globtype,globals, cpuinfo, aasmbase, - cginfo + cgbase {$ifdef delphi} ,dmisc {$endif} @@ -99,25 +99,16 @@ unit cpubase; NR_PC = NR_R15; { Integer Super registers first and last } -{$warning Supreg shall be $00-$1f} first_int_supreg = RS_R0; - last_int_supreg = RS_R15; - - first_int_imreg = $20; - last_int_imreg = $fe; + first_int_imreg = $10; { Float Super register first and last } - first_fpu_supreg = $00; - last_fpu_supreg = $07; - - first_fpu_imreg = $20; - last_fpu_imreg = $fe; + first_fpu_supreg = RS_F0; + first_fpu_imreg = $08; { MM Super register first and last } - first_mmx_supreg = RS_INVALID; - last_mmx_supreg = RS_INVALID; - first_mmx_imreg = RS_INVALID; - last_mmx_imreg = RS_INVALID; + first_mm_supreg = RS_S0; + first_mm_imreg = $20; {$warning TODO Calculate bsstart} regnumber_count_bsstart = 64; @@ -239,9 +230,6 @@ unit cpubase; Operands *****************************************************************************} - { Types of operand } - toptype=(top_none,top_reg,top_ref,top_const,top_symbol,top_regset,top_shifterop); - tupdatereg = (UR_None,UR_Update); pshifterop = ^tshifterop; @@ -252,17 +240,6 @@ unit cpubase; shiftimm : byte; end; - toper = record - case typ : toptype of - top_none : (); - top_reg : (reg:tregister;update:tupdatereg); - top_ref : (ref:preference); - top_const : (val:aword); - top_symbol : (sym:tasmsymbol;symofs:longint); - top_regset : (regset:tsuperregisterset); - top_shifterop : (shifterop : pshifterop); - end; - {***************************************************************************** Generic Location *****************************************************************************} @@ -275,10 +252,12 @@ unit cpubase; tparalocation = packed record size : TCGSize; loc : TCGLoc; - sp_fixup : longint; + alignment : byte; case TCGLoc of LOC_REFERENCE : (reference : tparareference); { segment in reference at the same place as in loc_register } + LOC_MMREGISTER,LOC_CMMREGISTER, + LOC_FPUREGISTER,LOC_CFPUREGISTER, LOC_REGISTER,LOC_CREGISTER : ( case longint of 1 : (register,registerhigh : tregister); @@ -288,8 +267,6 @@ unit cpubase; 3 : (reg64 : tregister64); 4 : (register64 : tregister64); ); - { it's only for better handling } - LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister); end; tlocation = packed record @@ -587,7 +564,10 @@ unit cpubase; end. { $Log$ - Revision 1.16 2003-10-31 08:40:51 mazen + Revision 1.17 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.16 2003/10/31 08:40:51 mazen * rgHelper renamed to rgBase * using findreg_by_<name|number>_table directly to decrease heap overheading diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas index 71ccb4668c..56ae22c065 100644 --- a/compiler/arm/cpupara.pas +++ b/compiler/arm/cpupara.pas @@ -35,17 +35,18 @@ unit cpupara; type tarmparamanager = class(tparamanager) - function push_addr_param(def : tdef;calloption : tproccalloption) : boolean;override; + function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override; function getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override; // procedure freeintparaloc(list: taasmoutput; nr : longint); override; - procedure create_paraloc_info(p : tabstractprocdef; side: tcallercallee);override; + + function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; end; implementation uses verbose,systems, - cpuinfo,cginfo,cgbase, + cpuinfo,cgbase, rgobj, defutil,symsym; @@ -139,28 +140,34 @@ unit cpupara; end; end; - function tarmparamanager.push_addr_param(def : tdef;calloption : tproccalloption) : boolean; + function tarmparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; begin + if varspez in [vs_var,vs_out] then + begin + result:=true; + exit; + end; case def.deftype of recorddef: - push_addr_param:=true; + result:=true; arraydef: - push_addr_param:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or + result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or is_open_array(def) or is_array_of_const(def) or is_array_constructor(def); setdef : - push_addr_param:=(tsetdef(def).settype<>smallset); + result:=(tsetdef(def).settype<>smallset); stringdef : - push_addr_param:=tstringdef(def).string_typ in [st_shortstring,st_longstring]; + result:=tstringdef(def).string_typ in [st_shortstring,st_longstring]; procvardef : - push_addr_param:=po_methodpointer in tprocvardef(def).procoptions; + result:=po_methodpointer in tprocvardef(def).procoptions; else - push_addr_param:=inherited push_addr_param(def,calloption); + result:=inherited push_addr_param(varspez,def,calloption); end; end; - procedure tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee); + + function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint; var nextintreg,nextfloatreg,nextmmreg : tregister; @@ -190,142 +197,149 @@ unit cpupara; end; begin - { zero alignment bytes } - fillchar(nextintreg,sizeof(nextintreg),0); - fillchar(nextfloatreg,sizeof(nextfloatreg),0); - fillchar(nextmmreg,sizeof(nextmmreg),0); - nextintreg:=RS_R0; - nextfloatreg:=RS_F0; - nextmmreg:=RS_D0; - stack_offset:=0; + result:=0; + { zero alignment bytes } + fillchar(nextintreg,sizeof(nextintreg),0); + fillchar(nextfloatreg,sizeof(nextfloatreg),0); + fillchar(nextmmreg,sizeof(nextmmreg),0); + nextintreg:=RS_R0; + nextfloatreg:=RS_F0; + nextmmreg:=RS_D0; + stack_offset:=0; - { frame pointer for nested procedures? } - { inc(nextintreg); } - { constructor? } - { destructor? } - hp:=tparaitem(p.para.first); - while assigned(hp) do - begin - if (hp.paratyp in [vs_var,vs_out]) then - begin - paradef := voidpointertype.def; - loc := LOC_REGISTER; - end - else - begin - paradef := hp.paratype.def; - loc:=getparaloc(paradef); - end; - { make sure all alignment bytes are 0 as well } - fillchar(paraloc,sizeof(paraloc),0); - case loc of - LOC_REGISTER: - begin - paraloc.size := def_cgsize(paradef); - { for things like formaldef } - if paraloc.size = OS_NO then - paraloc.size := OS_ADDR; - is_64bit := paraloc.size in [OS_64,OS_S64]; - if nextintreg<=(RS_R3-ord(is_64bit)) then - begin - paraloc.loc:=LOC_REGISTER; + { frame pointer for nested procedures? } + { inc(nextintreg); } + { constructor? } + { destructor? } + hp:=tparaitem(p.para.first); + while assigned(hp) do + begin + if (hp.paratyp in [vs_var,vs_out]) then + begin + paradef := voidpointertype.def; + loc := LOC_REGISTER; + end + else + begin + paradef := hp.paratype.def; + loc:=getparaloc(paradef); + end; + { make sure all alignment bytes are 0 as well } + fillchar(paraloc,sizeof(paraloc),0); + case loc of + LOC_REGISTER: + begin + paraloc.size := def_cgsize(paradef); + { for things like formaldef } + if paraloc.size = OS_NO then + paraloc.size := OS_ADDR; + is_64bit := paraloc.size in [OS_64,OS_S64]; + if nextintreg<=(RS_R3-ord(is_64bit)) then + begin + paraloc.loc:=LOC_REGISTER; if is_64bit then - begin - paraloc.registerhigh:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);; - inc(nextintreg); - end; - paraloc.registerlow:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);; - inc(nextintreg); - end - else - begin - nextintreg:=RS_R4; - paraloc.loc:=LOC_REFERENCE; - paraloc.reference.index:=NR_STACK_POINTER_REG; - paraloc.reference.offset:=stack_offset; - if not is_64bit then - inc(stack_offset,4) - else - inc(stack_offset,8); - end; - end; - LOC_FPUREGISTER: - begin - paraloc.size:=def_cgsize(paradef); - if nextfloatreg<=RS_F3 then - begin - paraloc.loc:=LOC_FPUREGISTER; - paraloc.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE); - inc(nextfloatreg); - end - else - begin - {!!!!!!!} - paraloc.size:=def_cgsize(paradef); - internalerror(2002071004); - end; - end; - LOC_REFERENCE: - begin - paraloc.size:=OS_ADDR; - if push_addr_param(paradef,p.proccalloption) or - is_open_array(paradef) or - is_array_of_const(paradef) then - assignintreg - else + begin + paraloc.registerhigh:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);; + inc(nextintreg); + end; + paraloc.registerlow:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);; + inc(nextintreg); + end + else begin + nextintreg:=RS_R4; paraloc.loc:=LOC_REFERENCE; paraloc.reference.index:=NR_STACK_POINTER_REG; paraloc.reference.offset:=stack_offset; - inc(stack_offset,hp.paratype.def.size); - end; - end; - else - internalerror(2002071002); - end; - if side=calleeside then - begin - if (paraloc.loc = LOC_REFERENCE) then - paraloc.reference.offset := tvarsym(hp.parasym).adjusted_address; - end; - hp.paraloc[side]:=paraloc; - hp:=tparaitem(hp.next); - end; - { Function return } - fillchar(paraloc,sizeof(tparalocation),0); - paraloc.size:=def_cgsize(p.rettype.def); - { Return in FPU register? } - if p.rettype.def.deftype=floatdef then - begin - paraloc.loc:=LOC_FPUREGISTER; - paraloc.register:=NR_FPU_RESULT_REG; - end - else - { Return in register? } - if not ret_in_param(p.rettype.def,p.proccalloption) then - begin - paraloc.loc:=LOC_REGISTER; - if paraloc.size in [OS_64,OS_S64] then - begin - paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; - paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; - end - else - paraloc.register:=NR_FUNCTION_RETURN_REG; - end - else - begin - paraloc.loc:=LOC_REFERENCE; + if not is_64bit then + inc(stack_offset,4) + else + inc(stack_offset,8); + end; + end; + LOC_FPUREGISTER: + begin + paraloc.size:=def_cgsize(paradef); + if nextfloatreg<=RS_F3 then + begin + paraloc.loc:=LOC_FPUREGISTER; + paraloc.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE); + inc(nextfloatreg); + end + else + begin + {!!!!!!!} + paraloc.size:=def_cgsize(paradef); + internalerror(2002071004); + end; + end; + LOC_REFERENCE: + begin + paraloc.size:=OS_ADDR; + if push_addr_param(hp.paratyp,paradef,p.proccalloption) or + is_open_array(paradef) or + is_array_of_const(paradef) then + assignintreg + else + begin + paraloc.loc:=LOC_REFERENCE; + paraloc.reference.index:=NR_STACK_POINTER_REG; + paraloc.reference.offset:=stack_offset; + inc(stack_offset,hp.paratype.def.size); + end; + end; + else + internalerror(2002071002); + end; + if side=calleeside then + begin +{$warning FIXME Calleeside offset needs to be calculated} +{!!!!!! + if (paraloc.loc = LOC_REFERENCE) then + paraloc.reference.offset := tvarsym(hp.parasym).adjusted_address; +} + end; + hp.paraloc[side]:=paraloc; + hp:=tparaitem(hp.next); end; - p.funcret_paraloc[side]:=paraloc; - end; + { Function return } + fillchar(paraloc,sizeof(tparalocation),0); + paraloc.size:=def_cgsize(p.rettype.def); + { Return in FPU register? } + if p.rettype.def.deftype=floatdef then + begin + paraloc.loc:=LOC_FPUREGISTER; + paraloc.register:=NR_FPU_RESULT_REG; + end + else + { Return in register? } + if not ret_in_param(p.rettype.def,p.proccalloption) then + begin + paraloc.loc:=LOC_REGISTER; + if paraloc.size in [OS_64,OS_S64] then + begin + paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; + paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; + end + else + paraloc.register:=NR_FUNCTION_RETURN_REG; + end + else + begin + paraloc.loc:=LOC_REFERENCE; + end; + p.funcret_paraloc[side]:=paraloc; + end; begin paramanager:=tarmparamanager.create; end. { $Log$ - Revision 1.7 2003-09-11 11:55:00 florian + Revision 1.8 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.7 2003/09/11 11:55:00 florian * improved arm code generation * move some protected and private field around * the temp. register for register parameters/arguments are now released diff --git a/compiler/arm/cpupi.pas b/compiler/arm/cpupi.pas index afece847a1..e7e4416c49 100644 --- a/compiler/arm/cpupi.pas +++ b/compiler/arm/cpupi.pas @@ -30,15 +30,15 @@ unit cpupi; uses cutils, - cgbase,cpuinfo,psub; + procinfo,cpuinfo,psub; type tarmprocinfo = class(tcgprocinfo) { max. of space need for parameters, currently used by the PowerPC port only } maxpushedparasize : aword; constructor create(aparent:tprocinfo);override; - procedure handle_body_start;override; - procedure after_pass1;override; + // procedure handle_body_start;override; + // procedure after_pass1;override; procedure allocate_push_parasize(size: longint);override; function calc_stackframe_size:longint;override; end; @@ -60,7 +60,7 @@ unit cpupi; maxpushedparasize:=0; end; - +(* procedure tarmprocinfo.handle_body_start; var ofs : aword; @@ -81,7 +81,6 @@ unit cpupi; inherited handle_body_start; end; - procedure tarmprocinfo.after_pass1; begin if not(po_assembler in procdef.procoptions) then @@ -102,6 +101,7 @@ unit cpupi; inherited after_pass1; end; end; +*) procedure tarmprocinfo.allocate_push_parasize(size:longint); @@ -126,7 +126,10 @@ begin end. { $Log$ - Revision 1.1 2003-08-20 15:50:13 florian + Revision 1.2 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.1 2003/08/20 15:50:13 florian * more arm stuff } diff --git a/compiler/arm/itarmgas.pas b/compiler/arm/itarmgas.pas index 461b19a14c..e797341e6d 100644 --- a/compiler/arm/itarmgas.pas +++ b/compiler/arm/itarmgas.pas @@ -27,7 +27,7 @@ unit itarmgas; interface uses - cginfo,cpubase; + cpubase,cgbase; const @@ -113,6 +113,9 @@ implementation end. { $Log$ - Revision 1.1 2003-09-04 00:15:29 florian + Revision 1.2 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.1 2003/09/04 00:15:29 florian * first bunch of adaptions of arm compiler for new register type } diff --git a/compiler/arm/narmadd.pas b/compiler/arm/narmadd.pas index eb3501c33c..b0c2ab7ab3 100644 --- a/compiler/arm/narmadd.pas +++ b/compiler/arm/narmadd.pas @@ -27,7 +27,7 @@ unit narmadd; interface uses - node,ncgadd,cpubase,cginfo; + node,ncgadd,cpubase; type tarmaddnode = class(tcgaddnode) @@ -260,11 +260,11 @@ interface exprasmlist.concat(taicpu.op_reg_const(A_CMP,left.location.register,right.location.value)) else begin - tmpreg:=rg.getregisterint(exprasmlist,location.size); + tmpreg:=cg.getintregister(exprasmlist,location.size); cg.a_load_const_reg(exprasmlist,OS_INT, aword(right.location.value),tmpreg); exprasmlist.concat(taicpu.op_reg_reg(A_CMP,left.location.register,tmpreg)); - rg.ungetregisterint(exprasmlist,tmpreg); + cg.ungetregister(exprasmlist,tmpreg); end; end else @@ -281,7 +281,10 @@ begin end. { $Log$ - Revision 1.4 2003-09-01 15:11:16 florian + Revision 1.5 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.4 2003/09/01 15:11:16 florian * fixed reference handling * fixed operand postfix for floating point instructions * fixed wrong shifter constant handling diff --git a/compiler/arm/narmcal.pas b/compiler/arm/narmcal.pas index d738cc9cec..b36343e911 100644 --- a/compiler/arm/narmcal.pas +++ b/compiler/arm/narmcal.pas @@ -31,7 +31,7 @@ interface type tarmcallnode = class(tcgcallnode) - procedure push_framepointer;override; + // procedure push_framepointer;override; end; implementation @@ -39,19 +39,22 @@ implementation uses paramgr; - +(* procedure tarmcallnode.push_framepointer; begin framepointer_paraloc:=paramanager.getintparaloc(procdefinition.proccalloption,1); end; - +*) begin ccallnode:=tarmcallnode; end. { $Log$ - Revision 1.2 2003-09-11 11:55:00 florian + Revision 1.3 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.2 2003/09/11 11:55:00 florian * improved arm code generation * move some protected and private field around * the temp. register for register parameters/arguments are now released diff --git a/compiler/arm/narmcnv.pas b/compiler/arm/narmcnv.pas index c30c91d892..05f6fd363d 100644 --- a/compiler/arm/narmcnv.pas +++ b/compiler/arm/narmcnv.pas @@ -66,7 +66,7 @@ implementation ncon,ncal, ncgutil, cpubase,aasmcpu, - rgobj,tgobj,cgobj,cginfo; + rgobj,tgobj,cgobj; {***************************************************************************** @@ -112,7 +112,7 @@ implementation begin location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def)); location_force_reg(exprasmlist,left.location,OS_32,true); - location.register:=rg.getregisterfpu(exprasmlist,location.size); + location.register:=cg.getfpuregister(exprasmlist,location.size); instr:=taicpu.op_reg_reg(A_FLT,location.register,left.location.register); instr.oppostfix:=cgsize2fpuoppostfix[def_cgsize(resulttype.def)]; exprasmlist.concat(instr); @@ -184,7 +184,10 @@ begin end. { $Log$ - Revision 1.4 2003-09-01 15:11:16 florian + Revision 1.5 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.4 2003/09/01 15:11:16 florian * fixed reference handling * fixed operand postfix for floating point instructions * fixed wrong shifter constant handling diff --git a/compiler/arm/narminl.pas b/compiler/arm/narminl.pas index 13289a59b5..4216e6f55d 100644 --- a/compiler/arm/narminl.pas +++ b/compiler/arm/narminl.pas @@ -49,7 +49,7 @@ implementation cutils,verbose,globals,fmodule, symconst,symdef, aasmbase,aasmtai,aasmcpu, - cginfo,cgbase,pass_1,pass_2, + cgbase,pass_1,pass_2, cpubase,paramgr, nbas,ncon,ncal,ncnv,nld, tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu; @@ -65,7 +65,7 @@ implementation location_copy(location,left.location); if left.location.loc=LOC_CFPUREGISTER then begin - location.register:=rg.getregisterfpu(exprasmlist,location.size); + location.register:=cg.getfpuregister(exprasmlist,location.size); location.loc := LOC_FPUREGISTER; end; end; @@ -123,6 +123,9 @@ begin end. { $Log$ - Revision 1.1 2003-08-28 00:05:29 florian + Revision 1.2 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.1 2003/08/28 00:05:29 florian * today's arm patches } diff --git a/compiler/arm/narmmat.pas b/compiler/arm/narmmat.pas index 1ae7891160..dd02034e6e 100644 --- a/compiler/arm/narmmat.pas +++ b/compiler/arm/narmmat.pas @@ -44,7 +44,7 @@ implementation defutil, cgbase,cgobj,pass_1,pass_2, ncon, - cpubase,cpuinfo,cginfo, + cpubase,cpuinfo, ncgutil,cgcpu,cg64f32,rgobj; {***************************************************************************** @@ -102,6 +102,9 @@ begin end. { $Log$ - Revision 1.3 2003-08-27 00:27:56 florian + Revision 1.4 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.3 2003/08/27 00:27:56 florian + same procedure as very day: today's work on arm } diff --git a/compiler/arm/radirect.pas b/compiler/arm/radirect.pas index 730bf74ffe..f08a043039 100644 --- a/compiler/arm/radirect.pas +++ b/compiler/arm/radirect.pas @@ -51,8 +51,7 @@ interface { parser } scanner, { codegen } - cginfo, - cgbase, + cgbase,procinfo, { constants } itarmgas, cpubase @@ -181,11 +180,10 @@ interface hs:=tvarsym(sym).mangledname else begin - if (tvarsym(sym).reg<>NR_NO) then - hs:=std_regname(framereg) + if (tvarsym(sym).localloc.loc=LOC_REGISTER) then + hs:=gas_regname(tvarsym(sym).localloc.register) else - hs:=tostr(tvarsym(sym).address)+ - '('+std_regname(framereg)+')'; + hs:='%%'+tvarsym(sym).name; end; end else @@ -203,11 +201,7 @@ interface begin if sym.typ=varsym then begin - l:=tvarsym(sym).address; - { set offset } - inc(l,current_procinfo.procdef.parast.address_fixup); -// hs:=tostr(l)+'('+gas_reg2str[procinfo.framepointer.enum]+')'; - hs:=tostr(l)+'('+std_regname(framereg)+')'; + hs:='%%'+tvarsym(sym).name; if pos(',',s) > 0 then tvarsym(sym).varstate:=vs_used; end; @@ -336,7 +330,10 @@ initialization end. { $Log$ - Revision 1.4 2003-09-04 00:15:29 florian + Revision 1.5 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.4 2003/09/04 00:15:29 florian * first bunch of adaptions of arm compiler for new register type Revision 1.3 2003/09/01 15:11:17 florian diff --git a/compiler/arm/rgcpu.pas b/compiler/arm/rgcpu.pas index de31e746b6..d83c1459f6 100644 --- a/compiler/arm/rgcpu.pas +++ b/compiler/arm/rgcpu.pas @@ -30,7 +30,7 @@ unit rgcpu; uses aasmbase,aasmtai, - cginfo, + cgbase, cpubase, rgobj; @@ -97,7 +97,10 @@ end. { $Log$ - Revision 1.4 2003-09-11 11:55:00 florian + Revision 1.5 2003-11-02 14:30:03 florian + * fixed ARM for new reg. allocation scheme + + Revision 1.4 2003/09/11 11:55:00 florian * improved arm code generation * move some protected and private field around * the temp. register for register parameters/arguments are now released