From 414bd5fa2213b1e6c02ade29d0bfc8c91cc00707 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 30 May 2003 23:57:08 +0000 Subject: [PATCH] * more sparc cleanup * accumulator removed, splitted in function_return_reg (called) and function_result_reg (caller) --- compiler/cgobj.pas | 15 +- compiler/i386/cpubase.inc | 41 +- compiler/i386/cpupara.pas | 9 +- compiler/i386/csopt386.pas | 15 +- compiler/i386/n386cal.pas | 9 +- compiler/i386/popt386.pas | 11 +- compiler/i386/ra386att.pas | 16 +- compiler/i386/ra386int.pas | 25 +- compiler/ncgcal.pas | 54 +- compiler/ncgflw.pas | 17 +- compiler/ncgld.pas | 11 +- compiler/ncgset.pas | 9 +- compiler/ncgutil.pas | 52 +- compiler/paramgr.pas | 34 +- compiler/powerpc/cpubase.pas | 233 ++-- compiler/powerpc/radirect.pas | 17 +- compiler/psub.pas | 9 +- compiler/rautils.pas | 38 +- compiler/sparc/aasmcpu.pas | 611 +++++------ compiler/sparc/cgcpu.pas | 1865 +++++++++++++-------------------- compiler/sparc/cpubase.pas | 1364 +++++++++++++----------- compiler/sparc/cpugas.pas | 20 +- compiler/sparc/cpupara.pas | 513 ++++----- compiler/sparc/cpupi.pas | 9 +- compiler/sparc/cputarg.pas | 9 +- compiler/sparc/ncpuadd.pas | 121 +-- compiler/sparc/ncpumat.pas | 9 +- compiler/x86/aasmcpu.pas | 9 +- compiler/x86/cgx86.pas | 16 +- compiler/x86/cpubase.pas | 14 +- compiler/x86/rax86.pas | 91 +- compiler/x86_64/cpubase.inc | 36 +- 32 files changed, 2534 insertions(+), 2768 deletions(-) diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas index 3121d5d6bc..220051129c 100644 --- a/compiler/cgobj.pas +++ b/compiler/cgobj.pas @@ -277,7 +277,7 @@ unit cgobj; {# This routine is used in exception management nodes. It should - save the exception reason currently in the accumulator. The + save the exception reason currently in the FUNCTION_RETURN_REG. The save should be done either to a temp (pointed to by href). or on the stack (pushing the value on the stack). @@ -297,7 +297,7 @@ unit cgobj; procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aword);virtual; {# This routine is used in exception management nodes. It should - load the exception reason to the accumulator. The saved value + load the exception reason to the FUNCTION_RETURN_REG. The saved value should either be in the temp. area (pointed to by href , href should *NOT* be freed) or on the stack (the value should be popped). @@ -1645,7 +1645,7 @@ unit cgobj; begin r.enum:=R_INTREGISTER;; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RETURN_REG; a_load_reg_ref(list, OS_S32, r, href); end; @@ -1662,7 +1662,7 @@ unit cgobj; begin r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RETURN_REG; a_load_ref_reg(list, OS_S32, href, r); end; @@ -1691,7 +1691,12 @@ finalization end. { $Log$ - Revision 1.102 2003-05-30 23:49:18 jonas + Revision 1.103 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.102 2003/05/30 23:49:18 jonas * a_load_loc_reg now has an extra size parameter for the destination register (properly fixes what I worked around in revision 1.106 of ncgutil.pas) diff --git a/compiler/i386/cpubase.inc b/compiler/i386/cpubase.inc index 59af643747..1443f66ffe 100644 --- a/compiler/i386/cpubase.inc +++ b/compiler/i386/cpubase.inc @@ -102,6 +102,7 @@ max_scratch_regs = 1; scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI); {$endif} + {***************************************************************************** GDB Information *****************************************************************************} @@ -145,34 +146,27 @@ *****************************************************************************} {# Stack pointer register } - stack_pointer_reg = R_ESP; NR_STACK_POINTER_REG = NR_ESP; {# Frame pointer register } - frame_pointer_reg = R_EBP; NR_FRAME_POINTER_REG = NR_EBP; {# Register for addressing absolute data in a position independant way, such as in PIC code. The exact meaning is ABI specific. For further information look at GCC source : PIC_OFFSET_TABLE_REGNUM } - pic_offset_reg = R_EBX; - {# Results are returned in this register (32-bit values) } - accumulator = R_EAX; - RS_ACCUMULATOR = RS_EAX; - NR_ACCUMULATOR = NR_EAX; - { The return_result_reg is used inside the called function to store its return - value when that is a scalar value otherwise a pointer to the address of the - result is placed inside it} - return_result_reg = accumulator; - RS_RETURN_RESULT_REG = RS_ACCUMULATOR; - NR_RETURN_RESULT_REG = NR_ACCUMULATOR; + NR_PIC_OFFSET_REG = NR_EBX; + { Results are returned in this register (32-bit values) } + NR_FUNCTION_RETURN_REG = NR_EAX; + RS_FUNCTION_RETURN_REG = RS_EAX; + { High part of 64bit return value } + NR_FUNCTION_RETURNHIGH_REG = NR_EDX; + RS_FUNCTION_RETURNHIGH_REG = RS_EDX; + { The value returned from a function is available in this register } + NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG; + RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG; + { The high part of 64bit value returned from a function is available in this register } + NR_FUNCTION_RESULTHIGH_REG = NR_FUNCTION_RETURNHIGH_REG; + RS_FUNCTION_RESULTHIGH_REG = RS_FUNCTION_RETURNHIGH_REG; - {the function_result_reg contains the function result after a call to a scalar - function othewise it contains a pointer to the returned result} - function_result_reg = accumulator; - {# Hi-Results are returned in this register (64-bit value high register) } - accumulatorhigh = R_EDX; - RS_ACCUMULATORHIGH = RS_EDX; - NR_ACCUMULATORHIGH = NR_EDX; { WARNING: don't change to R_ST0!! See comments above implementation of } { a_loadfpu* methods in rgcpu (JM) } fpu_result_reg = R_ST; @@ -202,7 +196,12 @@ { $Log$ - Revision 1.3 2003-05-16 14:33:31 peter + Revision 1.4 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.3 2003/05/16 14:33:31 peter * regvar fixes Revision 1.2 2002/04/25 16:12:09 florian diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas index d44fbbf9da..ddd9d11dfe 100644 --- a/compiler/i386/cpupara.pas +++ b/compiler/i386/cpupara.pas @@ -60,7 +60,7 @@ unit cpupara; case target_info.system of system_i386_win32 : begin - { Win32 returns small records in the accumulator } + { Win32 returns small records in the FUNCTION_RETURN_REG } case def.deftype of recorddef : begin @@ -133,7 +133,12 @@ begin end. { $Log$ - Revision 1.11 2003-05-13 15:16:13 peter + Revision 1.12 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.11 2003/05/13 15:16:13 peter * removed ret_in_acc, it's the reverse of ret_in_param * fixed ret_in_param for win32 cdecl array diff --git a/compiler/i386/csopt386.pas b/compiler/i386/csopt386.pas index 17a035663b..e7034e5062 100644 --- a/compiler/i386/csopt386.pas +++ b/compiler/i386/csopt386.pas @@ -363,9 +363,9 @@ Begin {CheckSequence} OrgRegResult := False; with startRegInfo do begin - newRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG]; - new2OldReg[FRAME_POINTER_REG].enum := FRAME_POINTER_REG; - new2OldReg[STACK_POINTER_REG].enum := STACK_POINTER_REG; + newRegsEncountered := [R_EBP, R_ESP]; + new2OldReg[R_EBP].enum := R_EBP; + new2OldReg[R_ESP].enum := R_ESP; oldRegsEncountered := newRegsEncountered; end; @@ -1334,7 +1334,7 @@ begin (Taicpu(startmod).opcode = A_MOVSX) or (Taicpu(startmod).opcode = A_LEA)) and (Taicpu(startmod).oper[0].typ = top_ref) and - (Taicpu(startmod).oper[0].ref^.base.enum = STACK_POINTER_REG)) or + (Taicpu(startmod).oper[0].ref^.base.enum = R_ESP)) or not(reg.enum in pTaiprop(hp1.optInfo)^.usedRegs) or findRegDealloc(reg,p))) then pTaiprop(startMod.optInfo)^.canBeRemoved := true; @@ -1997,7 +1997,12 @@ End. { $Log$ - Revision 1.45 2003-05-16 14:33:31 peter + Revision 1.46 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.45 2003/05/16 14:33:31 peter * regvar fixes Revision 1.44 2003/04/27 11:21:35 peter diff --git a/compiler/i386/n386cal.pas b/compiler/i386/n386cal.pas index c8459c408c..e572fb87ce 100644 --- a/compiler/i386/n386cal.pas +++ b/compiler/i386/n386cal.pas @@ -197,7 +197,12 @@ begin end. { $Log$ - Revision 1.92 2003-05-26 21:17:18 peter + Revision 1.93 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.92 2003/05/26 21:17:18 peter * procinlinenode removed * aktexit2label removed, fast exit removed + tcallnode.inlined_pass_2 added @@ -294,7 +299,7 @@ end. * old logs removed and tabs fixed Revision 1.69 2002/09/01 18:43:27 peter - * include accumulator in regs_to_push list + * include FUNCTION_RETURN_REG in regs_to_push list Revision 1.68 2002/09/01 12:13:00 peter * use a_call_reg diff --git a/compiler/i386/popt386.pas b/compiler/i386/popt386.pas index d171ab81f7..73eed6c877 100644 --- a/compiler/i386/popt386.pas +++ b/compiler/i386/popt386.pas @@ -1376,7 +1376,9 @@ Begin Taicpu(hp2).opcode := A_MOV; Taicpu(hp2).Loadoper(1,Taicpu(hp1).oper[0]); reference_reset_old(tmpref); - tmpRef.base .enum:= STACK_POINTER_REG; + tmpRef.base.enum:=R_INTREGISTER; + tmpRef.base.number:=NR_STACK_POINTER_REG; + convert_register_to_enum(tmpref.base); tmpRef.offset := l; Taicpu(hp2).loadRef(0,tmpRef); hp4 := hp1; @@ -2058,7 +2060,12 @@ End. { $Log$ - Revision 1.43 2003-04-27 11:21:35 peter + Revision 1.44 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.43 2003/04/27 11:21:35 peter * aktprocdef renamed to current_procdef * procinfo renamed to current_procinfo * procinfo will now be stored in current_module so it can be diff --git a/compiler/i386/ra386att.pas b/compiler/i386/ra386att.pas index 8a8dca91e6..d4c3436809 100644 --- a/compiler/i386/ra386att.pas +++ b/compiler/i386/ra386att.pas @@ -49,7 +49,8 @@ Implementation { parser } scanner, itx86att, - rax86,rautils + rax86,rautils, + cginfo,cgobj ; type @@ -1402,6 +1403,8 @@ var end; { end case } end; +const + regsize_2_size: array[S_B..S_L] of longint = (1,2,4); var tempreg : tregister; hl : tasmlabel; @@ -1441,7 +1444,7 @@ Begin begin opr.typ:=OPR_REGISTER; opr.reg:=actasmregister; - size:=reg2opsize(actasmregister); + SetSize(regsize_2_size[reg2opsize(actasmregister)],true); Consume(AS_REGISTER); end else @@ -1594,7 +1597,7 @@ Begin Message(asmr_e_invalid_operand_type); opr.typ:=OPR_REGISTER; opr.reg:=tempreg; - size:=reg2opsize(opr.reg); + SetSize(tcgsize2size[cg.reg_cgsize(opr.reg)],true); end else Message(asmr_e_syn_operand); @@ -2134,7 +2137,12 @@ finalization end. { $Log$ - Revision 1.44 2003-05-22 21:32:29 peter + Revision 1.45 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.44 2003/05/22 21:32:29 peter * removed some unit dependencies Revision 1.43 2003/04/30 15:45:35 florian diff --git a/compiler/i386/ra386int.pas b/compiler/i386/ra386int.pas index 6fc4f2cec9..395783fb48 100644 --- a/compiler/i386/ra386int.pas +++ b/compiler/i386/ra386int.pas @@ -52,7 +52,7 @@ Implementation scanner, rautils,rax86,ag386int, { codegen } - cgbase + cginfo,cgbase,cgobj ; type @@ -1565,7 +1565,7 @@ Begin Message(asmr_e_invalid_operand_type); opr.typ:=OPR_REGISTER; opr.reg:=tempreg; - size:=reg2opsize(opr.reg) + SetSize(tcgsize2size[cg.reg_cgsize(opr.reg)],true); end; end; @@ -1620,7 +1620,7 @@ end; Procedure T386IntelInstruction.BuildOpCode; var PrefixOp,OverrideOp: tasmop; - size : topsize; + size : tcgsize; operandnum : longint; Begin PrefixOp:=A_None; @@ -1706,9 +1706,9 @@ Begin { load the size in a temp variable, so it can be set when the operand is read } Case actasmtoken of - AS_DWORD : size:=S_L; - AS_WORD : size:=S_W; - AS_BYTE : size:=S_B; + AS_DWORD : size:=OS_32; + AS_WORD : size:=OS_16; + AS_BYTE : size:=OS_8; AS_QWORD : begin if (opcode=A_FCOM) or (opcode=A_FCOMP) or @@ -1721,11 +1721,11 @@ Begin (opcode=A_FST) or (opcode=A_FSTP) or (opcode=A_FADD) then - size:=S_FL + size:=OS_F64 else - size:=S_IQ; + size:=OS_64; end; - AS_TBYTE : size:=S_FX; + AS_TBYTE : size:=OS_F80; end; Consume(actasmtoken); if actasmtoken=AS_PTR then @@ -1961,7 +1961,12 @@ finalization end. { $Log$ - Revision 1.47 2003-04-30 15:45:35 florian + Revision 1.48 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.47 2003/04/30 15:45:35 florian * merged more x86-64/i386 code Revision 1.46 2003/04/27 11:21:35 peter diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 12d941cffb..ee994eff87 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -426,7 +426,8 @@ implementation begin location_reset(location,LOC_CREFERENCE,OS_ADDR); location.reference:=refcountedtemp; - r.enum:=accumulator; + r.enum:=R_INTREGISTER; + r.number:=NR_FUNCTION_RETURN_REG; cg.a_reg_alloc(exprasmlist,r); cg.a_load_reg_ref(exprasmlist,OS_ADDR,r,location.reference); cg.a_reg_dealloc(exprasmlist,r); @@ -440,10 +441,10 @@ implementation location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def)); {$ifdef cpufpemu} if cs_fp_emulation in aktmoduleswitches then - location.register.enum := accumulator - else + location.register.enum := FUNCTION_RESULT_REG + else {$endif cpufpemu} - location.register.enum:=FPU_RESULT_REG; + location.register.enum:=FPU_RESULT_REG; {$ifdef x86} inc(trgcpu(rg).fpuvaroffset); {$else x86} @@ -466,26 +467,26 @@ implementation {$ifndef cpu64bit} if cgsize in [OS_64,OS_S64] then begin - {Move the function result to free registers, preferably the - accumulator/accumulatorhigh, so no move is necessary.} + { Move the function result to free registers, preferably the + FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.} r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; hregister.enum:=R_INTREGISTER; - hregister.number:=NR_ACCUMULATORHIGH; + hregister.number:=NR_FUNCTION_RESULTHIGH_REG; {$ifdef newra} - rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR); - rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH); + rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT_REG); + rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULTHIGH_REG); rg.ungetregisterint(exprasmlist,r); rg.ungetregisterint(exprasmlist,hregister); location.registerlow:=rg.getregisterint(exprasmlist,OS_INT); location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT); {$else newra} - if RS_ACCUMULATOR in rg.unusedregsint then - location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR) + if RS_FUNCTION_RESULT_REG in rg.unusedregsint then + location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RESULT_REG) else cg.a_reg_alloc(exprasmlist,r); - if RS_ACCUMULATORHIGH in rg.unusedregsint then - location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH) + if RS_FUNCTION_RESULTHIGH_REG in rg.unusedregsint then + location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_FUNCTION_RETURNHIGH_REG) else cg.a_reg_alloc(exprasmlist,hregister); { do this after both low,high are allocated, else it is possible that @@ -502,8 +503,8 @@ implementation {$endif cpu64bit} begin {Move the function result to a free register, preferably the - accumulator, so no move is necessary.} - nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize); + FUNCTION_RESULT_REG, so no move is necessary.} + nr:=(RS_FUNCTION_RESULT_REG shl 8) or cgsize2subreg(cgsize); r.enum:=R_INTREGISTER; r.number:=nr; {$ifdef newra} @@ -512,7 +513,7 @@ implementation location.register:=rg.getregisterint(exprasmlist,cgsize); {$else newra} cg.a_reg_alloc(exprasmlist,r); - if RS_ACCUMULATOR in rg.unusedregsint then + if RS_FUNCTION_RESULT_REG in rg.unusedregsint then location.register:=rg.getexplicitregisterint(exprasmlist,nr) else location.register:=rg.getregisterint(exprasmlist,cgsize); @@ -640,10 +641,10 @@ implementation if (not is_void(resulttype.def)) and (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then begin - include(regs_to_push_int,RS_ACCUMULATOR); + include(regs_to_push_int,RS_FUNCTION_RESULT_REG); {$ifndef cpu64bit} if resulttype.def.size>sizeof(aword) then - include(regs_to_push_int,RS_ACCUMULATORHIGH); + include(regs_to_push_int,RS_FUNCTION_RESULTHIGH_REG); {$endif cpu64bit} end; rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int); @@ -1029,10 +1030,10 @@ implementation if (not is_void(resulttype.def)) and (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then begin - include(regs_to_push_int,RS_ACCUMULATOR); + include(regs_to_push_int,RS_FUNCTION_RESULT_REG); {$ifndef cpu64bit} if resulttype.def.size>sizeof(aword) then - include(regs_to_push_int,RS_ACCUMULATORHIGH); + include(regs_to_push_int,RS_FUNCTION_RESULTHIGH_REG); {$endif cpu64bit} end; rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int); @@ -1232,11 +1233,16 @@ begin end. { $Log$ - Revision 1.77 2003-05-29 10:05:40 jonas + Revision 1.78 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.77 2003/05/29 10:05:40 jonas * free callparatemps created for call-by-reference parameters Revision 1.76 2003/05/28 23:58:18 jonas - * added missing initialization of rg.usedint{in,by}proc + * added missing initialization of rg.usedintin,byproc * ppc now also saves/restores used fpu registers * ncgcal doesn't add used registers to usedby/inproc anymore, except for i386 @@ -1478,7 +1484,7 @@ end. * several powerpc related stuff fixed Revision 1.18 2002/09/01 18:43:27 peter - * include accumulator in regs_to_push list + * include FUNCTION_RETURN_REG in regs_to_push list Revision 1.17 2002/09/01 12:13:00 peter * use a_call_reg diff --git a/compiler/ncgflw.pas b/compiler/ncgflw.pas index ce25289c49..16a66cff42 100644 --- a/compiler/ncgflw.pas +++ b/compiler/ncgflw.pas @@ -893,7 +893,7 @@ implementation begin cg.a_call_name(exprasmlist,'FPC_POPOBJECTSTACK'); r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; cg.a_param_reg(exprasmlist,OS_ADDR,r,paramanager.getintparaloc(1)); cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION'); end; @@ -1021,7 +1021,7 @@ implementation cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK'); r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; cg.a_param_reg(exprasmlist, OS_ADDR, r, paramanager.getintparaloc(1)); cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION'); { we don't need to restore esi here because reraise never } @@ -1137,8 +1137,6 @@ implementation begin location_reset(location,LOC_VOID,OS_NO); - r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; oldflowcontrol:=flowcontrol; flowcontrol:=[]; objectlibrary.getlabel(nextonlabel); @@ -1149,6 +1147,8 @@ implementation cg.a_call_name(exprasmlist,'FPC_CATCHES'); { is it this catch? No. go to next onlabel } + r.enum:=R_INTREGISTER; + r.number:=NR_FUNCTION_RESULT_REG; cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,r,nextonlabel); ref.symbol:=nil; tg.GetTemp(exprasmlist,pointer_size,tt_normal,ref); @@ -1329,7 +1329,7 @@ implementation { the value should now be in the exception handler } cg.g_exception_reason_load(exprasmlist,href); r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; if implicitframe then begin cg.a_cmp_const_reg_label(exprasmlist,OS_S32,OC_EQ,0,r,endfinallylabel); @@ -1421,7 +1421,12 @@ begin end. { $Log$ - Revision 1.65 2003-05-30 18:55:21 jonas + Revision 1.66 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.65 2003/05/30 18:55:21 jonas * fixed several regvar related bugs for non-i386. make cycle with -Or now works for ppc diff --git a/compiler/ncgld.pas b/compiler/ncgld.pas index 2661e356bf..15671731c0 100644 --- a/compiler/ncgld.pas +++ b/compiler/ncgld.pas @@ -146,14 +146,14 @@ implementation if hregister.enum<>R_INTREGISTER then internalerror(200301171); { don't save the allocated register else the result will be destroyed later } - rg.saveusedintregisters(exprasmlist,pushed,[RS_ACCUMULATOR]-[hregister.number shr 8]); + rg.saveusedintregisters(exprasmlist,pushed,[RS_FUNCTION_RESULT_REG]-[hregister.number shr 8]); reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0); cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1)); { the called procedure isn't allowed to change } { any register except EAX } cg.a_call_reg(exprasmlist,hregister); r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,r,hregister); rg.restoreusedintregisters(exprasmlist,pushed); cg.a_label(exprasmlist,norelocatelab); @@ -922,7 +922,12 @@ begin end. { $Log$ - Revision 1.63 2003-05-30 23:54:08 jonas + Revision 1.64 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.63 2003/05/30 23:54:08 jonas * forgot to commit, a_load_loc_reg change Revision 1.62 2003/05/26 19:38:28 peter diff --git a/compiler/ncgset.pas b/compiler/ncgset.pas index b841820399..5658f58f17 100644 --- a/compiler/ncgset.pas +++ b/compiler/ncgset.pas @@ -618,7 +618,7 @@ implementation cg.a_call_name(exprasmlist,'FPC_SET_IN_BYTE'); { result of value is always one full register } r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register); { release the allocated register } if not (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then @@ -1121,7 +1121,12 @@ begin end. { $Log$ - Revision 1.37 2003-05-30 23:49:18 jonas + Revision 1.38 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.37 2003/05/30 23:49:18 jonas * a_load_loc_reg now has an extra size parameter for the destination register (properly fixes what I worked around in revision 1.106 of ncgutil.pas) diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index c4fdf67096..58110d8559 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -269,7 +269,7 @@ implementation cg.a_call_name(list,'FPC_PUSHEXCEPTADDR'); r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1)); cg.a_call_name(list,'FPC_SETJMP'); @@ -290,7 +290,7 @@ implementation begin cg.g_exception_reason_load(list, href); r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RESULT_REG; cg.a_cmp_const_reg_label(list,OS_S32,OC_EQ,a,r,endexceptlabel); end; end; @@ -796,7 +796,8 @@ implementation {$endif GDB} { this is the easiest case for inlined !! } - r.enum:=stack_pointer_reg; + r.enum:=R_INTREGISTER; + r.number:=NR_STACK_POINTER_REG; if calloption=pocall_inline then reference_reset_base(href,current_procinfo.framepointer,para_offset-pushedparasize) else @@ -1229,7 +1230,7 @@ implementation end; - procedure handle_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean); + procedure load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean); var href : treference; hreg,r,r2 : tregister; @@ -1240,7 +1241,7 @@ implementation reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset); cgsize:=def_cgsize(current_procdef.rettype.def); { Here, we return the function result. In most architectures, the value is - passed into the accumulator, but in a windowed architecure like sparc a + passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a function returns in a register and the caller receives it in an other one } case current_procdef.rettype.def.deftype of orddef, @@ -1248,14 +1249,14 @@ implementation begin uses_acc:=true; r.enum:=R_INTREGISTER; - r.number:=NR_RETURN_RESULT_REG; + r.number:=NR_FUNCTION_RETURN_REG; cg.a_reg_alloc(list,r); {$ifndef cpu64bit} if cgsize in [OS_64,OS_S64] then begin uses_acchi:=true; r2.enum:=R_INTREGISTER; - r2.number:=NR_ACCUMULATORHIGH; + r2.number:=NR_FUNCTION_RETURNHIGH_REG; cg.a_reg_alloc(list,r2); cg64.a_load64_ref_reg(list,href,joinreg64(r,r2)); end @@ -1263,7 +1264,7 @@ implementation {$endif cpu64bit} begin hreg.enum:=R_INTREGISTER; - hreg.number:=RS_RETURN_RESULT_REG shl 8 or cgsize2subreg(cgsize); + hreg.number:=(RS_FUNCTION_RETURN_REG shl 8) or cgsize2subreg(cgsize); cg.a_load_ref_reg(list,cgsize,href,hreg); end; end; @@ -1272,10 +1273,10 @@ implementation uses_fpu := true; {$ifdef cpufpemu} if cs_fp_emulation in aktmoduleswitches then - r.enum := accumulator + r.enum := FUNCTION_RETURN_REG else {$endif cpufpemu} - r.enum:=fpu_result_reg; + r.enum:=FPU_RESULT_REG; cg.a_loadfpu_ref_reg(list,cgsize,href,r); end; else @@ -1284,7 +1285,7 @@ implementation begin uses_acc:=true; r.enum:=R_INTREGISTER; - r.number:=NR_RETURN_RESULT_REG; + r.number:=NR_FUNCTION_RETURN_REG; cg.a_reg_alloc(list,r); {$ifndef cpu64bit} { Win32 can return records in EAX:EDX } @@ -1292,7 +1293,7 @@ implementation begin uses_acchi:=true; r2.enum:=R_INTREGISTER; - r2.number:=NR_ACCUMULATORHIGH; + r2.number:=NR_FUNCTION_RETURNHIGH_REG; cg.a_reg_alloc(list,r2); cg64.a_load64_ref_reg(list,href,joinreg64(r,r2)); end @@ -1300,7 +1301,7 @@ implementation {$endif cpu64bit} begin hreg.enum:=R_INTREGISTER; - hreg.number:=RS_RETURN_RESULT_REG shl 8 or cgsize2subreg(cgsize); + hreg.number:=RS_FUNCTION_RETURN_REG shl 8 or cgsize2subreg(cgsize); cg.a_load_ref_reg(list,cgsize,href,hreg); end; end @@ -1629,7 +1630,7 @@ implementation { Success exit } cg.a_label(list,okexitlabel); r.enum:=R_INTREGISTER; - r.number:=NR_ACCUMULATOR; + r.number:=NR_FUNCTION_RETURN_REG; cg.a_reg_alloc(list,r); { return the self pointer } srsym:=tvarsym(current_procdef.parast.search('self')); @@ -1641,7 +1642,7 @@ implementation usesacc:=true; end else - handle_return_value(list,usesacc,usesacchi,usesfpu) + load_return_value(list,usesacc,usesacchi,usesfpu) end; {$ifdef GDB} @@ -1782,7 +1783,7 @@ implementation Inlining ****************************************************************************} - procedure handle_inlined_return_value(list:TAAsmoutput); + procedure load_inlined_return_value(list:TAAsmoutput); var href : treference; r,r2 : tregister; @@ -1793,7 +1794,7 @@ implementation reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset); cgsize:=def_cgsize(current_procdef.rettype.def); { Here, we return the function result. In most architectures, the value is - passed into the accumulator, but in a windowed architecure like sparc a + passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a function returns in a register and the caller receives it in an other one } case current_procdef.rettype.def.deftype of orddef, @@ -1817,10 +1818,10 @@ implementation begin {$ifdef cpufpemu} if cs_fp_emulation in aktmoduleswitches then - r.enum := accumulator + r.enum := FUNCTION_RETURN_REG else {$endif cpufpemu} - r.enum:=fpu_result_reg; + r.enum:=FPU_RESULT_REG; cg.a_loadfpu_ref_reg(list,cgsize,href,r); end; else @@ -1898,8 +1899,8 @@ implementation begin if (current_procdef.proctypeoption=potype_constructor) then internalerror(200305263); -// handle_inlined_return_value(list); - handle_return_value(list,usesacc,usesacchi,usesfpu) +// load_inlined_return_value(list); + load_return_value(list,usesacc,usesacchi,usesfpu) end; cleanup_regvars(list); @@ -1908,7 +1909,12 @@ implementation end. { $Log$ - Revision 1.111 2003-05-30 23:49:18 jonas + Revision 1.112 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.111 2003/05/30 23:49:18 jonas * a_load_loc_reg now has an extra size parameter for the destination register (properly fixes what I worked around in revision 1.106 of ncgutil.pas) @@ -2116,7 +2122,7 @@ end. * pass proccalloption to ret_in_xxx and push_xxx functions Revision 1.61 2002/11/17 17:49:08 mazen - + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one + + return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one Revision 1.60 2002/11/17 16:31:56 carl * memory optimization (3-4%) : cleanup of tai fields, diff --git a/compiler/paramgr.pas b/compiler/paramgr.pas index 1558cc0406..4a65b67b74 100644 --- a/compiler/paramgr.pas +++ b/compiler/paramgr.pas @@ -236,7 +236,8 @@ unit paramgr; result.loc:=LOC_REFERENCE; result.size:=OS_ADDR; result.sp_fixup:=pointer_size; - result.reference.index.enum:=stack_pointer_reg; + result.reference.index.enum:=R_INTREGISTER; + result.reference.index.number:=NR_STACK_POINTER_REG; result.reference.offset:=0; end; @@ -246,7 +247,8 @@ unit paramgr; result.loc:=LOC_REFERENCE; result.size:=OS_ADDR; result.sp_fixup:=pointer_size; - result.reference.index.enum:=stack_pointer_reg; + result.reference.index.enum:=R_INTREGISTER; + result.reference.index.number:=NR_STACK_POINTER_REG; result.reference.offset:=0; end; @@ -265,29 +267,38 @@ unit paramgr; {$ifndef cpu64bit} if result.size in [OS_64,OS_S64] then begin - result.register64.reghi.enum:=accumulatorhigh; - result.register64.reglo.enum:=accumulator; + result.register64.reghi.enum:=R_INTREGISTER; + result.register64.reghi.number:=NR_FUNCTION_RETURNHIGH_REG; + result.register64.reglo.enum:=R_INTREGISTER; + result.register64.reglo.number:=NR_FUNCTION_RETURN_REG; end else {$endif cpu64bit} - result.register.enum:=accumulator; + begin + result.register.enum:=R_INTREGISTER; + result.register.number:=NR_FUNCTION_RETURN_REG; + end; end; floatdef : begin result.loc := LOC_FPUREGISTER; {$ifdef cpufpemu} if cs_fp_emulation in aktmoduleswitches then - result.register.enum := accumulator + begin + result.register.enum:=R_INTREGISTER; + result.register.number:=FUNCTION_RETURN_REG; + end else {$endif cpufpemu} - result.register.enum := FPU_RESULT_REG; + result.register.enum := FPU_RESULT_REG; end; else begin if not ret_in_param(def,calloption) then begin result.loc := LOC_REGISTER; - result.register.enum := accumulator; + result.register.enum:=R_INTREGISTER; + result.register.number:=NR_FUNCTION_RETURN_REG; end else begin @@ -388,7 +399,12 @@ end. { $Log$ - Revision 1.38 2003-05-13 15:16:13 peter + Revision 1.39 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.38 2003/05/13 15:16:13 peter * removed ret_in_acc, it's the reverse of ret_in_param * fixed ret_in_param for win32 cdecl array diff --git a/compiler/powerpc/cpubase.pas b/compiler/powerpc/cpubase.pas index a35a38dc96..e8707d7f17 100644 --- a/compiler/powerpc/cpubase.pas +++ b/compiler/powerpc/cpubase.pas @@ -221,6 +221,7 @@ uses NR_RTOC = NR_R2; {Super registers:} + RS_NONE=$00; RS_R0 = $01; RS_R1 = $02; RS_R2 = $03; RS_R3 = $04; RS_R4 = $05; RS_R5 = $06; RS_R6 = $07; RS_R7 = $08; RS_R8 = $09; @@ -380,7 +381,7 @@ uses case typ : toptype of top_none : (); top_reg : (reg:tregister); - top_ref : (ref:^treference); + top_ref : (ref:preference); top_const : (val:aword); top_symbol : (sym:tasmsymbol;symofs:longint); top_bool : (b: boolean); @@ -474,9 +475,6 @@ uses const max_operands = 5; - lvaluelocations = [LOC_REFERENCE, LOC_CREGISTER, LOC_CFPUREGISTER, - LOC_CMMREGISTER]; - {# Constant defining possibly all registers which might require saving } {$warning FIX ME !!!!!!!!! } ALL_REGISTERS = [R_0..R_FPSCR]; @@ -591,47 +589,47 @@ uses } - stab_regindex : array[firstreg..lastreg] of shortint = - ( - { R_NO } - -1, - { R0..R7 } - 0,1,2,3,4,5,6,7, - { R8..R15 } - 8,9,10,11,12,13,14,15, - { R16..R23 } - 16,17,18,19,20,21,22,23, - { R24..R32 } - 24,25,26,27,28,29,30,31, - { F0..F7 } - 32,33,34,35,36,37,38,39, - { F8..F15 } - 40,41,42,43,44,45,46,47, - { F16..F23 } - 48,49,50,51,52,53,54,55, - { F24..F31 } - 56,57,58,59,60,61,62,63, - { M0..M7 Multimedia registers are not supported by GCC } - -1,-1,-1,-1,-1,-1,-1,-1, - { M8..M15 } - -1,-1,-1,-1,-1,-1,-1,-1, - { M16..M23 } - -1,-1,-1,-1,-1,-1,-1,-1, - { M24..M31 } - -1,-1,-1,-1,-1,-1,-1,-1, - { CR } - -1, - { CR0..CR7 } - 68,69,70,71,72,73,74,75, - { XER } - 76, - { LR } - 65, - { CTR } - 66, - { FPSCR } - -1 - ); + stab_regindex : array[firstreg..lastreg] of shortint = + ( + { R_NO } + -1, + { R0..R7 } + 0,1,2,3,4,5,6,7, + { R8..R15 } + 8,9,10,11,12,13,14,15, + { R16..R23 } + 16,17,18,19,20,21,22,23, + { R24..R32 } + 24,25,26,27,28,29,30,31, + { F0..F7 } + 32,33,34,35,36,37,38,39, + { F8..F15 } + 40,41,42,43,44,45,46,47, + { F16..F23 } + 48,49,50,51,52,53,54,55, + { F24..F31 } + 56,57,58,59,60,61,62,63, + { M0..M7 Multimedia registers are not supported by GCC } + -1,-1,-1,-1,-1,-1,-1,-1, + { M8..M15 } + -1,-1,-1,-1,-1,-1,-1,-1, + { M16..M23 } + -1,-1,-1,-1,-1,-1,-1,-1, + { M24..M31 } + -1,-1,-1,-1,-1,-1,-1,-1, + { CR } + -1, + { CR0..CR7 } + 68,69,70,71,72,73,74,75, + { XER } + 76, + { LR } + 65, + { CTR } + 66, + { FPSCR } + -1 + ); {***************************************************************************** @@ -639,18 +637,11 @@ uses *****************************************************************************} {# Stack pointer register } - stack_pointer_reg = R_1; NR_STACK_POINTER_REG = NR_R1; RS_STACK_POINTER_REG = RS_R1; {# Frame pointer register } - frame_pointer_reg = stack_pointer_reg; NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG; RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG; - {# Self pointer register : contains the instance address of an - object or class. } - self_pointer_reg = R_9; - NR_SELF_POINTER_REG = NR_R9; - RS_SELF_POINTER_REG = RS_R9; {# Register for addressing absolute data in a position independant way, such as in PIC code. The exact meaning is ABI specific. For further information look at GCC source : PIC_OFFSET_TABLE_REGNUM @@ -658,28 +649,23 @@ uses Taken from GCC rs6000.h } {$warning As indicated in rs6000.h, but can't find it anywhere else!} - pic_offset_reg = R_30; - {# Results are returned in this register (32-bit values) } - accumulator = R_3; - NR_ACCUMULATOR = NR_R3; - RS_ACCUMULATOR = RS_R3; - {the return_result_reg, is used inside the called function to store its return - value when that is a scalar value otherwise a pointer to the address of the - result is placed inside it} - return_result_reg = accumulator; - NR_RETURN_RESULT_REG = NR_ACCUMULATOR; - RS_RETURN_RESULT_REG = RS_ACCUMULATOR; + NR_PIC_OFFSET_REG = NR_R30; + { Results are returned in this register (32-bit values) } + NR_FUNCTION_RETURN_REG = NR_R3; + RS_FUNCTION_RETURN_REG = RS_R3; + { High part of 64bit return value } + NR_FUNCTION_RETURNHIGH_REG = NR_R4; + RS_FUNCTION_RETURNHIGH_REG = RS_R4; + { The value returned from a function is available in this register } + NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG; + RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG; + { The high part of 64bit value returned from a function is available in this register } + NR_FUNCTION_RESULTHIGH_REG = NR_FUNCTION_RETURNHIGH_REG; + RS_FUNCTION_RESULTHIGH_REG = RS_FUNCTION_RETURNHIGH_REG; - {the function_result_reg contains the function result after a call to a scalar - function othewise it contains a pointer to the returned result} - function_result_reg = accumulator; - {# Hi-Results are returned in this register (64-bit value high register) } - accumulatorhigh = R_4; - NR_ACCUMULATORHIGH = NR_R4; - RS_ACCUMULATORHIGH = RS_R4; { WARNING: don't change to R_ST0!! See comments above implementation of } { a_loadfpu* methods in rgcpu (JM) } - fpu_result_reg = R_F1; + FPU_RESULT_REG = R_F1; mmresultreg = R_M0; {***************************************************************************** @@ -731,6 +717,7 @@ uses procedure convert_register_to_enum(var r:Tregister); function cgsize2subreg(s:Tcgsize):Tsubregister; + implementation uses @@ -792,7 +779,6 @@ implementation procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond); - begin r.simple := true; r.cond := cond; @@ -803,64 +789,69 @@ implementation end; end; + procedure convert_register_to_enum(var r:Tregister); - - begin - if r.enum = R_INTREGISTER then - if (r.number >= NR_NO) and - (r.number <= NR_R31) then - r.enum := toldregister(r.number shr 8) - else + begin + if r.enum = R_INTREGISTER then + if (r.number >= NR_NO) and + (r.number <= NR_R31) then + r.enum := toldregister(r.number shr 8) + else { case r.number of - NR_NO: r.enum:= R_NO; + NR_NO: r.enum:= R_NO; - NR_R0: r.enum:= R_0; - NR_R1: r.enum:= R_1; - NR_R2: r.enum:= R_2; - NR_R3: r.enum:= R_3; - NR_R4: r.enum:= R_4; - NR_R5: r.enum:= R_5; - NR_R6: r.enum:= R_6; - NR_R7: r.enum:= R_7; - NR_R8: r.enum:= R_8; - NR_R9: r.enum:= R_9; - NR_R10: r.enum:= R_10; - NR_R11: r.enum:= R_11; - NR_R12: r.enum:= R_12; - NR_R13: r.enum:= R_13; - NR_R14: r.enum:= R_14; - NR_R15: r.enum:= R_15; - NR_R16: r.enum:= R_16; - NR_R17: r.enum:= R_17; - NR_R18: r.enum:= R_18; - NR_R19: r.enum:= R_19; - NR_R20: r.enum:= R_20; - NR_R21: r.enum:= R_21; - NR_R22: r.enum:= R_22; - NR_R23: r.enum:= R_23; - NR_R24: r.enum:= R_24; - NR_R25: r.enum:= R_25; - NR_R26: r.enum:= R_26; - NR_R27: r.enum:= R_27; - NR_R28: r.enum:= R_28; - NR_R29: r.enum:= R_29; - NR_R30: r.enum:= R_30; - NR_R31: r.enum:= R_31; + NR_R0: r.enum:= R_0; + NR_R1: r.enum:= R_1; + NR_R2: r.enum:= R_2; + NR_R3: r.enum:= R_3; + NR_R4: r.enum:= R_4; + NR_R5: r.enum:= R_5; + NR_R6: r.enum:= R_6; + NR_R7: r.enum:= R_7; + NR_R8: r.enum:= R_8; + NR_R9: r.enum:= R_9; + NR_R10: r.enum:= R_10; + NR_R11: r.enum:= R_11; + NR_R12: r.enum:= R_12; + NR_R13: r.enum:= R_13; + NR_R14: r.enum:= R_14; + NR_R15: r.enum:= R_15; + NR_R16: r.enum:= R_16; + NR_R17: r.enum:= R_17; + NR_R18: r.enum:= R_18; + NR_R19: r.enum:= R_19; + NR_R20: r.enum:= R_20; + NR_R21: r.enum:= R_21; + NR_R22: r.enum:= R_22; + NR_R23: r.enum:= R_23; + NR_R24: r.enum:= R_24; + NR_R25: r.enum:= R_25; + NR_R26: r.enum:= R_26; + NR_R27: r.enum:= R_27; + NR_R28: r.enum:= R_28; + NR_R29: r.enum:= R_29; + NR_R30: r.enum:= R_30; + NR_R31: r.enum:= R_31; else} - internalerror(200301082); + internalerror(200301082); { end;} - end; + end; + function cgsize2subreg(s:Tcgsize):Tsubregister; - - begin - cgsize2subreg:=R_SUBWHOLE; - end; + begin + cgsize2subreg:=R_SUBWHOLE; + end; end. { $Log$ - Revision 1.53 2003-05-30 18:49:59 jonas + Revision 1.54 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.53 2003/05/30 18:49:59 jonas * changed scratchregs from r28-r30 to r29-r31 * made sure the regvar registers don't overlap with the scratchregs anymore @@ -924,10 +915,10 @@ end. + some comments describing the fields of treference Revision 1.36 2002/11/17 18:26:16 mazen - * fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg + * fixed a compilation bug accmulator-->FUNCTION_RETURN_REG, in definition of return_result_reg Revision 1.35 2002/11/17 17:49:09 mazen - + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one + + return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one Revision 1.34 2002/09/17 18:54:06 jonas * a_load_reg_reg() now has two size parameters: source and dest. This diff --git a/compiler/powerpc/radirect.pas b/compiler/powerpc/radirect.pas index c849cc54f9..59467f42ff 100644 --- a/compiler/powerpc/radirect.pas +++ b/compiler/powerpc/radirect.pas @@ -83,6 +83,7 @@ interface srsym,sym : tsym; srsymtable : tsymtable; code : TAAsmoutput; + framereg : tregister; i,l : longint; procedure writeasmline; @@ -104,6 +105,9 @@ interface begin ende:=false; + framereg.enum:=R_INTREGISTER; + framereg.number:=NR_STACK_POINTER_REG; + convert_register_to_enum(framereg); s:=''; if assigned(current_procdef.funcretsym) and is_fpu(current_procdef.rettype.def) then @@ -191,11 +195,11 @@ interface if (tvarsym(sym).reg.enum<>R_NO) then // until new regallocator stuff settles down // hs:=gas_reg2str[procinfo.framepointer.enum] - hs:=gas_reg2str[STACK_POINTER_REG] + hs:=gas_reg2str[framereg.enum] else hs:=tostr(tvarsym(sym).address)+ // '('+gas_reg2str[procinfo.framepointer.enum]+')'; - '('+gas_reg2str[STACK_POINTER_REG]+')'; + '('+gas_reg2str[framereg.enum]+')'; end; end else @@ -217,7 +221,7 @@ interface { set offset } inc(l,current_procdef.parast.address_fixup); // hs:=tostr(l)+'('+gas_reg2str[procinfo.framepointer.enum]+')'; - hs:=tostr(l)+'('+gas_reg2str[STACK_POINTER_REG]+')'; + hs:=tostr(l)+'('+gas_reg2str[framereg.enum]+')'; if pos(',',s) > 0 then tvarsym(sym).varstate:=vs_used; end; @@ -347,7 +351,12 @@ initialization end. { $Log$ - Revision 1.13 2003-04-27 11:21:36 peter + Revision 1.14 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.13 2003/04/27 11:21:36 peter * aktprocdef renamed to current_procdef * procinfo renamed to current_procinfo * procinfo will now be stored in current_module so it can be diff --git a/compiler/psub.pas b/compiler/psub.pas index fb90a5a8fe..b6537e0d11 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -1210,8 +1210,13 @@ begin end. { $Log$ - Revision 1.119 2003-05-28 23:58:18 jonas - * added missing initialization of rg.usedint{in,by}proc + Revision 1.120 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.119 2003/05/28 23:58:18 jonas + * added missing initialization of rg.usedintin,byproc * ppc now also saves/restores used fpu registers * ncgcal doesn't add used registers to usedby/inproc anymore, except for i386 diff --git a/compiler/rautils.pas b/compiler/rautils.pas index edd123dff6..fe527e4f7d 100644 --- a/compiler/rautils.pas +++ b/compiler/rautils.pas @@ -28,7 +28,7 @@ Interface Uses cutils,cclasses, - globtype,aasmbase,aasmtai,cpubase,cpuinfo, + globtype,aasmbase,aasmtai,cpubase,cpuinfo,cginfo, symconst,symbase,symtype,symdef; Const @@ -85,14 +85,14 @@ type end; TOperand = class - size : topsize; hastype, { if the operand has typecasted variable } hasvar : boolean; { if the operand is loaded with a variable } + size : TCGSize; opr : TOprRec; constructor create; destructor destroy;override; Procedure BuildOperand;virtual; - Procedure SetSize(_size:longint;force:boolean); + Procedure SetSize(_size:longint;force:boolean);virtual; Procedure SetCorrectSize(opcode:tasmop);virtual; Function SetupResult:boolean;virtual; Function SetupSelf:boolean; @@ -104,7 +104,6 @@ type TInstruction = class opcode : tasmop; - opsize : topsize; condition : tasmcond; ops : byte; labeled : boolean; @@ -690,7 +689,7 @@ end; constructor TOperand.Create; begin - size:=S_NO; + size:=OS_NO; hastype:=false; hasvar:=false; FillChar(Opr,sizeof(Opr),0); @@ -702,32 +701,33 @@ begin end; -Procedure TOperand.SetCorrectSize(opcode:tasmop); -begin -end; - Procedure TOperand.SetSize(_size:longint;force:boolean); begin if force or - ((size = S_NO) and (_size<=extended_size)) then + ((size = OS_NO) and (_size<=extended_size)) then Begin case _size of - 1 : size:=S_B; - 2 : size:=S_W{ could be S_IS}; - 4 : size:=S_L{ could be S_IL or S_FS}; - 8 : size:=S_IQ{ could be S_D or S_FL}; + 1 : size:=OS_8; + 2 : size:=OS_16{ could be S_IS}; + 4 : size:=OS_32{ could be S_IL or S_FS}; + 8 : size:=OS_64{ could be S_D or S_FL}; else begin { extended_size can also be 8, resulting in a duplicate label } if _size=extended_size then - size:=S_FX; + size:=OS_F80; end; end; end; end; +Procedure TOperand.SetCorrectSize(opcode:tasmop); +begin +end; + + Function TOperand.SetupResult:boolean; Begin SetupResult:=false; @@ -1016,7 +1016,6 @@ end; constructor TInstruction.create; Begin Opcode:=A_NONE; - Opsize:=S_NO; Condition:=C_NONE; Ops:=0; InitOperands; @@ -1554,7 +1553,12 @@ end; end. { $Log$ - Revision 1.61 2003-05-25 08:55:49 peter + Revision 1.62 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.61 2003/05/25 08:55:49 peter * load result using hidden parameter Revision 1.60 2003/05/15 18:58:53 peter diff --git a/compiler/sparc/aasmcpu.pas b/compiler/sparc/aasmcpu.pas index 73d654b792..9b51ee81c1 100644 --- a/compiler/sparc/aasmcpu.pas +++ b/compiler/sparc/aasmcpu.pas @@ -1,10 +1,8 @@ -{***************************************************************************** +{ $Id$ - Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman + Copyright (c) 1999-2002 by Mazen Neifer - * This code was inspired by the NASM sources - The Netwide Assembler is copyright (C) 1996 Simon Tatham and - Julian Hall. All rights reserved. + Contains the assembler object for the SPARC This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,379 +17,254 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ****************************************************************************} + + **************************************************************************** +} unit aasmcpu; -{$INCLUDE fpcdefs.inc} + +{$i fpcdefs.inc} + interface + uses - cclasses,globals,verbose, - cpuinfo,cpubase, - symppu, - aasmbase,aasmtai; -const - MaxPrefixes=4; -type - { alignment for operator } - tai_align=class(tai_align_abstract) - reg:tregister; - constructor create(b:byte); - constructor create_op(b:byte; _op:byte); - end; - taicpu = class(taicpu_abstract) - opsize:topsize; - constructor op_none(op:tasmop); - constructor op_reg(op:tasmop;reg:tregister); - constructor op_const(op:tasmop;_op1:aword); - constructor op_ref(op:tasmop;const _op1:treference); - constructor op_reg_reg(op:tasmop;_op1,_op2:tregister); - constructor op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference); - constructor op_reg_const(op:tasmop;_op1:tregister;_op2:aword); - constructor op_const_reg(op:tasmop;_op1:aword;_op2:tregister); - constructor op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister); - constructor op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference); - constructor op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister); - constructor op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister); - constructor op_reg_const_reg(Op:TAsmOp;SrcReg:TRegister;value:aWord;DstReg:TRegister); - constructor op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister); - constructor op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference); + cclasses,aasmtai, + aasmbase,globals,verbose, + cpubase,cpuinfo; - { this is for Jmp instructions } - constructor op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol); - constructor op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol); - constructor op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint); - constructor op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister); - constructor op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference); - procedure changeopsize(siz:topsize); - private - procedure init(_size:topsize);{this need to be called by all constructor} - public - { the next will reset all instructions that can change in pass 2 } - procedure SetCondition(const c:TAsmCond); - private - { next fields are filled in pass1, so pass2 is faster } - procedure Swatoperands; - end; -PROCEDURE DoneAsm; -PROCEDURE InitAsm; -implementation -uses - cutils, - CpuGas; -const - _size=S_SW;{To be removed soon} -{**************************************************************************** - TAI_ALIGN - ****************************************************************************} -constructor tai_align.create(b:byte); - begin - inherited create(b); - reg.enum:= R_NONE; - end; -constructor tai_align.create_op(b:byte; _op:byte); - begin - inherited create_op(b,_op); - reg.enum:= R_NONE; - end; -{***************************************************************************** - Taicpu Constructors -*****************************************************************************} -procedure taicpu.changeopsize(siz:topsize); - begin - opsize:=siz; - end; -procedure taicpu.init(_size:topsize); - begin - opsize:=_size; - end; -constructor taicpu.op_none(op:tasmop); - begin - inherited create(op); - init(_size); - end; -constructor taicpu.op_reg(op:tasmop;reg:tregister); - begin - inherited create(op); - init(_size); - ops:=1; - loadreg(0,reg); - end; -constructor taicpu.op_const(op:tasmop;_op1:aword); - begin - inherited create(op); - init(_size); - ops:=1; - loadconst(0,aword(_op1)); - end; -constructor taicpu.op_ref(op:tasmop;const _op1:treference); - begin - inherited create(op); - init(_size); - ops:=1; - loadref(0,_op1); - end; -constructor taicpu.op_reg_reg(op:tasmop;_op1,_op2:tregister); - begin - inherited create(op); - init(_size); - ops:=2; - loadreg(0,_op1); - loadreg(1,_op2); - end; -constructor taicpu.op_reg_const(op:tasmop;_op1:tregister; _op2:aword); - begin - inherited create(op); - init(_size); - ops:=2; - loadreg(0,_op1); - loadconst(1,aword(_op2)); - end; -constructor taicpu.op_reg_ref(Op:TAsmOp;Reg:TRegister;const Ref:TReference); - begin - if not(Op in [A_STB..A_STDFQ]) - then - fail; - inherited Create(Op); - init(_size); - ops:=2; - LoadReg(0,Reg); - LoadRef(1,Ref); - end; -constructor taicpu.op_const_reg(op:tasmop;_op1:aword;_op2:tregister); - begin - inherited create(op); - init(_size); - ops:=2; - loadconst(0,aword(_op1)); - loadreg(1,_op2); - end; -constructor TAiCpu.op_ref_reg(Op:TAsmOp;const Ref:TReference;Reg:TRegister); - begin - if not(Op in [A_JMPL,A_FLUSH,A_LDSB..A_LDDC,A_RETT,A_SWAP]) - then - InternalError(2003042900); - inherited Create(Op); - Init(S_SW); - Ops:=2; - LoadRef(0,Ref); - LoadReg(1,Reg); - end; -constructor taicpu.op_ref_ref(op:tasmop;_size:topsize;const _op1,_op2:treference); - begin - inherited create(op); - init(_size); - ops:=2; - loadref(0,_op1); - loadref(1,_op2); - end; -constructor taicpu.op_reg_reg_reg(op:tasmop;_op1,_op2,_op3:tregister); - begin - inherited create(op); - init(_size); - ops:=3; - loadreg(0,_op1); - loadreg(1,_op2); - loadreg(2,_op3); - end; -constructor taicpu.op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister); - begin - inherited create(op); - init(_size); - ops:=3; - loadreg(0,_op1); - loadref(1,_op2); - loadreg(2,_op3); - end; -constructor taicpu.op_reg_const_reg(op:TAsmOp;SrcReg:TRegister;Value:aWord;DstReg:TRegister); - begin - inherited Create(Op); - Init(S_W); - ops:=3; - LoadReg(0,SrcReg); - LoadConst(1,Value); - LoadReg(2,DstReg); - end; -constructor taicpu.op_const_ref_reg(op:tasmop;_size:topsize;_op1:aword;const _op2:treference;_op3:tregister); - begin - inherited create(op); - init(_size); - ops:=3; - loadconst(0,aword(_op1)); - loadref(1,_op2); - loadreg(2,_op3); - end; -constructor taicpu.op_const_reg_ref(op:tasmop;_size:topsize;_op1:aword;_op2:tregister;const _op3:treference); - begin - inherited create(op); - init(_size); - ops:=3; - loadconst(0,aword(_op1)); - loadreg(1,_op2); - loadref(2,_op3); - end; -constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_size:topsize;_op1:tasmsymbol); - begin - inherited create(op); - init(_size); - condition:=cond; - ops:=1; - loadsymbol(0,_op1,0); - end; -constructor taicpu.op_sym(op:tasmop;_size:topsize;_op1:tasmsymbol); - begin - inherited create(op); - init(_size); - ops:=1; - loadsymbol(0,_op1,0); - end; -constructor taicpu.op_sym_ofs(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint); - begin - inherited create(op); - init(_size); - ops:=1; - loadsymbol(0,_op1,_op1ofs); - end; -constructor taicpu.op_sym_ofs_reg(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;_op2:tregister); - begin - inherited create(op); - init(_size); - ops:=2; - loadsymbol(0,_op1,_op1ofs); - loadreg(1,_op2); - end; + type + taicpu = class(taicpu_abstract) + constructor op_none(op : tasmop); + constructor op_reg(op : tasmop;_op1 : tregister); + constructor op_ref(op : tasmop;const _op1 : treference); + constructor op_const(op : tasmop;_op1 : aword); -constructor taicpu.op_sym_ofs_ref(op:tasmop;_size:topsize;_op1:tasmsymbol;_op1ofs:longint;const _op2:treference); - begin - inherited create(op); - init(_size); - ops:=2; - loadsymbol(0,_op1,_op1ofs); - loadref(1,_op2); - end; + constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister); + constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference); + constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aword); + constructor op_const_reg(op:tasmop; _op1: aword; _op2: tregister); + constructor op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister); -procedure taicpu.Swatoperands; - var - p:TOper; - begin - { Fix the operands which are in AT&T style and we need them in Intel style } - case ops of - 2:begin - { 0,1 -> 1,0 } - p:=oper[0]; - oper[0]:=oper[1]; - oper[1]:=p; - end; - 3:begin - { 0,1,2 -> 2,1,0 } - p:=oper[0]; - oper[0]:=oper[2]; - oper[2]:=p; - end; - end; - end; -{ This check must be done with the operand in ATT order - i.e.after swapping in the intel reader - but before swapping in the NASM and TASM writers PM } -{***************************************************************************** - Assembler -*****************************************************************************} -procedure TAiCpu.SetCondition(const c:TAsmCond); - const - AsmCond2OpCode:array[TAsmCond]of TAsmOp= - (A_BN,A_BNE,A_BE,A_BG,A_BLE,A_BGE,A_BL,A_BGU,A_BLEU,A_BCC, -A_BCS,A_BPOS,A_NEG,A_BVC,A_BVS,A_BA,A_BNE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE,A_NONE); - begin - inherited SetCondition(c); - if Opcode=A_BA - then - begin - is_jmp:=true; - Opcode:=AsmCond2OpCode[c]; - {$IFDEF EXTDEBUG} - WriteLn('In TAiCpu.SetCondition TAsmCond=',cond2str[c],'==>',std_op2str[OpCode]); - {$ENDIF EXTDEBUG} + constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister); + constructor op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister); + constructor op_reg_const_reg(op:tasmop;_op1:TRegister;_op2:aword;_op3:tregister); + constructor op_const_ref_reg(op:tasmop;_op1:aword;const _op2:treference;_op3:tregister); + constructor op_const_reg_ref(op:tasmop;_op1:aword;_op2:tregister;const _op3:treference); + + { this is for Jmp instructions } + constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol); + constructor op_sym(op : tasmop;_op1 : tasmsymbol); + constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint); end; - end; -procedure DoneAsm; - begin - end; -procedure InitAsm; - begin - end; + + tai_align = class(tai_align_abstract) + { nothing to add } + end; + + procedure InitAsm; + procedure DoneAsm; + + +implementation + +{***************************************************************************** + taicpu Constructors +*****************************************************************************} + + constructor taicpu.op_none(op : tasmop); + begin + inherited create(op); + end; + + + constructor taicpu.op_reg(op : tasmop;_op1 : tregister); + begin + inherited create(op); + if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then + internalerror(2003031207); + ops:=1; + loadreg(0,_op1); + end; + + + constructor taicpu.op_ref(op : tasmop;const _op1 : treference); + begin + inherited create(op); + ops:=1; + loadref(0,_op1); + end; + + + constructor taicpu.op_const(op : tasmop;_op1 : aword); + begin + inherited create(op); + ops:=1; + loadconst(0,_op1); + end; + + + constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister); + begin + inherited create(op); + if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then + internalerror(2003031205); + if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then + internalerror(2003031206); + ops:=2; + loadreg(0,_op1); + loadreg(1,_op2); + end; + + constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aword); + begin + inherited create(op); + if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then + internalerror(2003031208); + ops:=2; + loadreg(0,_op1); + loadconst(1,_op2); + end; + + constructor taicpu.op_const_reg(op:tasmop; _op1: aword; _op2: tregister); + begin + inherited create(op); + if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then + internalerror(2003031209); + ops:=2; + loadconst(0,_op1); + loadreg(1,_op2); + end; + + + constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference); + begin + inherited create(op); + if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then + internalerror(2003031210); + ops:=2; + loadreg(0,_op1); + loadref(1,_op2); + end; + + + constructor taicpu.op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister); + begin + inherited create(op); + if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then + internalerror(2003031210); + ops:=2; + loadref(0,_op1); + loadreg(1,_op2); + end; + + + constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister); + begin + inherited create(op); + if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then + internalerror(2003031211); + if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then + internalerror(2003031212); + if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then + internalerror(2003031213); + ops:=3; + loadreg(0,_op1); + loadreg(1,_op2); + loadreg(2,_op3); + end; + + + constructor taicpu.op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister); + begin + inherited create(op); + if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then + internalerror(2003031214); + if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then + internalerror(2003031215); + ops:=3; + loadreg(0,_op1); + loadref(1,_op2); + loadreg(2,_op3); + end; + + + constructor taicpu.op_reg_const_reg(op:tasmop;_op1:TRegister;_op2:aword;_op3:tregister); + begin + inherited create(op); + if (_op1.enum = R_INTREGISTER) and (_op1.number = NR_NO) then + internalerror(2003031216); + if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then + internalerror(2003031217); + ops:=3; + loadreg(0,_op1); + loadconst(1,_op2); + loadreg(2,_op3); + end; + + + constructor taicpu.op_const_ref_reg(op:tasmop;_op1:aword;const _op2:treference;_op3:tregister); + begin + inherited create(op); + if (_op3.enum = R_INTREGISTER) and (_op3.number = NR_NO) then + internalerror(2003031218); + ops:=3; + loadconst(0,_op1); + loadref(1,_op2); + loadreg(2,_op3); + end; + + + constructor taicpu.op_const_reg_ref(op:tasmop;_op1:aword;_op2:tregister;const _op3:treference); + begin + inherited create(op); + if (_op2.enum = R_INTREGISTER) and (_op2.number = NR_NO) then + internalerror(2003031219); + ops:=3; + loadconst(0,_op1); + loadreg(1,_op2); + loadref(2,_op3); + end; + + constructor taicpu.op_cond_sym(op:tasmop;cond:TAsmCond;_op1:tasmsymbol); + begin + inherited create(op); + condition:=cond; + ops:=1; + loadsymbol(0,_op1,0); + end; + + + constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol); + begin + inherited create(op); + ops:=1; + loadsymbol(0,_op1,0); + end; + + + constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint); + begin + inherited create(op); + ops:=1; + loadsymbol(0,_op1,_op1ofs); + end; + + + procedure InitAsm; + begin + end; + + + procedure DoneAsm; + begin + end; + end. { - $Log$ - Revision 1.26 2003-05-28 23:18:31 florian - * started to fix and clean up the sparc port + $Log$ + Revision 1.27 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) - Revision 1.25 2003/05/07 11:45:02 mazen - - removed unused code - - Revision 1.24 2003/05/07 11:28:26 mazen - - method CheckNonCommutativeOpcode removed as not used - - Revision 1.23 2003/05/06 20:27:43 mazen - * A_BI changed to A_BL - - Revision 1.22 2003/05/06 15:00:36 mazen - - non used code removed to bring up with powerpc changes - - Revision 1.21 2003/04/29 11:06:15 mazen - * test of invalid opcode/operand combination gives internal error - - Revision 1.20 2003/04/28 09:40:47 mazen - * Debug message in SetCondition more explicit. - - Revision 1.19 2003/03/15 22:51:58 mazen - * remaking sparc rtl compile - - Revision 1.18 2003/03/10 21:59:54 mazen - * fixing index overflow in handling new registers arrays. - - Revision 1.17 2003/02/18 22:00:20 mazen - * asm condition generation modified by TAiCpu.SetCondition - - Revision 1.16 2003/01/08 18:43:58 daniel - * Tregister changed into a record - - Revision 1.15 2003/01/05 21:32:35 mazen - * fixing several bugs compiling the RTL - - Revision 1.14 2002/12/14 15:02:03 carl - * maxoperands -> max_operands (for portability in rautils.pas) - * fix some range-check errors with loadconst - + add ncgadd unit to m68k - * some bugfix of a_param_reg with LOC_CREFERENCE - - Revision 1.13 2002/11/17 16:32:04 carl - * memory optimization (3-4%) : cleanup of tai fields, - cleanup of tdef and tsym fields. - * make it work for m68k - - Revision 1.12 2002/11/10 19:07:46 mazen - * SPARC calling mechanism almost OK (as in GCC./mppcsparc ) - - Revision 1.11 2002/11/06 11:31:24 mazen - * op_reg_reg_reg don't need any more a TOpSize parameter - - Revision 1.10 2002/11/05 16:15:00 mazen - *** empty log message *** - - Revision 1.9 2002/10/28 20:59:17 mazen - * TOpSize values changed S_L --> S_SW - - Revision 1.8 2002/10/22 13:43:01 mazen - - cga.pas redueced to an empty unit - - Revision 1.7 2002/10/20 19:01:38 mazen - + op_raddr_reg and op_caddr_reg added to fix functions prologue - - Revision 1.6 2002/10/19 20:35:07 mazen - * carl's patch applied - - Revision 1.5 2002/10/15 09:00:28 mazen - * sone coding style modified - - Revision 1.4 2002/10/13 21:46:07 mazen - * assembler output format fixed } diff --git a/compiler/sparc/cgcpu.pas b/compiler/sparc/cgcpu.pas index 344d2692f7..123171418f 100644 --- a/compiler/sparc/cgcpu.pas +++ b/compiler/sparc/cgcpu.pas @@ -1,110 +1,110 @@ -{****************************************************************************** +{ $Id$ + Copyright (c) 1998-2002 by Florian Klaempfl - Copyright (c) 1998-2000 by Florian Klaempfl + This unit implements the code generator for the SPARC - This program is free software;you can redistribute it and/or modify + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation;either version 2 of the License, or + the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY;without even the implied warranty of + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program;if not, write to the Free Software + along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - *****************************************************************************} -UNIT cgcpu; -{This unit implements the code generator for the SPARC architecture} -{$INCLUDE fpcdefs.inc} -INTERFACE -USES - cginfo,cgbase,cgobj,cg64f32, - aasmbase,aasmtai,aasmcpu, - cpubase,cpuinfo,cpupara, - node,symconst; -TYPE - TCgSparc=CLASS(tcg) -{This method is used to pass a parameter, which is located in a register, to a -routine. It should give the parameter to the routine, as required by the -specific processor ABI. It is overriden for each CPU target. - Size : is the size of the operand in the register - r : is the register source of the operand - LocPara : is the location where the parameter will be stored} - procedure a_param_reg(list:TAasmOutput;sz:tcgsize;r:tregister;const LocPara:TParaLocation);override; - {passes a parameter which is a constant to a function} - procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);override; - procedure a_param_ref(list:TAasmOutput;sz: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_ref(list:TAasmOutput;CONST ref:TReference);override; - procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override; - {Branch Instruction} - procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override; - {General purpose instyructions} - procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);override; - procedure a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);override; - procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override; - procedure a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);override; - procedure a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);override; - procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override; - procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override; + + **************************************************************************** +} +unit cgcpu; + +{$i fpcdefs.inc} + +interface + + uses + cginfo,cgbase,cgobj,cg64f32, + aasmbase,aasmtai,aasmcpu, + cpubase,cpuinfo, + node,symconst; + + type + TCgSparc=class(tcg) + private + function IsSimpleRef(const ref:treference):boolean; + public + { This method is used to pass a parameter, which is located in a register, to a + routine. It should give the parameter to the routine, as required by the + specific processor ABI. It is overriden for each CPU target. + Size : is the size of the operand in the register + r : is the register source of the operand + LocPara : is the location where the parameter will be stored } + procedure a_param_reg(list:TAasmOutput;sz:tcgsize;r:tregister;const LocPara:TParaLocation);override; + { passes a parameter which is a constant to a function } + procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation);override; + procedure a_param_ref(list:TAasmOutput;sz: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_ref(list:TAasmOutput;const ref:TReference);override; + procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override; + { General purpose instructions } + procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);override; + procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override; + procedure a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;const ref:TReference;reg:TRegister);override; + procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override; + procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override; { move instructions } - procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override; - procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);override; - procedure a_load_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override; - procedure a_load_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override; - procedure a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);override; - procedure a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);override; + procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override; + procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;const ref:TReference);override; + procedure a_load_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);override; + procedure a_load_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);override; + procedure a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);override; + procedure a_loadaddr_ref_reg(list:TAasmOutput;const ref:TReference;r:tregister);override; { fpu move instructions } - procedure a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override; - procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override; - procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override; - { vector register move instructions } - procedure a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override; - procedure a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);override; - procedure a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);override; - procedure a_parammm_reg(list:TAasmOutput;reg:tregister);override; - { comparison operations } - procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override; - procedure a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;CONST ref:TReference;l:tasmlabel);override; - procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override; - procedure a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);override; - procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;} - procedure a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);override; - procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);override; - procedure g_overflowCheck(List:TAasmOutput;const p:TNode);override; - procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override; - procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override; - procedure g_restore_frame_pointer(list:TAasmOutput);override; - procedure g_restore_standard_registers(list:taasmoutput;usedinproc:Tsupregset);override; - procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override; - procedure g_save_all_registers(list : taasmoutput);override; - procedure g_save_standard_registers(list : taasmoutput; usedinproc : Tsupregset);override; - procedure g_concatcopy(list:TAasmOutput;CONST source,dest:TReference;len:aword;delsource,loadref:boolean);override; - class function reg_cgsize(CONST reg:tregister):tcgsize;override; - PRIVATE - function IsSimpleRef(const ref:treference):boolean; - procedure sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize); - procedure floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference); - procedure floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference); - procedure floatloadops(t:tcgsize;var op:tasmop;var s:topsize); - procedure floatstoreops(t:tcgsize;var op:tasmop;var s:topsize); - END; - TCg64Sparc=class(tcg64f32) - procedure a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);override; - procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override; - procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override; - procedure a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);override; - procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp); - END; -CONST - TOpCG2AsmOp:ARRAY[topcg]OF TAsmOp=(A_NONE,A_ADD,A_AND,A_UDIV,A_SDIV,A_UMUL, A_SMUL, A_NEG,A_NOT,A_OR,A_not,A_not,A_not,A_SUB,A_XOR); - TOpCmp2AsmCond:ARRAY[topcmp]OF TAsmCond=(C_NONE,C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A); - TCGSize2OpSize:ARRAY[tcgsize]OF TOpSize=(S_NO,S_B,S_W,S_SW,S_SW,S_B,S_W,S_SW,S_SW,S_FS,S_FD,S_FQ,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO); + procedure a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override; + procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);override; + procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);override; + { comparison operations } + procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override; + procedure a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;const ref:TReference;l:tasmlabel);override; + procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override; + procedure a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;const ref:TReference;reg:tregister;l:tasmlabel);override; + procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override; + procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;} + procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override; + procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override; + procedure g_overflowCheck(List:TAasmOutput;const p:TNode);override; + procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override; + procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override; + procedure g_restore_frame_pointer(list:TAasmOutput);override; + procedure g_restore_standard_registers(list:taasmoutput;usedinproc:Tsupregset);override; + procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override; + procedure g_save_all_registers(list : taasmoutput);override; + procedure g_save_standard_registers(list : taasmoutput; usedinproc : Tsupregset);override; + procedure g_concatcopy(list:TAasmOutput;const source,dest:TReference;len:aword;delsource,loadref:boolean);override; + class function reg_cgsize(const reg:tregister):tcgsize;override; + end; + + TCg64Sparc=class(tcg64f32) + procedure a_op64_ref_reg(list:TAasmOutput;op:TOpCG;const ref:TReference;reg:TRegister64);override; + procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override; + procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override; + procedure a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;const ref:TReference);override; + procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp); + end; + + const + TOpCG2AsmOp : array[topcg] of TAsmOp=( + A_NONE,A_ADD,A_AND,A_UDIV,A_SDIV,A_UMUL, A_SMUL, A_NEG,A_NOT,A_OR,A_not,A_not,A_not,A_SUB,A_XOR + ); + TOpCmp2AsmCond : array[topcmp] of TAsmCond=( + C_NONE,C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A + ); + implementation @@ -113,863 +113,543 @@ implementation symdef,symsym,defutil,paramgr, rgobj,tgobj,rgcpu,cpupi; - procedure TCgSparc.a_param_reg(list:TAasmOutput;sz:tcgsize;r:tregister;const LocPara:TParaLocation); - var - r2:Tregister; - begin - r2.enum:=R_G0; - with list,LocPara do - case Loc of - LOC_REGISTER: - case Sz of - OS_8,OS_S8: - Concat(taicpu.op_Reg_Const_Reg(A_AND,r,$FF,Register)); - OS_16,OS_S16: - begin - Concat(taicpu.op_Reg_Reg_Reg(A_AND,r,r2,Register)); - {This will put 00...00111 in the hiest 22 bits of the reg} - Concat(taicpu.op_Reg_Const_Reg(A_SETHI,Register,$7,Register)); - end; - OS_32,OS_S32: - if r.enum<>Register.enum - then - Concat(taicpu.op_Reg_Reg_Reg(A_OR,r,r2,Register)); - else - InternalError(2002032212); - end; - else - InternalError(2002101002); - end; - end; +{**************************************************************************** + This is private property, keep out! :) +****************************************************************************} - procedure TCgSparc.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation); - var - Ref:TReference; - begin - case locpara.loc of - LOC_REGISTER,LOC_CREGISTER: - a_load_const_reg(list,size,a,locpara.register); - LOC_REFERENCE: - begin - reference_reset(ref); - ref.base:=locpara.reference.index; - ref.offset:=locpara.reference.offset; - a_load_const_ref(list,size,a,ref); - end; - else - InternalError(2002122200); + function TCgSparc.IsSimpleRef(const ref:treference):boolean; + begin + if (ref.base.number=NR_NO) and (ref.index.number<>NR_NO) then + InternalError(2002100804); + result :=not(assigned(ref.symbol))and + (((ref.index.number = NR_NO) and + (ref.offset >= low(smallint)) and + (ref.offset <= high(smallint))) or + ((ref.index.number <> NR_NO) and + (ref.offset = 0))); end; - if locpara.sp_fixup<>0 - then - InternalError(2002122201); - end; - procedure TCgSparc.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const LocPara:TParaLocation); - var - ref: treference; - tmpreg:TRegister; - begin - with LocPara do +{**************************************************************************** + Assembler code +****************************************************************************} + + function TCgSparc.reg_cgsize(const reg:tregister):tcgsize; + begin + result:=OS_32; + end; + + + procedure TCgSparc.a_param_reg(list:TAasmOutput;sz:tcgsize;r:tregister;const LocPara:TParaLocation); + var + zeroreg:Tregister; + begin + zeroreg.enum:=R_INTREGISTER; + zeroreg.number:=NR_G0; + with list,LocPara do + case Loc of + LOC_REGISTER: + begin + case Sz of + OS_8,OS_S8: + Concat(taicpu.op_Reg_Const_Reg(A_AND,r,$FF,Register)); + OS_16,OS_S16: + begin + Concat(taicpu.op_Reg_Reg_Reg(A_AND,r,zeroreg,Register)); + {This will put 00...00111 in the hiest 22 bits of the reg} + Concat(taicpu.op_Reg_Const_Reg(A_SETHI,Register,$7,Register)); + end; + OS_32,OS_S32: + begin + if r.number<>Register.number then + Concat(taicpu.op_Reg_Reg_Reg(A_OR,r,zeroreg,Register)); + end; + else + InternalError(2002032212); + end; + end; + else + InternalError(2002101002); + end; + end; + + + procedure TCgSparc.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation); + var + Ref:TReference; + begin case locpara.loc of LOC_REGISTER,LOC_CREGISTER: - a_load_ref_reg(list,sz,r,Register); + a_load_const_reg(list,size,a,locpara.register); LOC_REFERENCE: begin - { Code conventions need the parameters being allocated in %o6+92. See - comment on g_stack_frame } - if locpara.sp_fixup<92 then - InternalError(2002081104); reference_reset(ref); ref.base:=locpara.reference.index; ref.offset:=locpara.reference.offset; - tmpreg := get_scratch_reg_int(list,sz); - a_load_ref_reg(list,sz,r,tmpreg); - a_load_reg_ref(list,sz,tmpreg,ref); - free_scratch_reg(list,tmpreg); - end; - LOC_FPUREGISTER,LOC_CFPUREGISTER: - case sz of - OS_32: - a_loadfpu_ref_reg(list,OS_F32,r,locpara.register); - OS_64: - a_loadfpu_ref_reg(list,OS_F64,r,locpara.register); - else - internalerror(2002072801); + a_load_const_ref(list,size,a,ref); end; else - internalerror(2002081103); + InternalError(2002122200); end; - end; - - - procedure TCgSparc.a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation); - var - Ref:TReference; - TmpReg:TRegister; - begin - case locpara.loc of - LOC_REGISTER,LOC_CREGISTER: - a_loadaddr_ref_reg(list,r,locpara.register); - LOC_REFERENCE: - begin - reference_reset(ref); - ref.base := locpara.reference.index; - ref.offset := locpara.reference.offset; - tmpreg := get_scratch_reg_address(list); - a_loadaddr_ref_reg(list,r,tmpreg); - a_load_reg_ref(list,OS_ADDR,tmpreg,ref); - free_scratch_reg(list,tmpreg); - end; - else - internalerror(2002080701); + if locpara.sp_fixup<>0 then + InternalError(2002122201); end; - end; - procedure TCgSparc.a_call_name(list:TAasmOutput;const s:string); - begin - list.concat(taicpu.op_sym(A_CALL,S_SW,objectlibrary.newasmsymbol(s))); - list.concat(taicpu.op_none(A_NOP)); - include(current_procinfo.flags,pi_do_call); - end; + procedure TCgSparc.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const LocPara:TParaLocation); + var + ref: treference; + tmpreg:TRegister; + begin + with LocPara do + case locpara.loc of + LOC_REGISTER,LOC_CREGISTER: + a_load_ref_reg(list,sz,r,Register); + LOC_REFERENCE: + begin + { Code conventions need the parameters being allocated in %o6+92. See + comment on g_stack_frame } + if locpara.sp_fixup<92 then + InternalError(2002081104); + reference_reset(ref); + ref.base:=locpara.reference.index; + ref.offset:=locpara.reference.offset; + tmpreg := get_scratch_reg_int(list,sz); + a_load_ref_reg(list,sz,r,tmpreg); + a_load_reg_ref(list,sz,tmpreg,ref); + free_scratch_reg(list,tmpreg); + end; + LOC_FPUREGISTER,LOC_CFPUREGISTER: + case sz of + OS_32: + a_loadfpu_ref_reg(list,OS_F32,r,locpara.register); + OS_64: + a_loadfpu_ref_reg(list,OS_F64,r,locpara.register); + else + internalerror(2002072801); + end; + else + internalerror(2002081103); + end; + end; - procedure TCgSparc.a_call_ref(list:TAasmOutput;const ref:TReference); - begin - list.concat(taicpu.op_ref(A_CALL,ref)); - list.concat(taicpu.op_none(A_NOP)); - include(current_procinfo.flags,pi_do_call); - end; - - - procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister); - var - RetAddrReg:TRegister; - begin - with RetAddrReg do - begin - enum:=R_INTREGISTER; - Number:=NR_O7; + procedure TCgSparc.a_paramaddr_ref(list:TAasmOutput;const r:TReference;const LocPara:TParaLocation); + var + Ref:TReference; + TmpReg:TRegister; + begin + case locpara.loc of + LOC_REGISTER,LOC_CREGISTER: + a_loadaddr_ref_reg(list,r,locpara.register); + LOC_REFERENCE: + begin + reference_reset(ref); + ref.base := locpara.reference.index; + ref.offset := locpara.reference.offset; + tmpreg := get_scratch_reg_address(list); + a_loadaddr_ref_reg(list,r,tmpreg); + a_load_reg_ref(list,OS_ADDR,tmpreg,ref); + free_scratch_reg(list,tmpreg); + end; + else + internalerror(2002080701); end; - list.concat(taicpu.op_reg_reg(A_JMPL,reg,RetAddrReg)); - { why only on Sparc/Linux? Doesn't use other implementations use the delay slot? (FK) } - if target_info.system=system_sparc_linux then + end; + + + procedure TCgSparc.a_call_name(list:TAasmOutput;const s:string); + begin + list.concat(taicpu.op_sym(A_CALL,objectlibrary.newasmsymbol(s))); list.concat(taicpu.op_none(A_NOP)); - include(current_procinfo.flags,pi_do_call); - end; - - - procedure TCgSparc.a_jmp_always(List:TAasmOutput;l:TAsmLabel); - begin - List.Concat(TAiCpu.op_sym(A_BA,S_NO,objectlibrary.newasmsymbol(l.name))); - end; - - - {********************** load instructions ********************} - procedure TCgSparc.a_load_const_reg(list : TAasmOutput;size : TCGSize;a : aword;reg : TRegister); - var - r:Tregister; - begin - r.enum:=R_INTREGISTER; - r.number:=NR_G0; - { we don't use the set instruction here because it could be evalutated to two - instructions which would cause problems with the delay slot (FK) } - { sethi allows to set the upper 22 bit, so we'll take full advantage of it } - if (a and $3ff)=0 then - list.concat(taicpu.op_const_reg(A_SETHI,(a and $fffffc00) shr 10,reg)) - else if (a and $ffffe000)=0 then - list.concat(taicpu.op_reg_const_reg(A_OR,r,a,reg)) - else - begin - list.concat(taicpu.op_const_reg(A_SETHI,(a and $ffffe000) shr 13,reg)); - list.concat(taicpu.op_reg_const_reg(A_OR,r,a and $1fff,reg)); - end; - end; - - - procedure TCgSparc.a_load_const_ref(list : TAasmOutput;size : tcgsize;a : aword;const ref : TReference); - var - r:Tregister; - begin - inherited a_load_const_ref(list,size,a,ref); - r.enum:=R_INTREGISTER; - r.number:=NR_G0; - if a=0 then - a_load_reg_ref(list,size,r,ref) - else - inherited a_load_const_ref(list,size,a,ref); - end; - - - procedure TCgSparc.a_load_reg_ref(list:TAasmOutput;size:TCGSize;reg:tregister;const Ref:TReference); - var - op:tasmop; - begin - case size of - { signed integer registers } - OS_8, - OS_S8: - Op:=A_STB; - OS_16, - OS_S16: - Op:=A_STH; - OS_32, - OS_S32: - Op:=A_ST; - else - InternalError(2002122100); + include(current_procinfo.flags,pi_do_call); end; - list.concat(taicpu.op_reg_ref(op,reg,ref)); - end; - procedure TCgSparc.a_load_ref_reg(list:TAasmOutput;size:TCgSize;const ref:TReference;reg:tregister); - var - op:tasmop; - begin - case size of - { signed integer registers } - OS_S8: - Op:=A_LDSB;{Load Signed Byte} - OS_S16: - Op:=A_LDSH;{Load Signed Halfword} - OS_8: - Op:=A_LDUB;{Load Unsigned Bye} - OS_16: - Op:=A_LDUH;{Load Unsigned Halfword} - OS_S32, - OS_32: - Op:=A_LD;{Load Word} - else - InternalError(2002122100); + procedure TCgSparc.a_call_ref(list:TAasmOutput;const ref:TReference); + begin + list.concat(taicpu.op_ref(A_CALL,ref)); + list.concat(taicpu.op_none(A_NOP)); + include(current_procinfo.flags,pi_do_call); end; - list.concat(taicpu.op_ref_reg(op,ref,reg)); - end; -procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister); - var - op:tasmop; - s:topsize; - r:Tregister; - begin - if(reg1.enum<>R_INTREGISTER)or(reg1.number=0) - then - InternalError(200303101); - if(reg2.enum<>R_INTREGISTER)or(reg2.number=0) - then - InternalError(200303102); - r.enum:=R_G0; - r.Number:=NR_G0; - if(reg1.Number<>reg2.Number)or - (tcgsize2size[tosize] fromsize)and - not(fromsize in [OS_32,OS_S32])) - then - with list do - case fromsize of - OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32: - concat(taicpu.op_reg_reg_reg(A_OR,r,reg1,reg2)); - OS_64,OS_S64: - begin - concat(taicpu.op_reg_reg_reg(A_OR,r,reg1,reg2)); - with reg1 do - begin - enum:=Succ(enum); - Number:=RegEnum2Number[enum]; - end; - with reg2 do - begin - enum:=Succ(enum); - Number:=RegEnum2Number[enum]; - end; - concat(taicpu.op_reg_reg_reg(A_OR,r,reg1,reg2)); - end; - else internalerror(2002090901); - end; - end; - - procedure TCgSparc.a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister); - - begin - { if NOT (reg1 IN [R_F0..R_F31]) then - begin - list.concat(taicpu.op_reg(A_NONE,S_NO, - trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset))); - inc(trgcpu(rg).fpuvaroffset); - end; - if NOT (reg2 IN [R_F0..R_F31]) then - begin - list.concat(taicpu.op_reg(A_JMPL,S_NO, - trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset))); - dec(trgcpu(rg).fpuvaroffset); - end;} - end; - - - procedure TCgSparc.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister); - - begin - floatload(list,size,ref); - { if (reg <> R_ST) then - a_loadfpu_reg_reg(list,R_ST,reg);} - end; - - - procedure TCgSparc.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference); - const - FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp = - { indexed? updating?} - (((A_STF,A_STF),(A_STF,A_STF)), - ((A_STDF,A_STDF),(A_STDF,A_STDF))); - var - op: tasmop; - ref2: treference; - freereg: boolean; - begin - if not(size in [OS_F32,OS_F64]) - then - internalerror(200201122); - { ref2:=ref; - freereg:=fixref(list,ref2); - op:=fpustoreinstr[size,ref2.index.enum <> R_NO,false]; - a_load_store(list,op,reg,ref2); - if freereg - then - cg.free_scratch_reg(list,ref2.base);} - end; - - - procedure TCgSparc.a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister); - - begin - // list.concat(taicpu.op_reg_reg(A_NONEQ,S_NO,reg1,reg2)); - end; - - - procedure TCgSparc.a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister); - - begin - // list.concat(taicpu.op_ref_reg(A_NONEQ,S_NO,ref,reg)); - end; - - - procedure TCgSparc.a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference); - - begin - // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,ref)); - end; - procedure TCgSparc.a_parammm_reg(list:TAasmOutput;reg:tregister); - VAR - href:TReference; - BEGIN - // list.concat(taicpu.op_const_reg(A_SUB,S_SW,8,R_RSP)); - // reference_reset_base(href,R_ESP,0); - // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,href)); - END; - procedure TCgSparc.a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister); - - var - opcode:tasmop; - power:LongInt; - - begin - (* Case Op of - OP_DIV, OP_IDIV: - Begin - if ispowerof2(a,power) then - begin - case op of - OP_DIV: - opcode := A_SHR; - OP_IDIV: - opcode := A_SAR; - end; - list.concat(taicpu.op_const_reg(opcode,S_SW,power, - reg)); - exit; - end; - { the rest should be handled specifically in the code } - { generator because of the silly register usage restraints } - internalerror(200109224); - End; - OP_MUL,OP_IMUL: - begin - if not(cs_check_overflow in aktlocalswitches) and - ispowerof2(a,power) then - begin - list.concat(taicpu.op_const_reg(A_SHL,S_SW,power, - reg)); - exit; - end; - if op = OP_IMUL then - list.concat(taicpu.op_const_reg(A_IMUL,S_SW, - a,reg)) - else - { OP_MUL should be handled specifically in the code } - { generator because of the silly register usage restraints } - internalerror(200109225); - end; - OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR: - if not(cs_check_overflow in aktlocalswitches) and - (a = 1) and - (op in [OP_ADD,OP_SUB]) then - if op = OP_ADD then - list.concat(taicpu.op_reg(A_INC,S_SW,reg)) - else - list.concat(taicpu.op_reg(A_DEC,S_SW,reg)) - else if (a = 0) then - if (op <> OP_AND) then - exit - else - list.concat(taicpu.op_const_reg(A_NONE,S_SW,0,reg)) - else if (a = high(aword)) and - (op in [OP_AND,OP_OR,OP_XOR]) then - begin - case op of - OP_AND: - exit; - OP_OR: - list.concat(taicpu.op_const_reg(A_NONE,S_SW,high(aword),reg)); - OP_XOR: - list.concat(taicpu.op_reg(A_NOT,S_SW,reg)); - end - end - else - list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],S_SW, - a,reg)); - OP_SHL,OP_SHR,OP_SAR: - begin - if (a and 31) <> 0 Then - list.concat(taicpu.op_const_reg( - TOpCG2AsmOp[op],S_SW,a and 31,reg)); - if (a shr 5) <> 0 Then - internalerror(68991); - end - else internalerror(68992); - end;*) - end; - - - procedure TCgSparc.a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference); - - var - opcode:tasmop; - power:LongInt; - - begin - (* Case Op of - OP_DIV, OP_IDIV: - Begin - if ispowerof2(a,power) then - begin - case op of - OP_DIV: - opcode := A_SHR; - OP_IDIV: - opcode := A_SAR; - end; - list.concat(taicpu.op_const_ref(opcode, - TCgSize2OpSize[size],power,ref)); - exit; - end; - { the rest should be handled specifically in the code } - { generator because of the silly register usage restraints } - internalerror(200109231); - End; - OP_MUL,OP_IMUL: - begin - if not(cs_check_overflow in aktlocalswitches) and - ispowerof2(a,power) then - begin - list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size], - power,ref)); - exit; - end; - { can't multiply a memory location directly with a CONSTant } - if op = OP_IMUL then - inherited a_op_const_ref(list,op,size,a,ref) - else - { OP_MUL should be handled specifically in the code } - { generator because of the silly register usage restraints } - internalerror(200109232); - end; - OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR: - if not(cs_check_overflow in aktlocalswitches) and - (a = 1) and - (op in [OP_ADD,OP_SUB]) then - if op = OP_ADD then - list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref)) - else - list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref)) - else if (a = 0) then - if (op <> OP_AND) then - exit - else - a_load_const_ref(list,size,0,ref) - else if (a = high(aword)) and - (op in [OP_AND,OP_OR,OP_XOR]) then - begin - case op of - OP_AND: - exit; - OP_OR: - list.concat(taicpu.op_const_ref(A_NONE,TCgSize2OpSize[size],high(aword),ref)); - OP_XOR: - list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],ref)); - end - end - else - list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op], - TCgSize2OpSize[size],a,ref)); - OP_SHL,OP_SHR,OP_SAR: - begin - if (a and 31) <> 0 Then - list.concat(taicpu.op_const_ref( - TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref)); - if (a shr 5) <> 0 Then - internalerror(68991); - end - else internalerror(68992); - end;*) - end; - - - procedure TCgSparc.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister); - - var - regloadsize:tcgsize; - dstsize:topsize; - tmpreg:tregister; - popecx:boolean; - - begin - (* dstsize := S_Q{makeregsize(dst,size)}; - case op of - OP_NEG,OP_NOT: - begin - if src <> R_NO then - internalerror(200112291); - list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst)); - end; - OP_MUL,OP_DIV,OP_IDIV: - { special stuff, needs separate handling inside code } - { generator } - internalerror(200109233); - OP_SHR,OP_SHL,OP_SAR: - begin - tmpreg := R_NO; - { we need cl to hold the shift count, so if the destination } - { is ecx, save it to a temp for now } - if dst in [R_ECX,R_CX,R_CL] then - begin - case S_SW of - S_B:regloadsize := OS_8; - S_W:regloadsize := OS_16; - else regloadsize := OS_32; - end; - tmpreg := get_scratch_reg(list); - a_load_reg_reg(list,regloadsize,OS_32,src,tmpreg); - end; - if not(src in [R_ECX,R_CX,R_CL]) then - begin - { is ecx still free (it's also free if it was allocated } - { to dst, since we've moved dst somewhere else already) } - if not((dst = R_ECX) or - ((R_ECX in rg.unusedregsint) and - { this will always be true, it's just here to } - { allocate ecx } - (rg.getexplicitregisterint(list,R_ECX) = R_ECX))) then - begin - list.concat(taicpu.op_reg(A_NONE,S_SW,R_ECX)); - popecx := true; - end; - a_load_reg_reg(list,OS_8,OS_8,(src),R_CL); - end - else - src := R_CL; - { do the shift } - if tmpreg = R_NO then - list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize, - R_CL,dst)) - else - begin - list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],S_SW, - R_CL,tmpreg)); - { move result back to the destination } - a_load_reg_reg(list,OS_32,OS_32,tmpreg,R_ECX); - free_scratch_reg(list,tmpreg); - end; - if popecx then - list.concat(taicpu.op_reg(A_POP,S_SW,R_ECX)) - else if not (dst in [R_ECX,R_CX,R_CL]) then - rg.ungetregisterint(list,R_ECX); - end; - else - begin - if S_SW <> dstsize then - internalerror(200109226); - list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize, - src,dst)); - end; - end;*) - end; - - - procedure TCgSparc.a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister); - - var - opsize:topsize; - - begin - (* case op of - OP_NEG,OP_NOT,OP_IMUL: - begin - inherited a_op_ref_reg(list,op,size,ref,reg); - end; - OP_MUL,OP_DIV,OP_IDIV: - { special stuff, needs separate handling inside code } - { generator } - internalerror(200109239); - else - begin - opsize := S_Q{makeregsize(reg,size)}; - list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],opsize,ref,reg)); - end; - end;*) - end; - - - procedure TCgSparc.a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference); - - var - opsize:topsize; - - begin - (* case op of - OP_NEG,OP_NOT: - begin - if reg <> R_NO then - internalerror(200109237); - list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref)); - end; - OP_IMUL: - begin - { this one needs a load/imul/store, which is the default } - inherited a_op_ref_reg(list,op,size,ref,reg); - end; - OP_MUL,OP_DIV,OP_IDIV: - { special stuff, needs separate handling inside code } - { generator } - internalerror(200109238); - else - begin - opsize := tcgsize2opsize[size]; - list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,ref)); - end; - end;*) - end; - - - procedure TCgSparc.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg; - size:tcgsize;a:aword;src, dst:tregister); - var - tmpref:TReference; - power:LongInt; - opsize:topsize; - begin - opsize := S_SW; - if (opsize <> S_SW) or - not (size in [OS_32,OS_S32]) then - begin - inherited a_op_const_reg_reg(list,op,size,a,src,dst); - exit; - end; - { if we get here, we have to do a 32 bit calculation, guaranteed } - Case Op of - OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR, - OP_SAR: - { can't do anything special for these } - inherited a_op_const_reg_reg(list,op,size,a,src,dst); - OP_IMUL: - begin - if not(cs_check_overflow in aktlocalswitches) and - ispowerof2(a,power) then - { can be done with a shift } - inherited a_op_const_reg_reg(list,op,size,a,src,dst); - list.concat(taicpu.op_reg_const_reg(A_SMUL,src,a,dst)); - end; - OP_ADD, OP_SUB: - if (a = 0) then - a_load_reg_reg(list,size,size,src,dst) - else - begin - reference_reset(tmpref); - tmpref.base := src; - tmpref.offset := LongInt(a); - if op = OP_SUB then - tmpref.offset := -tmpref.offset; - list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst)); - end - else internalerror(200112302); - end; - end; - - procedure TCgSparc.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg; - size:tcgsize;src1, src2, dst:tregister); - var - tmpref:TReference; - opsize:topsize; - begin - opsize := S_SW; - if (opsize <> S_SW) or - (S_SW <> S_SW) or - not (size in [OS_32,OS_S32]) then - begin - inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst); - exit; - end; - { if we get here, we have to do a 32 bit calculation, guaranteed } - Case Op of - OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR, - OP_SAR,OP_SUB,OP_NOT,OP_NEG: - { can't do anything special for these } - inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst); - OP_IMUL: - list.concat(taicpu.op_reg_reg_reg(A_SMUL,src1,src2,dst)); - OP_ADD: - begin - reference_reset(tmpref); - tmpref.base := src1; - tmpref.index := src2; - list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst)); - end - else internalerror(200112303); - end; - end; - - {*************** compare instructructions ****************} - procedure TCgSparc.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel); - begin - if(a=0) - then - list.concat(taicpu.op_reg_reg(A_CMP,reg,reg)) - else - list.concat(taicpu.op_reg_const(A_CMP,reg,a)); - a_jmp_cond(list,cmp_op,l); - end; - procedure TCgSparc.a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;const ref:TReference;l:tasmlabel); - var - cReg,rReg:TRegister; - begin - with cg do - begin - cReg:=get_scratch_reg_int(List,size); - rReg:=get_scratch_reg_int(List,size); - a_load_const_reg(List,OS_32,a,cReg); - a_load_ref_reg(List,OS_32,ref,rReg); - List.Concat(taicpu.op_reg_reg(A_CMP,rReg,cReg)); - a_jmp_cond(list,cmp_op,l); - free_scratch_reg(List,cReg); - free_scratch_reg(List,rReg); - end; - end; - - procedure TCgSparc.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp; - reg1,reg2:tregister;l:tasmlabel); - - begin - { if regsize(reg1) <> S_SW then - internalerror(200109226); - list.concat(taicpu.op_reg_reg(A_CMP,regsize(reg1),reg1,reg2)); - a_jmp_cond(list,cmp_op,l);} - end; - procedure TCgSparc.a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel); - var - TempReg:TRegister; - begin - TempReg:=cg.get_scratch_reg_int(List,size); - a_load_ref_reg(list,OS_32,Ref,TempReg); - list.concat(taicpu.op_reg_reg_reg(A_SUBcc,TempReg,Reg,CpuReg[R_G0])); - a_jmp_cond(list,cmp_op,l); - cg.free_scratch_reg(exprasmlist,TempReg); + procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister); + var + RetAddrReg:TRegister; + begin + retaddrreg.enum:=R_INTREGISTER; + retaddrreg.Number:=NR_O7; + list.concat(taicpu.op_reg_reg(A_JMPL,reg,RetAddrReg)); + { why only on Sparc/Linux? Doesn't use other implementations use the delay slot? (FK) } + if target_info.system=system_sparc_linux then + list.concat(taicpu.op_none(A_NOP)); + include(current_procinfo.flags,pi_do_call); end; - procedure TCgSparc.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:TAsmLabel); - var - ai:TAiCpu; - begin - ai:=TAiCpu.Op_sym(A_BA,S_NO,l); - ai.SetCondition(TOpCmp2AsmCond[cond]); - with List do - begin - Concat(ai); - Concat(TAiCpu.Op_none(A_NOP)); + {********************** load instructions ********************} + + procedure TCgSparc.a_load_const_reg(list : TAasmOutput;size : TCGSize;a : aword;reg : TRegister); + var + r:Tregister; + begin + r.enum:=R_INTREGISTER; + r.number:=NR_G0; + { we don't use the set instruction here because it could be evalutated to two + instructions which would cause problems with the delay slot (FK) } + { sethi allows to set the upper 22 bit, so we'll take full advantage of it } + if (a and aword($3ff))=0 then + list.concat(taicpu.op_const_reg(A_SETHI,(a and aword($fffffc00)) shr 10,reg)) + else if (a and aword($ffffe000))=0 then + list.concat(taicpu.op_reg_const_reg(A_OR,r,a,reg)) + else + begin + list.concat(taicpu.op_const_reg(A_SETHI,(a and aword($ffffe000)) shr 13,reg)); + list.concat(taicpu.op_reg_const_reg(A_OR,r,a and $1fff,reg)); + end; + end; + + + procedure TCgSparc.a_load_const_ref(list : TAasmOutput;size : tcgsize;a : aword;const ref : TReference); + var + r:Tregister; + begin + inherited a_load_const_ref(list,size,a,ref); + r.enum:=R_INTREGISTER; + r.number:=NR_G0; + if a=0 then + a_load_reg_ref(list,size,r,ref) + else + inherited a_load_const_ref(list,size,a,ref); + end; + + + procedure TCgSparc.a_load_reg_ref(list:TAasmOutput;size:TCGSize;reg:tregister;const Ref:TReference); + var + op:tasmop; + begin + case size of + { signed integer registers } + OS_8, + OS_S8: + Op:=A_STB; + OS_16, + OS_S16: + Op:=A_STH; + OS_32, + OS_S32: + Op:=A_ST; + else + InternalError(2002122100); end; - end; + list.concat(taicpu.op_reg_ref(op,reg,ref)); + end; - procedure TCgSparc.a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel); - var - ai:taicpu; - begin - ai := Taicpu.op_sym(A_BA,S_NO,l); - ai.SetCondition(flags_to_cond(f)); - with List do - begin - Concat(ai); - Concat(TAiCpu.Op_none(A_NOP)); + procedure TCgSparc.a_load_ref_reg(list:TAasmOutput;size:TCgSize;const ref:TReference;reg:tregister); + var + op:tasmop; + begin + case size of + { signed integer registers } + OS_S8: + Op:=A_LDSB;{Load Signed Byte} + OS_S16: + Op:=A_LDSH;{Load Signed Halfword} + OS_8: + Op:=A_LDUB;{Load Unsigned Bye} + OS_16: + Op:=A_LDUH;{Load Unsigned Halfword} + OS_S32, + OS_32: + Op:=A_LD;{Load Word} + else + InternalError(2002122100); end; - end; + list.concat(taicpu.op_ref_reg(op,ref,reg)); + end; - procedure TCgSparc.g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister); - var - ai:taicpu; - r,hreg:tregister; - begin - r.enum:=R_PSR; - hreg := rg.makeregsize(reg,OS_8); - ai:=Taicpu.Op_reg_reg(A_RDPSR,r,hreg); - ai.SetCondition(flags_to_cond(f)); - with List do - begin - Concat(ai); - Concat(TAiCpu.Op_none(A_NOP)); + procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister); + var + r : Tregister; + begin + if(reg1.enum<>R_INTREGISTER)or(reg1.number=NR_NO) then + InternalError(200303101); + if(reg2.enum<>R_INTREGISTER)or(reg2.number=NR_NO) then + InternalError(200303102); + r.enum:=R_INTREGISTER; + r.Number:=NR_G0; + if (reg1.Number<>reg2.Number) or + (tcgsize2size[tosize] fromsize) and + not(fromsize in [OS_32,OS_S32]) + ) then + begin + case tosize of + OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32: + list.concat(taicpu.op_reg_reg_reg(A_OR,r,reg1,reg2)); + else + internalerror(2002090901); + end; + end; + end; + + + procedure TCgSparc.a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister); + + begin + { if NOT (reg1 IN [R_F0..R_F31]) then + begin + list.concat(taicpu.op_reg(A_NONE,S_NO, + trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset))); + inc(trgcpu(rg).fpuvaroffset); + end; + if NOT (reg2 IN [R_F0..R_F31]) then + begin + list.concat(taicpu.op_reg(A_JMPL,S_NO, + trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset))); + dec(trgcpu(rg).fpuvaroffset); + end;} + end; + + + procedure TCgSparc.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister); + + begin +// floatload(list,size,ref); + { if (reg <> R_ST) then + a_loadfpu_reg_reg(list,R_ST,reg);} + end; + + + procedure TCgSparc.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference); + const + FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp = + { indexed? updating?} + (((A_STF,A_STF),(A_STF,A_STF)), + ((A_STDF,A_STDF),(A_STDF,A_STDF))); + var + ref2: treference; + freereg: boolean; + begin + if not(size in [OS_F32,OS_F64]) + then + internalerror(200201122); + { ref2:=ref; + freereg:=fixref(list,ref2); + op:=fpustoreinstr[size,ref2.index.enum <> R_NO,false]; + a_load_store(list,op,reg,ref2); + if freereg + then + cg.free_scratch_reg(list,ref2.base);} + end; + + + procedure TCgSparc.a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister); + begin + list.concat(taicpu.op_reg_const_reg(TOpCG2AsmOp[op],reg,a,reg)); + end; + + + procedure TCgSparc.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister); + begin + list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst)); + end; + + + procedure TCgSparc.a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;const ref:TReference;reg:TRegister); + begin + list.concat(taicpu.op_reg_ref_reg(TOpCG2AsmOp[op],reg,ref,reg)); + end; + + + procedure TCgSparc.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister); + var + tmpref:TReference; + power:LongInt; + begin + if not (size in [OS_32,OS_S32]) then + begin + inherited a_op_const_reg_reg(list,op,size,a,src,dst); + exit; + end; + { if we get here, we have to do a 32 bit calculation, guaranteed } + Case Op of + OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR, + OP_SAR: + { can't do anything special for these } + inherited a_op_const_reg_reg(list,op,size,a,src,dst); + OP_IMUL: + begin + if not(cs_check_overflow in aktlocalswitches) and + ispowerof2(a,power) then + { can be done with a shift } + inherited a_op_const_reg_reg(list,op,size,a,src,dst); + list.concat(taicpu.op_reg_const_reg(A_SMUL,src,a,dst)); + end; + OP_ADD, OP_SUB: + if (a = 0) then + a_load_reg_reg(list,size,size,src,dst) + else + begin + reference_reset(tmpref); + tmpref.base := src; + tmpref.offset := LongInt(a); + if op = OP_SUB then + tmpref.offset := -tmpref.offset; + list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst)); + end + else + internalerror(200112302); end; - if hreg.enum<>reg.enum then - a_load_reg_reg(list,OS_32,OS_32,hreg,reg); - end; + end; + + procedure TCgSparc.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg; + size:tcgsize;src1, src2, dst:tregister); + var + tmpref:TReference; + begin + if not (size in [OS_32,OS_S32]) then + begin + inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst); + exit; + end; + { if we get here, we have to do a 32 bit calculation, guaranteed } + Case Op of + OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR, + OP_SAR,OP_SUB,OP_NOT,OP_NEG: + { can't do anything special for these } + inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst); + OP_IMUL: + list.concat(taicpu.op_reg_reg_reg(A_SMUL,src1,src2,dst)); + OP_ADD: + begin + reference_reset(tmpref); + tmpref.base := src1; + tmpref.index := src2; + list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst)); + end + else internalerror(200112303); + end; + end; - procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const p:TNode); - var - hl:TAsmLabel; - r:Tregister; - begin - r.enum:=R_NONE; - if not(cs_check_overflow in aktlocalswitches) then - exit; - objectlibrary.getlabel(hl); - if not((p.resulttype.def.deftype=pointerdef) or - ((p.resulttype.def.deftype=orddef) and - (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar, - bool8bit,bool16bit,bool32bit]))) - then - begin - list.concat(taicpu.op_reg(A_NONE,r)); - a_jmp_always(list,hl) - end - else - a_jmp_cond(list,OC_NONE,hl); + {*************** compare instructructions ****************} + + procedure TCgSparc.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel); + begin + if(a=0) + then + list.concat(taicpu.op_reg_reg(A_CMP,reg,reg)) + else + list.concat(taicpu.op_reg_const(A_CMP,reg,a)); + a_jmp_cond(list,cmp_op,l); + end; + + + procedure TCgSparc.a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;const ref:TReference;l:tasmlabel); + var + cReg,rReg:TRegister; + begin + cReg:=get_scratch_reg_int(List,size); + rReg:=get_scratch_reg_int(List,size); + a_load_const_reg(List,OS_32,a,cReg); + a_load_ref_reg(List,OS_32,ref,rReg); + a_cmp_reg_reg_label(list,OS_32,cmp_op,rReg,cReg,l); + free_scratch_reg(List,cReg); + free_scratch_reg(List,rReg); + end; + + + procedure TCgSparc.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel); + begin + List.Concat(taicpu.op_reg_reg(A_CMP,reg1,reg2)); + a_jmp_cond(list,cmp_op,l); + end; + + + procedure TCgSparc.a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;const ref:TReference;reg:tregister;l:tasmlabel); + var + zeroreg,TempReg:TRegister; + begin + TempReg:=cg.get_scratch_reg_int(List,size); + a_load_ref_reg(list,OS_32,Ref,TempReg); + zeroreg.enum:=R_INTREGISTER; + zeroreg.number:=NR_G0; + list.concat(taicpu.op_reg_reg_reg(A_SUBcc,TempReg,Reg,zeroreg)); + a_jmp_cond(list,cmp_op,l); + cg.free_scratch_reg(exprasmlist,TempReg); + end; + + + procedure TCgSparc.a_jmp_always(List:TAasmOutput;l:TAsmLabel); + begin + List.Concat(TAiCpu.op_sym(A_BA,objectlibrary.newasmsymbol(l.name))); + end; + + + procedure TCgSparc.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:TAsmLabel); + var + ai:TAiCpu; + begin + ai:=TAiCpu.Op_sym(A_BA,l); + ai.SetCondition(TOpCmp2AsmCond[cond]); + list.Concat(ai); + list.Concat(TAiCpu.Op_none(A_NOP)); + end; + + + procedure TCgSparc.a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel); + var + ai:taicpu; + begin + ai := Taicpu.op_sym(A_BA,l); + ai.SetCondition(flags_to_cond(f)); + list.Concat(ai); + list.Concat(TAiCpu.Op_none(A_NOP)); + end; + + + procedure TCgSparc.g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister); + var + ai:taicpu; + r,hreg:tregister; + begin + r.enum:=R_PSR; + ai:=Taicpu.Op_reg_reg(A_RDPSR,r,reg); + ai.SetCondition(flags_to_cond(f)); + list.Concat(ai); + list.Concat(TAiCpu.Op_none(A_NOP)); + end; + + + procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const p:TNode); + var + hl:TAsmLabel; + begin + if not(cs_check_overflow in aktlocalswitches) then + exit; + objectlibrary.getlabel(hl); + if not((p.resulttype.def.deftype=pointerdef) or + ((p.resulttype.def.deftype=orddef) and + (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar, + bool8bit,bool16bit,bool32bit]))) then + begin +{$warning TODO Overflow check} + a_jmp_always(list,hl) + end + else + a_jmp_cond(list,OC_NONE,hl); a_call_name(list,'FPC_OVERFLOW'); a_label(list,hl); end; + { *********** entry/exit code and address loading ************ } procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt); @@ -986,7 +666,7 @@ procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1, after execution of that instruction is the called function stack pointer} r.enum:=R_INTREGISTER; r.number:=NR_STACK_POINTER_REG; - list.concat(Taicpu.Op_reg_const_reg(A_SAVE,r,-LocalSize,r)); + list.concat(Taicpu.Op_reg_const_reg(A_SAVE,r,aword(-LocalSize),r)); end; @@ -1122,7 +802,7 @@ procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1, end; - procedure TCg64Sparc.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64); + procedure TCg64Sparc.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;const ref:TReference;reg:TRegister64); var op1,op2:TAsmOp; tempref:TReference; @@ -1199,80 +879,76 @@ procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1, end; - { ************* concatcopy ************ } - procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean); - var - countreg: TRegister; - src, dst: TReference; - lab: tasmlabel; - count, count2: aword; - orgsrc, orgdst: boolean; - r:Tregister; - begin - {$ifdef extdebug} - if len > high(longint) - then - internalerror(2002072704); - {$endif extdebug} - { make sure short loads are handled as optimally as possible } - if not loadref - then - if(len <= 8)and(byte(len) in [1,2,4,8]) - then - begin - if len < 8 - then - begin - a_load_ref_ref(list,int_cgsize(len),source,dest); - if delsource - then - reference_release(list,source); - end - else - begin - r.enum:=R_F0; - a_reg_alloc(list,r); - a_loadfpu_ref_reg(list,OS_F64,source,r); - if delsource - then - reference_release(list,source); - a_loadfpu_reg_ref(list,OS_F64,r,dest); - a_reg_dealloc(list,r); - end; - exit; + { ************* concatcopy ************ } + + procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean); + var + countreg: TRegister; + src, dst: TReference; + lab: tasmlabel; + count, count2: aword; + orgsrc, orgdst: boolean; + r:Tregister; + begin + if len > high(longint) then + internalerror(2002072704); + { make sure short loads are handled as optimally as possible } + if not loadref then + begin + if (len <= 8) and (byte(len) in [1,2,4,8]) then + begin + if len < 8 then + begin + a_load_ref_ref(list,int_cgsize(len),source,dest); + if delsource then + reference_release(list,source); + end + else + begin + r.enum:=R_F0; + a_reg_alloc(list,r); + a_loadfpu_ref_reg(list,OS_F64,source,r); + if delsource then + reference_release(list,source); + a_loadfpu_reg_ref(list,OS_F64,r,dest); + a_reg_dealloc(list,r); + end; + exit; + end; end; reference_reset(src); reference_reset(dst); { load the address of source into src.base } - if loadref - then + if loadref then begin src.base := get_scratch_reg_address(list); a_load_ref_reg(list,OS_32,source,src.base); orgsrc := false; end - else if not issimpleref(source) or - ((source.index.enum<>R_NO)and - ((source.offset+longint(len))>high(smallint))) - then - begin - src.base := get_scratch_reg_address(list); - a_loadaddr_ref_reg(list,source,src.base); - orgsrc := false; - end + else + if not issimpleref(source) or + ( + (source.index.number<>NR_NO) and + ((source.offset+longint(len))>high(smallint)) + ) then + begin + src.base := get_scratch_reg_address(list); + a_loadaddr_ref_reg(list,source,src.base); + orgsrc := false; + end else begin src := source; orgsrc := true; end; - if not orgsrc and delsource - then + if not orgsrc and delsource then reference_release(list,source); { load the address of dest into dst.base } if not issimpleref(dest) or - ((dest.index.enum <> R_NO) and - ((dest.offset + longint(len)) > high(smallint))) - then + ( + (dest.index.number<>NR_NO) and + ((dest.offset + longint(len)) > high(smallint)) + ) then begin dst.base := get_scratch_reg_address(list); a_loadaddr_ref_reg(list,dest,dst.base); @@ -1283,10 +959,9 @@ procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1, dst := dest; orgdst := true; end; - count:=len and 7;{count:=len div 8} - if count>4 - then - { generate a loop } + { generate a loop } + count:=len div 8; + if count>4 then begin { the offsets are zero after the a_loadaddress_ref_reg and just } { have to be set to 8. I put an Inc there so debugging may be } @@ -1312,198 +987,78 @@ procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1, a_reg_dealloc(list,r); len := len mod 8; end; - count:=len and 7; - if count>0 - then - { unrolled loop } - begin - r.enum:=R_F0; - a_reg_alloc(list,r); - for count2 := 1 to count do - begin - a_loadfpu_ref_reg(list,OS_F64,src,r); - a_loadfpu_reg_ref(list,OS_F64,r,dst); - inc(src.offset,8); - inc(dst.offset,8); - end; - a_reg_dealloc(list,r); - len := len mod 8; - end; - - if (len and 4) <> 0 then - begin - r.enum:=R_O0; - a_reg_alloc(list,r); - a_load_ref_reg(list,OS_32,src,r); - a_load_reg_ref(list,OS_32,r,dst); - inc(src.offset,4); - inc(dst.offset,4); - a_reg_dealloc(list,r); - end; - { copy the leftovers } - if (len and 2) <> 0 then - begin - r.enum:=R_O0; - a_reg_alloc(list,r); - a_load_ref_reg(list,OS_16,src,r); - a_load_reg_ref(list,OS_16,r,dst); - inc(src.offset,2); - inc(dst.offset,2); - a_reg_dealloc(list,r); - end; - if (len and 1) <> 0 then - begin - r.enum:=R_O0; - a_reg_alloc(list,r); - a_load_ref_reg(list,OS_8,src,r); - a_load_reg_ref(list,OS_8,r,dst); - a_reg_dealloc(list,r); - end; - if orgsrc then - begin - if delsource then - reference_release(list,source); - end - else - free_scratch_reg(list,src.base); - if not orgdst then - free_scratch_reg(list,dst.base); - end; - function TCgSparc.reg_cgsize(CONST reg:tregister):tcgsize; - begin - result:=OS_32; - end; - - - {***************** This is private property, keep out! :) *****************} - function TCgSparc.IsSimpleRef(const ref:treference):boolean; - begin - if(ref.base.enum=R_NONE)and(ref.index.enum <> R_NO) - then - InternalError(2002100804); - result :=not(assigned(ref.symbol))and - (((ref.index.enum = R_NO) and - (ref.offset >= low(smallint)) and - (ref.offset <= high(smallint))) or - ((ref.index.enum <> R_NO) and - (ref.offset = 0))); - end; - procedure TCgSparc.sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize); - begin - case s2 of - S_B: - if S1 in [OS_8,OS_S8] - then - s3 := S_B - else - internalerror(200109221); - S_W: - case s1 of - OS_8,OS_S8: - s3 := S_B; - OS_16,OS_S16: - s3 := S_H; - else - internalerror(200109222); + { unrolled loop } + count:=len and 7; + if count>0 then + begin + r.enum:=R_F0; + a_reg_alloc(list,r); + for count2 := 1 to count do + begin + a_loadfpu_ref_reg(list,OS_F64,src,r); + a_loadfpu_reg_ref(list,OS_F64,r,dst); + inc(src.offset,8); + inc(dst.offset,8); + end; + a_reg_dealloc(list,r); + len := len mod 8; end; - S_SW: - case s1 of - OS_8,OS_S8: - s3 := S_B; - OS_16,OS_S16: - s3 := S_H; - OS_32,OS_S32: - s3 := S_W; - else - internalerror(200109223); + if (len and 4) <> 0 then + begin + r.enum:=R_INTREGISTER; + r.number:=NR_O0; + a_reg_alloc(list,r); + a_load_ref_reg(list,OS_32,src,r); + a_load_reg_ref(list,OS_32,r,dst); + inc(src.offset,4); + inc(dst.offset,4); + a_reg_dealloc(list,r); end; - else internalerror(200109227); + { copy the leftovers } + if (len and 2) <> 0 then + begin + r.enum:=R_INTREGISTER; + r.number:=NR_O0; + a_reg_alloc(list,r); + a_load_ref_reg(list,OS_16,src,r); + a_load_reg_ref(list,OS_16,r,dst); + inc(src.offset,2); + inc(dst.offset,2); + a_reg_dealloc(list,r); + end; + if (len and 1) <> 0 then + begin + r.enum:=R_INTREGISTER; + r.number:=NR_O0; + a_reg_alloc(list,r); + a_load_ref_reg(list,OS_8,src,r); + a_load_reg_ref(list,OS_8,r,dst); + a_reg_dealloc(list,r); + end; + if orgsrc then + begin + if delsource then + reference_release(list,source); + end + else + free_scratch_reg(list,src.base); + if not orgdst then + free_scratch_reg(list,dst.base); end; - if s3 in [S_B,S_W,S_SW] - then - op := A_LD - { else if s3=S_DW - then - op:=A_LDD - else if s3 in [OS_8,OS_16,OS_32] - then - op := A_NONE} - else - op := A_NONE; - end; - procedure TCgSparc.floatloadops(t:tcgsize;VAR op:tasmop;VAR s:topsize); - BEGIN - (* case t of - OS_F32:begin - op:=A_FLD; - s:=S_FS; - end; - OS_F64:begin - op:=A_FLD; - { ???? } - s:=S_FL; - end; - OS_F80:begin - op:=A_FLD; - s:=S_FX; - end; - OS_C64:begin - op:=A_FILD; - s:=S_IQ; - end; - else internalerror(17); - end;*) - END; - procedure TCgSparc.floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference); - VAR - op:tasmop; - s:topsize; - BEGIN - floatloadops(t,op,s); - list.concat(Taicpu.Op_ref(op,ref)); - { inc(trgcpu(rg).fpuvaroffset);} - END; - procedure TCgSparc.floatstoreops(t:tcgsize;var op:tasmop;var s:topsize); - BEGIN - { case t of - OS_F32:begin - op:=A_FSTP; - s:=S_FS; - end; - OS_F64:begin - op:=A_FSTP; - s:=S_FL; - end; - OS_F80:begin - op:=A_FSTP; - s:=S_FX; - end; - OS_C64:begin - op:=A_FISTP; - s:=S_IQ; - end; - else - internalerror(17); - end;} - end; - procedure TCgSparc.floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference); - VAR - op:tasmop; - s:topsize; - BEGIN - floatstoreops(t,op,s); - list.concat(Taicpu.Op_ref(op,ref)); - { dec(trgcpu(rg).fpuvaroffset);} - END; - begin - cg:=TCgSparc.Create; - cg64:=TCg64Sparc.Create; - end. +begin + cg:=TCgSparc.Create; + cg64:=TCg64Sparc.Create; +end. { $Log$ - Revision 1.52 2003-05-28 23:18:31 florian + Revision 1.53 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.52 2003/05/28 23:18:31 florian * started to fix and clean up the sparc port Revision 1.51 2003/05/26 22:04:57 mazen @@ -1602,7 +1157,7 @@ procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1, * made operator search faster by walking the list only once Revision 1.24 2002/11/17 17:49:09 mazen - + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one + + return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one Revision 1.23 2002/11/10 19:07:46 mazen * SPARC calling mechanism almost OK (as in GCC./mppcsparc ) diff --git a/compiler/sparc/cpubase.pas b/compiler/sparc/cpubase.pas index 1888496849..b700bd27a1 100644 --- a/compiler/sparc/cpubase.pas +++ b/compiler/sparc/cpubase.pas @@ -1,8 +1,8 @@ -{****************************************************************************** +{ $Id$ - Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman + Copyright (c) 1998-2002 by Florian Klaempfl - Contains the base types for the Scalable Processor ARChitecture (SPARC) + Contains the base types for the SPARC This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,255 +17,356 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ****************************************************************************} -unit cpuBase; + + **************************************************************************** +} +{ This Unit contains the base types for the PowerPC +} +unit cpubase; {$i fpcdefs.inc} interface - uses - globals,cutils,cclasses,aasmbase,cpuinfo,cginfo; +uses + strings,cutils,cclasses,aasmbase,cpuinfo,cginfo; + -const - {Size of the instruction table converted by nasmconv.pas} - maxinfolen=8; - {Defines the default address size for a processor} - OS_ADDR=OS_32; - {the natural int size for a processor} - OS_INT=OS_32; - {the maximum float size for a processor} - OS_FLOAT=OS_F64; - {the size of a vector register for a processor} - OS_VECTOR=OS_M64; -type -{$WARNING CPU32 opcodes do not fully include the Ultra SPRAC instruction set.} - { don't change the order of these opcodes! } - TAsmOp=({$INCLUDE opcode.inc}); - op2strtable=array[TAsmOp]OF STRING[11]; -CONST - FirstOp=Low(TAsmOp); - LastOp=High(TAsmOp); - std_op2str:op2strtable=({$INCLUDE strinst.inc}); {***************************************************************************** - Operand Sizes + Assembler Opcodes *****************************************************************************} -type - TOpSize=(S_NO, - S_B,{Byte} - S_H,{Half word} - S_W,{Word} - S_L:=S_W, - S_D,{Double Word} - S_Q,{Quad word} - S_IQ:=S_Q, - S_SB,{Signed byte} - S_SH,{Signed half word} - S_SW,{Signed word} - S_SD,{Signed double word} - S_SQ,{Signed quad word} - S_FS,{Float single word} - S_FX:=S_FS, - S_FD,{Float double word} - S_FQ,{Float quad word} - S_NEAR, - S_FAR, - S_SHORT); -{*****************************************************************************} -{ Conditions } -{*****************************************************************************} -type - TAsmCond=(C_None, - C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE, - C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP, - C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z - ); -CONST - cond2str:array[TAsmCond] of string[3]=('', - 'a','ae','b','be','c','e','g','ge','l','le','na','nae', - 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np', - 'ns','nz','o','p','pe','po','s','z' - ); - inverse_cond:array[TAsmCond] of TAsmCond=(C_None, - C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE, - C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P, - C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ - ); -CONST - CondAsmOps=3; - CondAsmOp:array[0..CondAsmOps-1] of TAsmOp=(A_FCMPd, A_JMPL, A_FCMPs); - CondAsmOpStr:array[0..CondAsmOps-1] of string[7]=('FCMPd','JMPL','FCMPs'); -{*****************************************************************************} -{ Registers } -{*****************************************************************************} -type - { enumeration for registers, don't change the order } - { it's used by the register size conversions } - TCpuRegister=({$INCLUDE cpuregs.inc}); - TOldRegister=TCpuRegister; - Tnewregister=word; - Tsuperregister=byte; - Tsubregister=byte; - Tregister=record - enum:TCpuRegister; - number:Tnewregister; - end; - TRegister64=PACKED RECORD - {A type to store register locations for 64 Bit values.} - RegLo,RegHi:TRegister; - end; - treg64=tregister64;{alias for compact code} - TRegisterSet=SET OF TCpuRegister; - Tsupregset=set of Tsuperregister; -const - R_NO=R_NONE; - firstreg = Succ(R_NONE); - lastreg = Pred(R_INTREGISTER); -{General registers.} -const - NR_NONE=$0000; - NR_NO=NR_NONE; - NR_G0=$0001; - NR_G1=$0002; - NR_G2=$0003; - NR_G3=$0004; - NR_G4=$0005; - NR_G5=$0006; - NR_G6=$0007; - NR_G7=$0008; - NR_O0=$0100; - NR_O1=$0200; - NR_O2=$0300; - NR_O3=$0400; - NR_O4=$0500; - NR_O5=$0600; - NR_O6=$0700; - NR_O7=$0800; - NR_L0=$0900; - NR_L1=$0A00; - NR_L2=$0B00; - NR_L3=$0C00; - NR_L4=$0D00; - NR_L5=$0E00; - NR_L6=$0F00; - NR_L7=$1000; - NR_I0=$1100; - NR_I1=$1200; - NR_I2=$1300; - NR_I3=$1400; - NR_I4=$1500; - NR_I5=$1600; - NR_I6=$1700; - NR_I7=$1800; -{Floating point} - NR_F0=$2000; - NR_F1=$2000; - NR_F2=$2000; - NR_F3=$2000; - NR_F4=$2000; - NR_F5=$2000; - NR_F6=$2000; - NR_F7=$2000; - NR_F8=$2000; - NR_F9=$2000; - NR_F10=$2000; - NR_F11=$2000; - NR_F12=$2000; - NR_F13=$2000; - NR_F14=$2000; - NR_F15=$2000; - NR_F16=$2000; - NR_F17=$2000; - NR_F18=$2000; - NR_F19=$2000; - NR_F20=$2000; - NR_F21=$2000; - NR_F22=$2000; - NR_F23=$2000; - NR_F24=$2000; - NR_F25=$2000; - NR_F26=$2000; - NR_F27=$2000; - NR_F28=$2000; - NR_F29=$2000; - NR_F30=$2000; - NR_F31=$2000; -{Coprocessor point} - NR_C0=$3000; - NR_C1=$3000; - NR_C2=$3000; - NR_C3=$3000; - NR_C4=$3000; - NR_C5=$3000; - NR_C6=$3000; - NR_C7=$3000; - NR_C8=$3000; - NR_C9=$3000; - NR_C10=$3000; - NR_C11=$3000; - NR_C12=$3000; - NR_C13=$3000; - NR_C14=$3000; - NR_C15=$3000; - NR_C16=$3000; - NR_C17=$3000; - NR_C18=$3000; - NR_C19=$3000; - NR_C20=$3000; - NR_C21=$3000; - NR_C22=$3000; - NR_C23=$3000; - NR_C24=$3000; - NR_C25=$3000; - NR_C26=$3000; - NR_C27=$3000; - NR_C28=$3000; - NR_C29=$3000; - NR_C30=$3000; - NR_C31=$3000; -{ASR} - NR_ASR0=$4000; - NR_ASR1=$4000; - NR_ASR2=$4000; - NR_ASR3=$4000; - NR_ASR4=$4000; - NR_ASR5=$4000; - NR_ASR6=$4000; - NR_ASR7=$4000; - NR_ASR8=$4000; - NR_ASR9=$4000; - NR_ASR10=$4000; - NR_ASR11=$4000; - NR_ASR12=$4000; - NR_ASR13=$4000; - NR_ASR14=$4000; - NR_ASR15=$4000; - NR_ASR16=$4000; - NR_ASR17=$4000; - NR_ASR18=$4000; - NR_ASR19=$4000; - NR_ASR20=$4000; - NR_ASR21=$4000; - NR_ASR22=$4000; - NR_ASR23=$4000; - NR_ASR24=$4000; - NR_ASR25=$4000; - NR_ASR26=$4000; - NR_ASR27=$4000; - NR_ASR28=$4000; - NR_ASR29=$4000; - NR_ASR30=$4000; - NR_ASR31=$4000; -{Floating point status/"front of queue" registers} - NR_FSR=$5000; - NR_FQ=$5001; { was $50001, probably typo (FK) } - NR_CSR=$5000; - NR_CQ=$5000; - NR_PSR=$5000; - NR_TBR=$5000; - NR_WIM=$5000; - NR_Y=$5000; + type +{$WARNING CPU32 opcodes do not fully include the Ultra SPRAC instruction set.} + { don't change the order of these opcodes! } + TAsmOp=({$INCLUDE opcode.inc}); + + {# This should define the array of instructions as string } + op2strtable=array[tasmop] of string[11]; + + Const + {# First value of opcode enumeration } + firstop = low(tasmop); + {# Last value of opcode enumeration } + lastop = high(tasmop); + + std_op2str:op2strtable=({$INCLUDE strinst.inc}); + +{***************************************************************************** + Registers +*****************************************************************************} + + type + TCpuRegister=( + R_NO + {General purpose global registers} + ,R_G0{This register is usually set to zero and used as a scratch register} + ,R_G1,R_G2,R_G3,R_G4,R_G5,R_G6,R_G7 + {General purpose out registers} + ,R_O0,R_O1,R_O2,R_O3,R_O4,R_O5,R_O6 + ,R_O7{This register is used to save the address of the last CALL instruction} + {General purpose local registers} + ,R_L0 + ,R_L1{This register is used to save the Program Counter (PC) after a Trap} + ,R_L2{This register is used to save the Program Counter (nPC) after a Trap} + ,R_L3,R_L4,R_L5,R_L6,R_L7 + {General purpose in registers} + ,R_I0,R_I1,R_I2,R_I3,R_I4,R_I5,R_I6,R_I7 + {Floating point registers} + ,R_F0,R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7 + ,R_F8,R_F9,R_F10,R_F11,R_F12,R_F13,R_F14,R_F15 + ,R_F16,R_F17,R_F18,R_F19,R_F20,R_F21,R_F22,R_F23 + ,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,R_F30,R_F31 + {Floating point status/"front of queue" registers} + ,R_FSR,R_FQ + {Coprocessor registers} + ,R_C0,R_C1,R_C2,R_C3,R_C4,R_C5,R_C6,R_C7 + ,R_C8,R_C9,R_C10,R_C11,R_C12,R_C13,R_C14,R_C15 + ,R_C16,R_C17,R_C18,R_C19,R_C20,R_C21,R_C22,R_C23 + ,R_C24,R_C25,R_C26,R_C27,R_C28,R_C29,R_C30,R_C31 + {Coprocessor status/queue registers} + ,R_CSR + ,R_CQ + {Integer Unit control & status registers} + ,R_PSR{Processor Status Register : informs upon the program status} + ,R_TBR{Trap Base Register : saves the Trap vactor base address} + ,R_WIM{Window Invalid Mask : } + ,R_Y{Multiply/Devide Register : } + {Ancillary State Registers : these are implementation dependent registers and + thus, are not specified by the SPARC Reference Manual. I did choose the SUN's + implementation according to the Assembler Refernce Manual.(MN)} + ,R_ASR0,R_ASR1,R_ASR2,R_ASR3,R_ASR4,R_ASR5,R_ASR6,R_ASR7 + ,R_ASR8,R_ASR9,R_ASR10,R_ASR11,R_ASR12,R_ASR13,R_ASR14,R_ASR15 + ,R_ASR16,R_ASR17,R_ASR18,R_ASR19,R_ASR20,R_ASR21,R_ASR22,R_ASR23 + ,R_ASR24,R_ASR25,R_ASR26,R_ASR27,R_ASR28,R_ASR29,R_ASR30,R_ASR31 + {The following registers are just used with the new register allocator} + ,R_INTREGISTER,R_FLOATREGISTER,R_MMXREGISTER,R_KNIREGISTER + ); + + TOldRegister=TCpuRegister; + + Tnewregister=word; + Tsuperregister=byte; + Tsubregister=byte; + + Tregister=record + enum:Toldregister; + number:Tnewregister; + end; + + {# Set type definition for registers } + tregisterset = set of Toldregister; + Tsupregset=set of Tsuperregister; + + { A type to store register locations for 64 Bit values. } + tregister64 = packed record + reglo,reghi : tregister; + end; + + { alias for compact code } + treg64 = tregister64; + + + Const + {# First register in the tregister enumeration } + firstreg = low(Toldregister); + {# Last register in the tregister enumeration } + lastreg = R_ASR31; + type + {# Type definition for the array of string of register nnames } + treg2strtable = array[firstreg..lastreg] of string[7]; + + const + std_reg2str:treg2strtable=( + '', + {general purpose global registers} + '%g0','%g1','%g2','%g3','%g4','%g5','%g6','%g7', + {general purpose out registers} + '%o0','%o1','%o2','%o3','%o4','%o5','%o6','%o7', + {general purpose local registers} + '%l0','%l1','%l2','%l3','%l4','%l5','%l6','%l7', + {general purpose in registers} + '%i0','%i1','%i2','%i3','%i4','%i5','%i6','%i7', + {floating point registers} + '%f0','%f1','%f2','%f3','%f4','%f5','%f6','%f7', + '%f8','%f9','%f10','%f11','%f12','%f13','%f14','%f15', + '%f16','%f17','%f18','%f19','%f20','%f21','%f22','%f23', + '%f24','%f25','%f26','%f27','%f28','%f29','%f30','%f31', + {floating point status/"front of queue" registers} + '%fSR','%fQ', + {coprocessor registers} + '%c0','%c1','%c2','%c3','%c4','%c5','%c6','%c7', + '%c8','%c9','%c10','%c11','%c12','%c13','%c14','%c15', + '%c16','%c17','%c18','%c19','%c20','%c21','%c22','%c23', + '%c24','%c25','%c26','%c27','%c28','%c29','%c30','%c31', + {coprocessor status/queue registers} + '%csr','%cq', + {"Program status"/"Trap vactor base address register"/"Window invalid mask"/Y registers} + '%psr','%tbr','%wim','%y', + {Ancillary state registers} + '%asr0','%asr1','%asr2','%asr3','%asr4','%asr5','%asr6','%asr7', + '%asr8','%asr9','%asr10','%asr11','%asr12','%asr13','%asr14','%asr15', + '%asr16','%asr17','%asr18','%asr19','%asr20','%asr21','%asr22','%asr23', + '%asr24','%asr25','%asr26','%asr27','%asr28','%asr29','%asr30','%asr31' + ); + + {New register coding:} + + {Special registers:} + const + NR_NO=$0000; {Invalid register} + + {Normal registers:} + + {General purpose registers:} + NR_G0=$0100; + NR_G1=$0200; + NR_G2=$0300; + NR_G3=$0400; + NR_G4=$0500; + NR_G5=$0600; + NR_G6=$0700; + NR_G7=$0800; + NR_O0=$0900; + NR_O1=$0a00; + NR_O2=$0b00; + NR_O3=$0c00; + NR_O4=$0d00; + NR_O5=$0e00; + NR_O6=$0f00; + NR_O7=$1000; + NR_L0=$1100; + NR_L1=$1200; + NR_L2=$1300; + NR_L3=$1400; + NR_L4=$1500; + NR_L5=$1600; + NR_L6=$1700; + NR_L7=$1800; + NR_I0=$1900; + NR_I1=$1A00; + NR_I2=$1B00; + NR_I3=$1C00; + NR_I4=$1D00; + NR_I5=$1E00; + NR_I6=$1F00; + NR_I7=$2000; +{$ifdef dummy} + { Floating point } + NR_F0=$2000; + NR_F1=$2000; + NR_F2=$2000; + NR_F3=$2000; + NR_F4=$2000; + NR_F5=$2000; + NR_F6=$2000; + NR_F7=$2000; + NR_F8=$2000; + NR_F9=$2000; + NR_F10=$2000; + NR_F11=$2000; + NR_F12=$2000; + NR_F13=$2000; + NR_F14=$2000; + NR_F15=$2000; + NR_F16=$2000; + NR_F17=$2000; + NR_F18=$2000; + NR_F19=$2000; + NR_F20=$2000; + NR_F21=$2000; + NR_F22=$2000; + NR_F23=$2000; + NR_F24=$2000; + NR_F25=$2000; + NR_F26=$2000; + NR_F27=$2000; + NR_F28=$2000; + NR_F29=$2000; + NR_F30=$2000; + NR_F31=$2000; + { Coprocessor point } + NR_C0=$3000; + NR_C1=$3000; + NR_C2=$3000; + NR_C3=$3000; + NR_C4=$3000; + NR_C5=$3000; + NR_C6=$3000; + NR_C7=$3000; + NR_C8=$3000; + NR_C9=$3000; + NR_C10=$3000; + NR_C11=$3000; + NR_C12=$3000; + NR_C13=$3000; + NR_C14=$3000; + NR_C15=$3000; + NR_C16=$3000; + NR_C17=$3000; + NR_C18=$3000; + NR_C19=$3000; + NR_C20=$3000; + NR_C21=$3000; + NR_C22=$3000; + NR_C23=$3000; + NR_C24=$3000; + NR_C25=$3000; + NR_C26=$3000; + NR_C27=$3000; + NR_C28=$3000; + NR_C29=$3000; + NR_C30=$3000; + NR_C31=$3000; + { ASR } + NR_ASR0=$4000; + NR_ASR1=$4000; + NR_ASR2=$4000; + NR_ASR3=$4000; + NR_ASR4=$4000; + NR_ASR5=$4000; + NR_ASR6=$4000; + NR_ASR7=$4000; + NR_ASR8=$4000; + NR_ASR9=$4000; + NR_ASR10=$4000; + NR_ASR11=$4000; + NR_ASR12=$4000; + NR_ASR13=$4000; + NR_ASR14=$4000; + NR_ASR15=$4000; + NR_ASR16=$4000; + NR_ASR17=$4000; + NR_ASR18=$4000; + NR_ASR19=$4000; + NR_ASR20=$4000; + NR_ASR21=$4000; + NR_ASR22=$4000; + NR_ASR23=$4000; + NR_ASR24=$4000; + NR_ASR25=$4000; + NR_ASR26=$4000; + NR_ASR27=$4000; + NR_ASR28=$4000; + NR_ASR29=$4000; + NR_ASR30=$4000; + NR_ASR31=$4000; + { Floating point status/"front of queue" registers } + NR_FSR=$5000; + NR_FQ=$5000; + NR_CSR=$5000; + NR_CQ=$5000; + NR_PSR=$5000; + NR_TBR=$5000; + NR_WIM=$5000; + NR_Y=$5000; +{$endif dummy} + + {Super registers:} + RS_NO=$00; + RS_O0=$01; + RS_O1=$02; + RS_O2=$03; + RS_O3=$04; + RS_O4=$05; + RS_O5=$06; + RS_O6=$07; + RS_O7=$08; + RS_L0=$09; + RS_L1=$0A; + RS_L2=$0B; + RS_L3=$0C; + RS_L4=$0D; + RS_L5=$0E; + RS_L6=$0F; + RS_L7=$10; + RS_I0=$11; + RS_I1=$12; + RS_I2=$13; + RS_I3=$14; + RS_I4=$15; + RS_I5=$16; + RS_I6=$17; + RS_I7=$18; + RS_G0=$19; + RS_G1=$1A; + RS_G2=$1B; + RS_G3=$1C; + RS_G4=$1D; + RS_G5=$1E; + RS_G6=$1F; + RS_G7=$20; + + first_supreg = $01; + last_supreg = $20; + + first_imreg = $21; + last_imreg = $ff; + + { Subregisters, situation unknown!! } + R_SUBWHOLE=$00; + R_SUBL=$00; + {Conversion between TCpuRegister and NewRegisters} RegEnum2Number:array[TCpuRegister]of cardinal=( NR_NO, @@ -410,121 +511,127 @@ const NR_NO, NR_NO ); -{Superregisters.} -const - RS_O0=$01; - RS_O1=$02; - RS_O2=$03; - RS_O3=$04; - RS_O4=$05; - RS_O5=$06; - RS_O6=$07; - RS_O7=$08; - RS_L0=$09; - RS_L1=$0A; - RS_L2=$0B; - RS_L3=$0C; - RS_L4=$0D; - RS_L5=$0E; - RS_L6=$0F; - RS_L7=$10; - RS_I0=$11; - RS_I1=$12; - RS_I2=$13; - RS_I3=$14; - RS_I4=$15; - RS_I5=$16; - RS_I6=$17; - RS_I7=$18; - RS_G0=$19; - RS_G1=$1A; - RS_G2=$1B; - RS_G3=$1C; - RS_G4=$1D; - RS_G5=$1E; - RS_G6=$1F; - RS_G7=$20; +{***************************************************************************** + Conditions +*****************************************************************************} - first_supreg = $01; - last_supreg = $20; + type + TAsmCond=(C_None, + C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE, + C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP, + C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z + ); - first_imreg = $21; - last_imreg = $ff; + const + cond2str:array[TAsmCond] of string[3]=('', + 'a','ae','b','be','c','e','g','ge','l','le','na','nae', + 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np', + 'ns','nz','o','p','pe','po','s','z' + ); - {Subregisters; nothing known about.} - R_SUBWHOLE=$00; - R_SUBL=$00; + inverse_cond:array[TAsmCond] of TAsmCond=(C_None, + C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE, + C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P, + C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ + ); + + const + CondAsmOps=3; + CondAsmOp:array[0..CondAsmOps-1] of TAsmOp=( + A_FCMPd, A_JMPL, A_FCMPs + ); + CondAsmOpStr:array[0..CondAsmOps-1] of string[7]=( + 'FCMPd','JMPL','FCMPs' + ); -type - reg2strtable=array[TCpuRegister] OF STRING[7]; - TCpuReg=array[TCpuRegister]of TRegister; -const - std_reg2str:reg2strtable=({$INCLUDE strregs.inc}); - CpuReg:TCpuReg=({$INCLUDE registers.inc}); {***************************************************************************** Flags *****************************************************************************} -type - TResFlags=( - F_E, {Equal} - F_NE, {Not Equal} - F_G, {Greater} - F_L, {Less} - F_GE, {Greater or Equal} - F_LE, {Less or Equal} - F_C, {Carry} - F_NC, {Not Carry} - F_A, {Above} - F_AE, {Above or Equal} - F_B, {Below} - F_BE {Below or Equal} - ); + + type + TResFlags=( + F_E, {Equal} + F_NE, {Not Equal} + F_G, {Greater} + F_L, {Less} + F_GE, {Greater or Equal} + F_LE, {Less or Equal} + F_C, {Carry} + F_NC, {Not Carry} + F_A, {Above} + F_AE, {Above or Equal} + F_B, {Below} + F_BE {Below or Equal} + ); + {***************************************************************************** Reference *****************************************************************************} -type - TRefOptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup); - { since we have no full 32 bit offsets, we need to be able to specify the high - and low bits of the address of a symbol } - trefsymaddr = (refs_full,refs_hi,refs_lo); + type + TRefOptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup); - { immediate/reference record } - poperreference = ^treference; - Preference=^Treference; - treference = packed record - base, - index : tregister; - offset : LongInt; - symbol : tasmsymbol; - symaddr : trefsymaddr; - offsetfixup : LongInt; - options : trefoptions; - alignment : byte; - end; + { since we have no full 32 bit offsets, we need to be able to specify the high + and low bits of the address of a symbol } + trefsymaddr = (refs_full,refs_hi,refs_lo); + + { reference record } + preference = ^treference; + treference = packed record + { base register, R_NO if none } + base, + { index register, R_NO if none } + index : tregister; + { offset, 0 if none } + offset : longint; + { symbol this reference refers to, nil if none } + symbol : tasmsymbol; + { used in conjunction with symbols and offsets: refs_full means } + { means a full 32bit reference, refs_hi means the upper 16 bits } + { and refs_lo the lower 16 bits of the address } + symaddr : trefsymaddr; + { changed when inlining and possibly in other cases, don't } + { set manually } + offsetfixup : longint; + { used in conjunction with the previous field } + options : trefoptions; + { alignment this reference is guaranteed to have } + alignment : byte; + end; + + { reference record } + pparareference = ^tparareference; + tparareference = packed record + index : tregister; + offset : aword; + end; + + const + symaddr2str: array[trefsymaddr] of string[3] = ('','%hi','%lo'); - { reference record } - PParaReference=^TParaReference; - TParaReference = packed record - Index : TRegister; - Offset : longint; - end; {***************************************************************************** - Operands + Operand *****************************************************************************} - { Types of operand } - toptype=(top_none,top_reg,top_ref,top_const,top_symbol); - toper=record - ot:LongInt; - case typ:toptype of - top_none:(); - top_reg:(reg:tregister); - top_ref:(ref:poperreference); - top_const:(val:aword); - top_symbol:(sym:tasmsymbol;symofs:LongInt); - end; + + type + toptype=(top_none,top_reg,top_ref,top_const,top_symbol); + toper=record + ot:LongInt; + case typ:toptype of + top_none:(); + top_reg:(reg:tregister); + top_ref:(ref:preference); + top_const:(val:aword); + top_symbol:(sym:tasmsymbol;symofs:LongInt); + end; + +{***************************************************************************** + Operand Sizes +*****************************************************************************} + +{$ifdef dummy} {***************************************************************************** Argument Classification *****************************************************************************} @@ -539,310 +646,373 @@ type AC_FPUUP, AC_SSE, AC_SSEUP); +{$endif dummy} {***************************************************************************** Generic Location *****************************************************************************} -type - { tparamlocation describes where a parameter for a procedure is stored. - References are given from the caller's point of view. The usual TLocation isn't - used, because contains a lot of unnessary fields. } - TParaLocation=packed record - Size:TCGSize; - Loc:TCGLoc; - sp_fixup:LongInt; - CASE TCGLoc OF - LOC_REFERENCE:(reference:tparareference); - { segment in reference at the same place as in loc_register } - LOC_REGISTER,LOC_CREGISTER : ( - CASE LongInt OF - 1 : (register,registerhigh : tregister); - { overlay a registerlow } - 2 : (registerlow : tregister); - { overlay a 64 Bit register type } - 3 : (reg64 : tregister64); - 4 : (register64 : tregister64); - ); - { it's only for better handling } - LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister); - end; - TLocation=packed record - loc : TCGLoc; + type + { tparamlocation describes where a parameter for a procedure is stored. + References are given from the caller's point of view. The usual + TLocation isn't used, because contains a lot of unnessary fields. + } + tparalocation = packed record size : TCGSize; + { The location type where the parameter is passed, usually + LOC_REFERENCE,LOC_REGISTER or LOC_FPUREGISTER + } + loc : TCGLoc; + { The stack pointer must be decreased by this value before + the parameter is copied to the given destination. + This allows to "encode" pushes with tparalocation. + On the PowerPC, this field is unsed but it is there + because several generic code accesses it. + } + sp_fixup : longint; case TCGLoc of - LOC_FLAGS : (resflags : tresflags); - LOC_CONSTANT : ( + LOC_REFERENCE : (reference : tparareference); + LOC_FPUREGISTER, LOC_CFPUREGISTER, LOC_MMREGISTER, LOC_CMMREGISTER, + LOC_REGISTER,LOC_CREGISTER : ( case longint of - 1 : (value : AWord); - 2 : (valuelow, valuehigh:AWord); - { overlay a complete 64 Bit value } - 3 : (valueqword : qword); - ); - LOC_CREFERENCE, - LOC_REFERENCE : (reference : treference); - { segment in reference at the same place as in loc_register } - LOC_REGISTER,LOC_CREGISTER : ( - case longint of - 1 : (register,registerhigh,segment : tregister); + 1 : (register,registerhigh : tregister); { overlay a registerlow } 2 : (registerlow : tregister); { overlay a 64 Bit register type } 3 : (reg64 : tregister64); 4 : (register64 : tregister64); - ); - { it's only for better handling } - LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister); + ); end; + + treglocation = packed record + case longint of + 1 : (register,registerhigh : tregister); + { overlay a registerlow } + 2 : (registerlow : tregister); + { overlay a 64 Bit register type } + 3 : (reg64 : tregister64); + 4 : (register64 : tregister64); + end; + + + tlocation = packed record + size : TCGSize; + loc : tcgloc; + case tcgloc of + LOC_CREFERENCE,LOC_REFERENCE : (reference : treference); + LOC_CONSTANT : ( + case longint of +{$ifdef FPC_BIG_ENDIAN} + 1 : (_valuedummy,value : AWord); +{$else FPC_BIG_ENDIAN} + 1 : (value : AWord); +{$endif FPC_BIG_ENDIAN} + { can't do this, this layout depends on the host cpu. Use } + { lo(valueqword)/hi(valueqword) instead (JM) } + { 2 : (valuelow, valuehigh:AWord); } + { overlay a complete 64 Bit value } + 3 : (valueqword : qword); + ); + LOC_FPUREGISTER, LOC_CFPUREGISTER, LOC_MMREGISTER, LOC_CMMREGISTER, + LOC_REGISTER,LOC_CREGISTER : ( + case longint of + 1 : (registerlow,registerhigh : tregister); + 2 : (register : tregister); + { overlay a 64 Bit register type } + 3 : (reg64 : tregister64); + 4 : (register64 : tregister64); + ); + LOC_FLAGS : (resflags : tresflags); + end; + {***************************************************************************** Constants *****************************************************************************} -const - general_registers = [R_G0..R_I7]; - general_superregisters = [RS_O0..RS_I7]; - { legend: } - { xxxregs = set of all possibly used registers of that type in the code } - { generator } - { usableregsxxx = set of all 32bit components of registers that can be } - { possible allocated to a regvar or using getregisterxxx (this } - { excludes registers which can be only used for parameter } - { passing on ABI's that define this) } - { c_countusableregsxxx = amount of registers in the usableregsxxx set } - IntRegs=[R_G0..R_I7]; - usableregsint=[RS_O0..RS_I7]; - c_countusableregsint = 24; - fpuregs=[R_F0..R_F31]; - usableregsfpu=[R_F0..R_F31]; - c_countusableregsfpu=32; - mmregs=[]; - usableregsmm=[]; - c_countusableregsmm=0; - { no distinction on this platform } - maxaddrregs = 0; - addrregs = []; - usableregsaddr = []; - c_countusableregsaddr = 0; + const + max_operands = 3; + {# Constant defining possibly all registers which might require saving } + ALL_REGISTERS = [R_G0..R_I7]; + ALL_INTREGISTERS = [1..255]; - firstsaveintreg = RS_O0; - lastsaveintreg = RS_I7; - firstsavefpureg = R_F0; - lastsavefpureg = R_F31; - firstsavemmreg = R_NONE; - lastsavemmreg = R_NONE; - lowsavereg = R_G0; - highsavereg = R_I7; + general_registers = [R_G0..R_I7]; + general_superregisters = [RS_O0..RS_I7]; - ALL_REGISTERS = [lowsavereg..highsavereg]; - ALL_INTREGISTERS = [1..255]; + {# low and high of the available maximum width integer general purpose } + { registers } + LoGPReg = R_G0; + HiGPReg = R_I7; + + {# low and high of every possible width general purpose register (same as } + { above on most architctures apart from the 80x86) } + LoReg = R_G0; + HiReg = R_I7; + + {# Table of registers which can be allocated by the code generator + internally, when generating the code. + } + { legend: } + { xxxregs = set of all possibly used registers of that type in the code } + { generator } + { usableregsxxx = set of all 32bit components of registers that can be } + { possible allocated to a regvar or using getregisterxxx (this } + { excludes registers which can be only used for parameter } + { passing on ABI's that define this) } + { c_countusableregsxxx = amount of registers in the usableregsxxx set } + + maxintregs = 8; + intregs = [R_G0..R_I7]; + usableregsint = [RS_O0..RS_I7]; + c_countusableregsint = 24; + + maxfpuregs = 8; + fpuregs=[R_F0..R_F31]; + usableregsfpu=[R_F0..R_F31]; + c_countusableregsfpu=32; + + mmregs = []; + usableregsmm = []; + c_countusableregsmm = 0; + + { no distinction on this platform } + maxaddrregs = 0; + addrregs = []; + usableregsaddr = []; + c_countusableregsaddr = 0; + + firstsaveintreg = RS_O0; + lastsaveintreg = RS_I7; + firstsavefpureg = R_F0; + lastsavefpureg = R_F31; + firstsavemmreg = R_NO; + lastsavemmreg = R_NO; + + maxvarregs = 8; + varregs : Array [1..maxvarregs] of Tnewregister = + (RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7); + + maxfpuvarregs = 1; + fpuvarregs : Array [1..maxfpuvarregs] of Toldregister = + (R_F2); + + { + max_param_regs_int = 6; + param_regs_int: Array[1..max_param_regs_int] of Toldregister = + (R_3,R_4,R_5,R_6,R_7,R_8,R_9,R_10); + + max_param_regs_fpu = 13; + param_regs_fpu: Array[1..max_param_regs_fpu] of Toldregister = + (R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7,R_F8,R_F9,R_F10,R_F11,R_F12,R_F13); + + max_param_regs_mm = 13; + param_regs_mm: Array[1..max_param_regs_mm] of Toldregister = + (R_M1,R_M2,R_M3,R_M4,R_M5,R_M6,R_M7,R_M8,R_M9,R_M10,R_M11,R_M12,R_M13); + } + + {# Registers which are defined as scratch and no need to save across + routine calls or in assembler blocks. + } + max_scratch_regs = 2; + scratch_regs: Array[1..max_scratch_regs] of Tsuperregister = (RS_O7,RS_G2); + +{***************************************************************************** + Default generic sizes +*****************************************************************************} + + {# Defines the default address size for a processor, } + OS_ADDR = OS_32; + {# the natural int size for a processor, } + OS_INT = OS_32; + {# the maximum float size for a processor, } + OS_FLOAT = OS_F64; + {# the size of a vector register for a processor } + OS_VECTOR = OS_M64; - lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER, - LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER]; {***************************************************************************** GDB Information *****************************************************************************} - {# Register indexes for stabs information, when some parameters or variables - are stored in registers. - Taken from rs6000.h (DBX_REGISTER_NUMBER) from GCC 3.x source code.} - stab_regindex:array[TCpuRegister]OF ShortInt=({$INCLUDE stabregi.inc}); -{*************************** generic register names **************************} - stack_pointer_reg = R_O6; - NR_STACK_POINTER_REG = NR_O6; - RS_STACK_POINTER_REG = RS_O6; - frame_pointer_reg = R_I6; - NR_FRAME_POINTER_REG = NR_I6; - RS_FRAME_POINTER_REG = RS_I6; - {the return_result_reg, is used inside the called function to store its return - value when that is a scalar value otherwise a pointer to the address of the - result is placed inside it} - return_result_reg = R_I0; - NR_RETURN_RESULT_REG = NR_I0; - RS_RETURN_RESULT_REG = RS_I0; - {the function_result_reg contains the function result after a call to a scalar - function othewise it contains a pointer to the returned result} - function_result_reg = R_O0; - NR_FUNCTION_RESULT_REG = NR_O0; - RS_FUNCTION_RESULT_REG = RS_O0; - self_pointer_reg =R_G5; - NR_SELF_POINTER_REG = NR_G5; -{ RS_SELF_POINTER_REG = RS_G5;} - {There is no accumulator in the SPARC architecture. There are just families - of registers. All registers belonging to the same family are identical except - in the "global registers" family where GO is different from the others : - G0 gives always 0 when it is red and thows away any value written to it. - Nevertheless, scalar routine results are returned onto R_O0.} - accumulator = R_O0; - NR_ACCUMULATOR = NR_O0; - RS_ACCUMULATOR = RS_O1; - accumulatorhigh = R_O1; - NR_ACCUMULATORHIGH = NR_O1; - RS_ACCUMULATORHIGH = RS_O1; - fpu_result_reg = R_F0; - mmresultreg = R_G0; -{*****************************************************************************} -{ GCC /ABI linking information } -{*****************************************************************************} - { Registers which must be saved when calling a routine declared as cppdecl, - cdecl, stdcall, safecall, palmossyscall. The registers saved should be the ones - as defined in the target ABI and / or GCC. + {# Register indexes for stabs information, when some + parameters or variables are stored in registers. - This value can be deduced from the CALLED_USED_REGISTERS array in the GCC - source. - } - std_saved_registers=[]; + Taken from rs6000.h (DBX_REGISTER_NUMBER) + from GCC 3.x source code. + } - { Required parameter alignment when calling a routine declared as stdcall and - cdecl. The alignment value should be the one defined by GCC or the target ABI. - - The value of this constant is equal to the constant - PARM_BOUNDARY / BITS_PER_UNIT in the GCC source. } - std_param_align=4; - - { Registers which are defined as scratch and no need to save across routine - calls or in assembler blocks.} - ScratchRegsCount=2; - scratch_regs:array[1..ScratchRegsCount] OF Tsuperregister=(RS_O7,RS_G2); - - { low and high of the available maximum width integer general purpose - registers } - LoGPReg = R_G0; - HiGPReg = R_I7; - - { low and high of every possible width general purpose register (same as - above on most architctures apart from the 80x86) } - LoReg = R_G0; - HiReg = R_I7; - - cpuflags = []; - - { sizes } - pointersize = 4; - extended_size = 8; { SPARC architecture uses IEEE floating point numbers} - mmreg_size = 8; - SizePostfix_pointer = S_SW; + stab_regindex : array[firstreg..lastreg] of shortint = + ( + 0{R_NO} + {General purpose global registers} + ,1{R_G0}{This register is usually set to zero and used as a scratch register} + ,2{R_G1},3{R_G2},4{R_G3},5{R_G4},6{R_G5},7{R_G6},8{R_G7} + {General purpose out registers} + ,9{R_O0},10{R_O1},11{R_O2},12{R_O3},13{R_O4},14{R_O5},15{R_O6} + ,16{R_O7}{This register is used to save the address of the last CALL instruction} + {General purpose local registers} + ,16{R_L0} + ,17{R_L1}{This register is used to save the Program Counter (PC) after a Trap} + ,18{R_L2}{This register is used to save the Program Counter (nPC) after a Trap} + ,19{R_L3},20{R_L4},21{R_L5},22{R_L6},23{R_L7} + {General purpose in registers} + ,24{R_I0},25{R_I1},26{R_I2},27{R_I3},28{R_I4},29{R_I5},30{R_I6},31{R_I7} + {Floating point registers} + ,32{R_F0},33{R_F1},34{R_F2},35{R_F3},36{R_F4},37{R_F5},38{R_F6},39{R_F7} + ,40{R_F8},41{R_F9},42{R_F10},43{R_F11},44{R_F12},45{R_F13},46{R_F14},47{R_F15} + ,48{R_F16},49{R_F17},50{R_F18},51{R_F19},52{R_F20},53{R_F21},54{R_F22},55{R_F23} + ,56{R_F24},57{R_F25},58{R_F26},59{R_F27},60{R_F28},61{R_F29},62{R_F30},63{R_F31} + {Floating point status/"front of queue" registers} + ,64{R_FSR},65{R_FQ} + {Coprocessor registers} + ,66{R_C0},67{R_C1},68{R_C2},69{R_C3},70{R_C4},71{R_C5},72{R_C6},73{R_C7} + ,74{R_C8},75{R_C9},76{R_C10},77{R_C11},78{R_C12},79{R_C13},80{R_C14},81{R_C15} + ,82{R_C16},83{R_C17},84{R_C18},85{R_C19},86{R_C20},87{R_C21},88{R_C22},89{R_C23} + ,90{R_C24},91{R_C25},92{R_C26},93{R_C27},94{R_C28},95{R_C29},96{R_C30},98{R_C31} + {Coprocessor status/queue registers} + ,99{R_CSR} + ,100{R_CQ} + {Integer Unit control & status registers} + ,101{R_PSR}{Processor Status Register : informs upon the program status} + ,102{R_TBR}{Trap Base Register : saves the Trap vactor base address} + ,103{R_WIM}{Window Invalid Mask : } + ,104{R_Y}{Multiply/Devide Register : } + {Ancillary State Registers : these are implementation dependent registers and + thus, are not specified by the SPARC Reference Manual. I did choose the SUN's + implementation according to the Assembler Refernce Manual.(MN)} + ,105{R_ASR0},106{R_ASR1},107{R_ASR2},108{R_ASR3},109{R_ASR4},110{R_ASR5},111{R_ASR6},112{R_ASR7} + ,113{R_ASR8},114{R_ASR9},115{R_ASR10},116{R_ASR11},117{R_ASR12},118{R_ASR13},119{R_ASR14},120{R_ASR15} + ,121{R_ASR16},122{R_ASR17},123{R_ASR18},124{R_ASR19},125{R_ASR20},126{R_ASR21},127{R_ASR22},127{R_ASR23} + ,127{R_ASR24},127{R_ASR25},127{R_ASR26},127{R_ASR27},127{R_ASR28},127{R_ASR29},127{R_ASR30},127{R_ASR31} + ); {***************************************************************************** - Instruction table + Generic Register names +*****************************************************************************} + + {# Stack pointer register } + NR_STACK_POINTER_REG = NR_O6; + RS_STACK_POINTER_REG = RS_O6; + {# Frame pointer register } + NR_FRAME_POINTER_REG = NR_I6; + RS_FRAME_POINTER_REG = RS_I6; + {# Register for addressing absolute data in a position independant way, + such as in PIC code. The exact meaning is ABI specific. For + further information look at GCC source : PIC_OFFSET_TABLE_REGNUM + + Taken from GCC rs6000.h + } +{$warning As indicated in rs6000.h, but can't find it anywhere else!} + {PIC_OFFSET_REG = R_30;} + { the return_result_reg, is used inside the called function to store its return + value when that is a scalar value otherwise a pointer to the address of the + result is placed inside it } + NR_FUNCTION_RETURN_REG = NR_I0; + RS_FUNCTION_RETURN_REG = RS_I0; + { The high part of 64bit value returned by this function } + NR_FUNCTION_RETURNHIGH_REG = NR_I1; + RS_FUNCTION_RETURNHIGH_REG = RS_I1; + { the FUNCTION_RESULT_REG contains the function result after a call to a scalar + function othewise it contains a pointer to the returned result} + NR_FUNCTION_RESULT_REG = NR_O0; + RS_FUNCTION_RESULT_REG = RS_O0; + { The high part of 64bit value returned from a function is available in this register } + NR_FUNCTION_RESULTHIGH_REG = NR_O1; + RS_FUNCTION_RESULTHIGH_REG = RS_O1; + + FPU_RESULT_REG = R_F0; + mmresultreg = R_NO; + +{***************************************************************************** + GCC /ABI linking information +*****************************************************************************} + + {# Registers which must be saved when calling a routine declared as + cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers + saved should be the ones as defined in the target ABI and / or GCC. + + This value can be deduced from CALLED_USED_REGISTERS array in the + GCC source. + } + std_saved_registers = []; + + {# Required parameter alignment when calling a routine declared as + stdcall and cdecl. The alignment value should be the one defined + by GCC or the target ABI. + + The value of this constant is equal to the constant + PARM_BOUNDARY / BITS_PER_UNIT in the GCC source. + } + std_param_align = 4; { for 32-bit version only } + +{***************************************************************************** + CPU Dependent Constants *****************************************************************************} -{$ifndef NOAG386BIN} -type - tinsentry=packed record - opcode : tasmop; - ops : byte; - optypes : array[0..2] of LongInt; - code : array[0..maxinfolen] of char; - flags : LongInt; - end; - pinsentry=^tinsentry; - TInsTabCache=array[TasmOp] of LongInt; - PInsTabCache=^TInsTabCache; -VAR - InsTabCache : PInsTabCache; -{$endif NOAG386BIN} {***************************************************************************** Helpers *****************************************************************************} -const - maxvarregs=8; - VarRegs:array[1..maxvarregs] of tnewregister = ( - RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7 - ); - maxfpuvarregs = 8; - max_operands = 3; - maxintregs = maxvarregs; - maxfpuregs = maxfpuvarregs; - max_scratch_regs=8; + function is_calljmp(o:tasmop):boolean; -function is_calljmp(o:tasmop):boolean; -function flags_to_cond(CONST f:TResFlags):TAsmCond; -procedure convert_register_to_enum(var Reg:Tregister); -function cgsize2subreg(s:Tcgsize):Tsubregister; + function flags_to_cond(const f: TResFlags) : TAsmCond; + procedure convert_register_to_enum(var r:Tregister); + function cgsize2subreg(s:Tcgsize):Tsubregister; implementation - uses - verbose; - const - CallJmpOp=[A_JMPL..A_CBccc]; + uses + verbose; - function is_calljmp(o:tasmop):boolean; - begin - if o in CallJmpOp - then - is_calljmp:=true - else - is_calljmp:=false; - end; +{***************************************************************************** + Helpers +*****************************************************************************} -function flags_to_cond(const f:TResFlags):TAsmCond; - CONST - flags_2_cond:array[TResFlags]OF TAsmCond= - (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE); - BEGIN - result:=flags_2_cond[f]; - end; + function is_calljmp(o:tasmop):boolean; + const + CallJmpOp=[A_JMPL..A_CBccc]; + begin + is_calljmp:=(o in CallJmpOp); + end; -procedure convert_register_to_enum(var Reg:Tregister); - begin - with Reg do - if(enum=R_INTREGISTER) - then - if(number<=RegEnum2Number[R_I7]) - then - begin - enum:=Low(enum); - repeat - Inc(enum); - until(number=RegEnum2Number[enum])or(enum=High(enum)); - end - else - internalerror(200301082); - end; -function cgsize2subreg(s:Tcgsize):Tsubregister; -begin - cgsize2subreg:=R_SUBWHOLE; -end; + function flags_to_cond(const f:TResFlags):TAsmCond; + const + flags_2_cond:array[TResFlags] of TAsmCond= + (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE); + begin + result:=flags_2_cond[f]; + end; + + + procedure convert_register_to_enum(var r:Tregister); + begin + with R do + if(enum=R_INTREGISTER) then + if(number<=RegEnum2Number[R_I7]) then + begin + enum:=Low(enum); + repeat + Inc(enum); + until(number=RegEnum2Number[enum])or(enum=High(enum)); + end + else + internalerror(200301082); + end; + + + function cgsize2subreg(s:Tcgsize):Tsubregister; + begin + cgsize2subreg:=R_SUBWHOLE; + end; + end. { $Log$ - Revision 1.34 2003-05-28 23:18:31 florian - * started to fix and clean up the sparc port + Revision 1.35 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) - Revision 1.33 2003/05/26 22:08:42 mazen - + RegEnum2Number to ease handling register pairs - * changed convert_register_to_enum to use above - array - - Revision 1.32 2003/05/23 21:10:50 florian - * fixed sparc compiler compilation - - Revision 1.31 2003/05/22 16:11:22 florian - * fixed sparc compilation partially - - Revision 1.30 2003/05/06 14:58:46 mazen - - non used constants OT_* removed - * some keywords moved lower case - - Revision 1.29 2003/04/29 12:03:52 mazen - * TOldRegister isnow just an alias for TCpuRegister - * TCpuRegister is used to define cpu register set physically available - + CpuRegs array to easially create correspondence between TCpuRegister and TRegister - - Revision 1.28 2003/04/28 09:46:30 mazen - + max_scratch_regs variable added because requested by common compiler code - - Revision 1.27 2003/04/23 13:35:39 peter - * fix sparc compile - - Revision 1.26 2003/04/23 12:35:35 florian - * fixed several issues with powerpc - + applied a patch from Jonas for nested function calls (PowerPC only) - * ... } diff --git a/compiler/sparc/cpugas.pas b/compiler/sparc/cpugas.pas index dc5550141b..28436ef552 100644 --- a/compiler/sparc/cpugas.pas +++ b/compiler/sparc/cpugas.pas @@ -48,20 +48,17 @@ unit cpugas; begin inc(offset,offsetfixup); offsetfixup:=0; - if base.enum>lastreg then + if (base.enum<>R_INTREGISTER) or (index.enum<>R_INTREGISTER) then internalerror(200301081); - if index.enum>lastreg then - internalerror(200301081); - if assigned(symbol) then begin + if (base.number<>NR_NO) or (index.number<>NR_NO) then + internalerror(2003052601); GetReferenceString:=symbol.name; if offset>0 then GetReferenceString:=GetReferenceString+'+'+ToStr(offset) else if offset<0 then GetReferenceString:=GetReferenceString+ToStr(offset); - if (base.enum<>R_NONE) or (index.enum<>R_NONE) then - internalerror(2003052601); if symaddr=refs_hi then GetReferenceString:='%hi('+GetReferenceString+')' else if symaddr=refs_lo then @@ -71,9 +68,9 @@ unit cpugas; end else begin - if base.enum<>R_NONE then + if base.number<>NR_NO then GetReferenceString:=std_reg2str[base.enum]+'+'; - if index.enum<>R_NONE then + if index.number<>NR_NO then GetReferenceString:=GetReferenceString+std_reg2str[index.enum]+'+'; if Offset<>0 then internalerror(2003052603); @@ -199,7 +196,12 @@ begin end. { $Log$ - Revision 1.15 2003-05-28 23:18:31 florian + Revision 1.16 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.15 2003/05/28 23:18:31 florian * started to fix and clean up the sparc port Revision 1.14 2003/05/07 11:55:34 mazen diff --git a/compiler/sparc/cpupara.pas b/compiler/sparc/cpupara.pas index 83a9247b20..399123ab19 100644 --- a/compiler/sparc/cpupara.pas +++ b/compiler/sparc/cpupara.pas @@ -1,8 +1,8 @@ -{****************************************************************************** +{ $Id$ - Copyright (c) 2002 by Florian Klaempfl + Copyright (c) 1998-2002 by Florian Klaempfl - PowerPC specific calling conventions + Calling conventions for the SPARC This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,269 +19,296 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *****************************************************************************} unit cpupara; -{SPARC specific calling conventions are handled by this unit} -{$INCLUDE fpcdefs.inc} + +{$i fpcdefs.inc} + interface -uses - cpubase, - symconst,symbase,symtype,symdef,paramgr; -type - TSparcParaManager=class(TParaManager) - {Returns a structure giving the information on the storage of the parameter - (which must be an integer parameter) - @param(nr Parameter number of routine, starting from 1)} - function GetIntParaLoc(nr:longint):TParaLocation;override; - {Creates location information related to the parameter of the function} - procedure create_param_loc_info(p:TAbstractProcDef);override; - {Returns the location where the invisible parameter for structured function - results will be passed.} - function GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;override; - end; + + uses + cpubase, + symconst,symbase,symtype,symdef,paramgr; + + type + TSparcParaManager=class(TParaManager) + {Returns a structure giving the information on the storage of the parameter + (which must be an integer parameter) + @param(nr Parameter number of routine, starting from 1)} + function GetIntParaLoc(nr:longint):TParaLocation;override; + {Creates location information related to the parameter of the function} + procedure create_param_loc_info(p:TAbstractProcDef);override; + {Returns the location where the invisible parameter for structured function + results will be passed.} + function GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation;override; + end; + + implementation -uses - verbose, - cpuinfo,cginfo,cgbase, - defutil; -function TSparcParaManager.GetIntParaLoc(nr:longint):TParaLocation; - begin - if nr<1 - then - InternalError(2002100806); - FillChar(GetIntParaLoc,SizeOf(TParaLocation),0); - Dec(nr); - with GetIntParaLoc do - if nr<6 - then{The six first parameters are passed into registers} - begin - loc:=LOC_REGISTER; - register.enum:=ToldRegister(LongInt(R_i0)+nr); - end - else{The other parameters are passed into the frame} - begin - loc:=LOC_REFERENCE; - reference.index.enum:=frame_pointer_reg; - reference.offset:=-68-nr*4; - end; - end; -function GetParaLoc(p:TDef):TCGLoc; - begin -{Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER if -push_addr_param for the def is true} - case p.DefType of - OrdDef: - GetParaLoc:=LOC_REGISTER; - FloatDef: - GetParaLoc:=LOC_FPUREGISTER; - enumdef: - getparaloc:=LOC_REGISTER; - pointerdef: - getparaloc:=LOC_REGISTER; - formaldef: - getparaloc:=LOC_REGISTER; - classrefdef: - getparaloc:=LOC_REGISTER; - recorddef: - getparaloc:=LOC_REFERENCE; - objectdef: - if is_object(p) - then - getparaloc:=LOC_REFERENCE - else - getparaloc:=LOC_REGISTER; - stringdef: - if is_shortstring(p) or is_longstring(p) - then - getparaloc:=LOC_REFERENCE - else - getparaloc:=LOC_REGISTER; - procvardef: - if (po_methodpointer in tprocvardef(p).procoptions) - then - getparaloc:=LOC_REFERENCE - else - getparaloc:=LOC_REGISTER; - filedef: - getparaloc:=LOC_REGISTER; - arraydef: - getparaloc:=LOC_REFERENCE; - setdef: - if is_smallset(p) - then - getparaloc:=LOC_REGISTER - else - getparaloc:=LOC_REFERENCE; - variantdef: - getparaloc:=LOC_REFERENCE; - { avoid problems with errornous definitions } - errordef: - getparaloc:=LOC_REGISTER; - else - internalerror(2002071001); - end; - end; -procedure TSparcParaManager.create_param_loc_info(p:TAbstractProcDef); - var - nextintreg,nextfloatreg:tregister; - stack_offset:aword; - hp:tparaitem; - loc:tcgloc; - is_64bit:boolean; - begin - nextintreg.enum:=R_O0; - nextfloatreg.enum:=R_F0; - stack_offset:=92; - hp:=TParaItem(p.para.First); - while assigned(hp) do + + uses + verbose, + cpuinfo,cginfo,cgbase, + defutil; + + function TSparcParaManager.GetIntParaLoc(nr:longint):TParaLocation; begin - loc:=GetParaLoc(hp.paratype.def); - case loc of - LOC_REGISTER: + if nr<1 then + InternalError(2002100806); + FillChar(GetIntParaLoc,SizeOf(TParaLocation),0); + Dec(nr); + with GetIntParaLoc do + begin + { The six first parameters are passed into registers } + if nr<6 then begin - hp.paraloc.size:=def_cgSize(hp.paratype.def); - if hp.paraloc.size=OS_NO - then - hp.paraloc.size:=OS_ADDR; - is_64bit:=hp.paraloc.size in [OS_64,OS_S64]; - if NextIntReg.enum<=ToldRegister(ord(R_i5)-ord(is_64bit)) - then - begin - hp.paraloc.loc:=LOC_REGISTER; - hp.paraloc.registerlow:=NextIntReg; - inc(NextIntReg.enum); - if is_64bit - then - begin - hp.paraloc.registerhigh:=nextintreg; - inc(nextintreg.enum); - end; - end - else - begin - nextintreg.enum:=R_i6; - hp.paraloc.loc:=LOC_REFERENCE; - hp.paraloc.reference.index.enum:=stack_pointer_reg; - hp.paraloc.reference.offset:=stack_offset; - if not is_64bit - then - inc(stack_offset,4) - else - inc(stack_offset,8); - end; + loc:=LOC_REGISTER; + register.enum:=R_INTREGISTER; + register.number:=(RS_I0+nr) shl 8; + end + else + { The other parameters are passed into the frame } + begin + loc:=LOC_REFERENCE; + reference.index.enum:=R_INTREGISTER; + reference.index.number:=NR_FRAME_POINTER_REG; + reference.offset:=-68-nr*4; end; - LOC_FPUREGISTER: - begin - if hp.paratyp in [vs_var,vs_out] - then + end; + end; + + + function GetParaLoc(p:TDef):TCGLoc; + begin + { Later, the LOC_REFERENCE is in most cases changed into + LOC_REGISTER if push_addr_param for the def is true} + case p.DefType of + OrdDef: + GetParaLoc:=LOC_REGISTER; + FloatDef: + GetParaLoc:=LOC_FPUREGISTER; + enumdef: + getparaloc:=LOC_REGISTER; + pointerdef: + getparaloc:=LOC_REGISTER; + formaldef: + getparaloc:=LOC_REGISTER; + classrefdef: + getparaloc:=LOC_REGISTER; + recorddef: + getparaloc:=LOC_REFERENCE; + objectdef: + if is_object(p) then + getparaloc:=LOC_REFERENCE + else + getparaloc:=LOC_REGISTER; + stringdef: + if is_shortstring(p) or is_longstring(p) then + getparaloc:=LOC_REFERENCE + else + getparaloc:=LOC_REGISTER; + procvardef: + if (po_methodpointer in tprocvardef(p).procoptions) then + getparaloc:=LOC_REFERENCE + else + getparaloc:=LOC_REGISTER; + filedef: + getparaloc:=LOC_REGISTER; + arraydef: + getparaloc:=LOC_REFERENCE; + setdef: + if is_smallset(p) then + getparaloc:=LOC_REGISTER + else + getparaloc:=LOC_REFERENCE; + variantdef: + getparaloc:=LOC_REFERENCE; + { avoid problems with errornous definitions } + errordef: + getparaloc:=LOC_REGISTER; + else + internalerror(2002071001); + end; + end; + + + procedure TSparcParaManager.create_param_loc_info(p:TAbstractProcDef); + var + nextintreg : tsuperregister; + nextfloatreg : toldregister; + stack_offset : longint; + hp : tparaitem; + loc : tcgloc; + is_64bit : boolean; + begin + nextintreg:=RS_O0; + nextfloatreg:=R_F0; + stack_offset:=92; + hp:=TParaItem(p.para.First); + while assigned(hp) do + begin + loc:=GetParaLoc(hp.paratype.def); + case loc of + LOC_REGISTER: begin - if NextIntReg.enum<=R_O5 - then + hp.paraloc.size:=def_cgSize(hp.paratype.def); + if hp.paraloc.size=OS_NO then + hp.paraloc.size:=OS_ADDR; + is_64bit:=(hp.paraloc.size in [OS_64,OS_S64]); + if NextIntReg<=RS_I5-ord(is_64bit) then begin - hp.paraloc.size:=OS_ADDR; hp.paraloc.loc:=LOC_REGISTER; - hp.paraloc.register:=nextintreg; - inc(nextintreg.enum); + hp.paraloc.registerlow.enum:=R_INTREGISTER; + hp.paraloc.registerlow.number:=NextIntReg shl 8; + inc(NextIntReg); + if is_64bit then + begin + hp.paraloc.registerhigh.enum:=R_INTREGISTER; + hp.paraloc.registerhigh.number:=nextintreg shl 8; + inc(nextintreg); + end; + end + else + begin + nextintreg:=RS_I6; + hp.paraloc.loc:=LOC_REFERENCE; + hp.paraloc.reference.index.enum:=R_INTREGISTER; + hp.paraloc.reference.index.number:=NR_STACK_POINTER_REG; + hp.paraloc.reference.offset:=stack_offset; + if not is_64bit then + inc(stack_offset,4) + else + inc(stack_offset,8); + end; + end; + + LOC_FPUREGISTER: + begin + if hp.paratyp in [vs_var,vs_out] then + begin + if NextIntReg<=RS_O5 then + begin + hp.paraloc.size:=OS_ADDR; + hp.paraloc.loc:=LOC_REGISTER; + hp.paraloc.register.enum:=R_INTREGISTER; + hp.paraloc.register.number:=nextintreg shl 8; + inc(nextintreg); + end + else + begin + {!!!!!!!} + hp.paraloc.size:=def_cgsize(hp.paratype.def); + internalerror(2002071006); + end; + end + else if nextfloatreg<=R_F10 then + begin + hp.paraloc.size:=def_cgsize(hp.paratype.def); + hp.paraloc.loc:=LOC_FPUREGISTER; + hp.paraloc.register.enum:=nextfloatreg; + inc(nextfloatreg); end else begin {!!!!!!!} hp.paraloc.size:=def_cgsize(hp.paratype.def); - internalerror(2002071006); + internalerror(2002071004); end; - end - else if nextfloatreg.enum<=R_F10 then - begin - hp.paraloc.size:=def_cgsize(hp.paratype.def); - hp.paraloc.loc:=LOC_FPUREGISTER; - hp.paraloc.register:=nextfloatreg; - inc(nextfloatreg.enum); - end - else - begin - {!!!!!!!} - hp.paraloc.size:=def_cgsize(hp.paratype.def); - internalerror(2002071004); end; + + LOC_REFERENCE: + begin + hp.paraloc.size:=OS_ADDR; + if push_addr_param(hp.paratype.def,p.proccalloption) or (hp.paratyp in [vs_var,vs_out]) then + begin + if nextintreg<=RS_O5 then + begin + hp.paraloc.loc:=LOC_REGISTER; + hp.paraloc.register.enum:=R_INTREGISTER; + hp.paraloc.register.number:=nextintreg shl 8; + inc(nextintreg); + end + else + begin + hp.paraloc.loc:=LOC_REFERENCE; + hp.paraloc.reference.index.enum:=R_INTREGISTER; + hp.paraloc.reference.index.number:=NR_STACK_POINTER_REG; + hp.paraloc.reference.offset:=stack_offset; + inc(stack_offset,4); + end; + end + else + begin + hp.paraloc.loc:=LOC_REFERENCE; + hp.paraloc.reference.index.enum:=R_INTREGISTER; + hp.paraloc.reference.index.number:=NR_STACK_POINTER_REG; + hp.paraloc.reference.offset:=stack_offset; + inc(stack_offset,hp.paratype.def.size); + end; + end; + + else + internalerror(2002071002); end; - LOC_REFERENCE: - begin - hp.paraloc.size:=OS_ADDR; - if push_addr_param(hp.paratype.def,p.proccalloption) or (hp.paratyp in [vs_var,vs_out]) then - begin - if nextintreg.enum<=R_O5 then - begin - hp.paraloc.loc:=LOC_REGISTER; - hp.paraloc.register:=nextintreg; - inc(nextintreg.enum); - end - else - begin - hp.paraloc.loc:=LOC_REFERENCE; - hp.paraloc.reference.index.enum:=stack_pointer_reg; - hp.paraloc.reference.offset:=stack_offset; - inc(stack_offset,4); - end; - end - else - begin - hp.paraloc.loc:=LOC_REFERENCE; - hp.paraloc.reference.index.enum:=stack_pointer_reg; - hp.paraloc.reference.offset:=stack_offset; - inc(stack_offset,hp.paratype.def.size); - end; - end; - else - internalerror(2002071002); - end; - hp:=TParaItem(hp.Next); - end; - end; -function tSparcParaManager.GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation; - begin - with GetFuncRetParaLoc do - case p.rettype.def.deftype of - orddef,enumdef: - begin - loc:=LOC_REGISTER; - register.enum:=return_result_reg; - size:=def_cgsize(p.rettype.def); - if size in [OS_S64,OS_64] - then - RegisterHigh.enum:=R_I1; + hp:=TParaItem(hp.Next); end; - floatdef: - begin - loc:=LOC_FPUREGISTER; - register.enum:=R_F1; - size:=def_cgsize(p.rettype.def); - end; - setdef, - variantdef, - pointerdef, - formaldef, - classrefdef, - recorddef, - objectdef, - stringdef, - procvardef, - filedef, - arraydef, - errordef: - begin - loc:=LOC_REFERENCE; - reference.index.enum:=frame_pointer_reg; - reference.offset:=64; - size:=OS_ADDR; - end; - else - internalerror(2002090903); end; - end; + + + function tSparcParaManager.GetFuncRetParaLoc(p:TAbstractProcDef):TParaLocation; + begin + with GetFuncRetParaLoc do + begin + case p.rettype.def.deftype of + orddef,enumdef: + begin + loc:=LOC_REGISTER; + register.enum:=R_INTREGISTER; + register.number:=NR_FUNCTION_RETURN_REG; + size:=def_cgsize(p.rettype.def); + if size in [OS_S64,OS_64] then + internalerror(200305309); + end; + floatdef: + begin + loc:=LOC_FPUREGISTER; + register.enum:=R_F1; + size:=def_cgsize(p.rettype.def); + end; + setdef, + variantdef, + pointerdef, + formaldef, + classrefdef, + recorddef, + objectdef, + stringdef, + procvardef, + filedef, + arraydef, + errordef: + begin + loc:=LOC_REFERENCE; + reference.index.enum:=R_INTREGISTER; + reference.index.number:=NR_FRAME_POINTER_REG; + reference.offset:=64; + size:=OS_ADDR; + end; + else + internalerror(2002090903); + end; + end; + end; + begin ParaManager:=TSparcParaManager.create; end. { $Log$ - Revision 1.16 2003-04-23 13:35:39 peter + Revision 1.17 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.16 2003/04/23 13:35:39 peter * fix sparc compile Revision 1.15 2003/04/23 12:35:35 florian diff --git a/compiler/sparc/cpupi.pas b/compiler/sparc/cpupi.pas index de761f590c..0db0f1074f 100644 --- a/compiler/sparc/cpupi.pas +++ b/compiler/sparc/cpupi.pas @@ -101,7 +101,12 @@ begin end. { $Log$ - Revision 1.15 2003-05-23 22:33:48 florian + Revision 1.16 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.15 2003/05/23 22:33:48 florian * fix some small flaws which prevent sparc linux system unit from compiling * some reformatting done @@ -133,7 +138,7 @@ end. + added debug output on screen with -an command line option Revision 1.8 2002/11/17 17:49:09 mazen - + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one + + return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one Revision 1.7 2002/11/14 21:42:08 mazen * fixing return value variable address diff --git a/compiler/sparc/cputarg.pas b/compiler/sparc/cputarg.pas index 9e4cd73786..23d12b7292 100644 --- a/compiler/sparc/cputarg.pas +++ b/compiler/sparc/cputarg.pas @@ -48,14 +48,17 @@ implementation **************************************} ,CpuGas - ,ogcoff - ,ogelf ; end. { $Log$ - Revision 1.3 2003-05-23 21:10:50 florian + Revision 1.4 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.3 2003/05/23 21:10:50 florian * fixed sparc compiler compilation Revision 1.2 2002/09/07 15:25:14 peter diff --git a/compiler/sparc/ncpuadd.pas b/compiler/sparc/ncpuadd.pas index 1c4e742924..e2561870b4 100644 --- a/compiler/sparc/ncpuadd.pas +++ b/compiler/sparc/ncpuadd.pas @@ -34,8 +34,8 @@ type procedure second_addfloat; function GetResFlags(unsigned:Boolean):TResFlags; procedure emit_compare(unsigned:boolean); - procedure left_must_be_reg(OpSize:TOpSize;NoSwap:Boolean); - procedure emit_generic_code(op:TAsmOp;OpSize:TOpSize;unsigned,extra_not,mboverflow:Boolean); + procedure left_must_be_reg(OpSize:TcgSize;NoSwap:Boolean); + procedure emit_generic_code(op:TAsmOp;OpSize:TcgSize;unsigned,extra_not,mboverflow:Boolean); procedure emit_op_right_left(op:TAsmOp); procedure Load_left_right(cmpop,load_constants:Boolean); procedure pass_left_and_right; @@ -47,12 +47,11 @@ uses cutils,verbose,globals, symconst,symdef,SymType,paramgr, aasmbase,aasmtai,aasmcpu,defutil,htypechk, - cgbase,pass_2,regvars, + cpuinfo,cgbase,pass_2,regvars, cpupara, ncon,nset, ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32; -const - opsize_2_cgSize:array[S_B..S_L]of TCgSize=(OS_8,OS_16,OS_32); + procedure TSparcAddNode.clear_left_right(cmpop:Boolean); begin if(right.location.loc in [LOC_REGISTER,LOC_FPUREGISTER])and(cmpop or(location.register.enum <> right.location.register.enum)) @@ -160,7 +159,7 @@ procedure TSparcAddNode.second_addboolean; then exprasmlist.concat(taicpu.op_reg_reg(A_JMPL,left.location.register,right.location.register)) else - exprasmlist.concat(taicpu.op_reg_const(A_JMPL,left.location.register,longint(right.location.value))); + exprasmlist.concat(taicpu.op_reg_const(A_JMPL,left.location.register,right.location.value)); location.resflags := GetResFlags(true); end; else @@ -280,7 +279,7 @@ function TSparcAddNode.GetResFlags(unsigned:Boolean):TResFlags; end; end; end; -procedure TSparcAddNode.left_must_be_reg(OpSize:TOpSize;NoSwap:Boolean); +procedure TSparcAddNode.left_must_be_reg(OpSize:TcgSize;NoSwap:Boolean); begin if(left.location.loc=LOC_REGISTER) then @@ -296,10 +295,10 @@ procedure TSparcAddNode.left_must_be_reg(OpSize:TOpSize;NoSwap:Boolean); begin {maybe we can reuse a constant register when the operation is a comparison that doesn't change the value of the register} - location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],(nodetype in [ltn,lten,gtn,gten,equaln,unequaln])); + location_force_reg(exprasmlist,left.location,opsize,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln])); end; end; -procedure TSparcAddNode.emit_generic_code(op:TAsmOp;OpSize:TOpSize;unsigned,extra_not,mboverflow:Boolean); +procedure TSparcAddNode.emit_generic_code(op:TAsmOp;OpSize:TcgSize;unsigned,extra_not,mboverflow:Boolean); var power:LongInt; hl4:TAsmLabel; @@ -398,12 +397,12 @@ procedure TSparcAddNode.emit_generic_code(op:TAsmOp;OpSize:TOpSize;unsigned,extr IF cs_check_overflow IN aktlocalswitches THEN begin - // getlabel(hl4); + objectlibrary.getlabel(hl4); IF unsigned THEN - exprasmList.concat(Taicpu.Op_sym(A_JMPL,S_NO,hl4)) + exprasmList.concat(Taicpu.Op_sym(A_JMPL,hl4)) ELSE - exprasmList.concat(Taicpu.Op_sym(A_JMPL,S_NO,hl4)); + exprasmList.concat(Taicpu.Op_sym(A_JMPL,hl4)); cg.a_call_name(exprasmlist,'FPC_OVERFLOW'); cg.a_label(exprasmlist,hl4); end; @@ -425,7 +424,7 @@ procedure TSparcAddNode.emit_compare(unsigned:boolean); then begin {$ifdef ExtDebug} - if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>$ffffffff) or unsigned) + if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>aword($ffffffff)) or unsigned) then internalerror(2002080301); {$endif extdebug} @@ -463,7 +462,7 @@ procedure TSparcAddNode.emit_compare(unsigned:boolean); if useconst then exprasmlist.concat(taicpu.op_reg_const(op, - left.location.register,longint(right.location.value))) + left.location.register,right.location.value)) else begin exprasmlist.concat(taicpu.op_reg_reg(op,left.location.register,tmpreg)); @@ -495,7 +494,6 @@ procedure TSparcAddNode.second_add64bit; var op : TOpCG; op1,op2 : TAsmOp; - hl4 : tasmlabel; cmpop, unsigned : boolean; r : Tregister; @@ -600,6 +598,7 @@ procedure TSparcAddNode.second_add64bit; var tempreg64: tregister64; + zeroreg : tregister; begin firstcomplex(self); @@ -681,7 +680,7 @@ procedure TSparcAddNode.second_add64bit; tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist,OS_INT) else tempreg64.reglo := left.location.registerlow; - if ((right.location.valueqword shr 32) <> 0) then + if (hi(right.location.valueqword) <> 0) then tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist,OS_INT) else tempreg64.reghi := left.location.registerhigh; @@ -690,25 +689,25 @@ procedure TSparcAddNode.second_add64bit; if (right.location.valueqword <> 0) then { negative values can be handled using SUB, } { positive values < 65535 using XOR. } - if (longint(right.location.valueqword) >= -32767) and - (longint(right.location.valueqword) < 0) then + if (longint(lo(right.location.valueqword)) >= -32767) and + (longint(lo(right.location.valueqword)) < 0) then cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT, - right.location.valueqword, + lo(right.location.valueqword), left.location.registerlow,tempreg64.reglo) else cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT, - right.location.valueqword, + lo(right.location.valueqword), left.location.registerlow,tempreg64.reglo); - if ((right.location.valueqword shr 32) <> 0) then - if (longint(right.location.valueqword shr 32) >= -32767) and - (longint(right.location.valueqword shr 32) < 0) then + if (hi(right.location.valueqword)<>0) then + if (longint(hi(right.location.valueqword))>= -32767) and + (longint(hi(right.location.valueqword)) < 0) then cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT, - right.location.valueqword shr 32, + hi(right.location.valueqword), left.location.registerhigh,tempreg64.reghi) else cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT, - right.location.valueqword shr 32, + hi(right.location.valueqword), left.location.registerhigh,tempreg64.reghi); end else @@ -720,14 +719,14 @@ procedure TSparcAddNode.second_add64bit; tempreg64); end; - r.enum:=R_G0; - cg.a_reg_alloc(exprasmlist,r); - exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR,r, - tempreg64.reglo,tempreg64.reghi)); - cg.a_reg_dealloc(exprasmlist,r); - if (tempreg64.reglo.enum <> left.location.registerlow.enum) then + zeroreg.enum:=R_INTREGISTER; + zeroreg.number:=NR_G0; + cg.a_reg_alloc(exprasmlist,zeroreg); + exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR,zeroreg,tempreg64.reglo,tempreg64.reghi)); + cg.a_reg_dealloc(exprasmlist,zeroreg); + if (tempreg64.reglo.number <> left.location.registerlow.number) then cg.free_scratch_reg(exprasmlist,tempreg64.reglo); - if (tempreg64.reghi.enum <> left.location.registerhigh.enum) then + if (tempreg64.reghi.number <> left.location.registerhigh.number) then cg.free_scratch_reg(exprasmlist,tempreg64.reghi); location_reset(location,LOC_FLAGS,OS_NO); @@ -735,7 +734,7 @@ procedure TSparcAddNode.second_add64bit; end; xorn,orn,andn,addn: begin - if (location.registerlow.enum = R_NO) then + if (location.registerlow.number = NR_NO) then begin location.registerlow := rg.getregisterint(exprasmlist,OS_INT); location.registerhigh := rg.getregisterint(exprasmlist,OS_INT); @@ -757,7 +756,7 @@ procedure TSparcAddNode.second_add64bit; if left.location.loc <> LOC_CONSTANT then begin - if (location.registerlow.enum = R_NO) then + if (location.registerlow.number = NR_NO) then begin location.registerlow := rg.getregisterint(exprasmlist,OS_INT); location.registerhigh := rg.getregisterint(exprasmlist,OS_INT); @@ -775,7 +774,7 @@ procedure TSparcAddNode.second_add64bit; end else if ((left.location.valueqword shr 32) = 0) then begin - if (location.registerlow.enum = R_NO) then + if (location.registerlow.number = NR_NO) then begin location.registerlow := rg.getregisterint(exprasmlist,OS_INT); location.registerhigh := rg.getregisterint(exprasmlist,OS_INT); @@ -802,7 +801,7 @@ procedure TSparcAddNode.second_add64bit; else if (left.location.valueqword = 0) then begin // (const32 shl 32) - reg64 - if (location.registerlow.enum = R_NO) then + if (location.registerlow.number = NR_NO) then begin location.registerlow := rg.getregisterint(exprasmlist,OS_INT); location.registerhigh := rg.getregisterint(exprasmlist,OS_INT); @@ -821,7 +820,7 @@ procedure TSparcAddNode.second_add64bit; def_cgsize(left.resulttype.def),true); if (left.location.loc = LOC_REGISTER) then location.register64 := left.location.register64 - else if (location.registerlow.enum = R_NO) then + else if (location.registerlow.number = NR_NO) then begin location.registerlow := rg.getregisterint(exprasmlist,OS_INT); location.registerhigh := rg.getregisterint(exprasmlist,OS_INT); @@ -1009,30 +1008,21 @@ procedure TSparcAddNode.set_result_location(cmpOp,unsigned:Boolean); ELSE location_copy(location,left.location); end; -function def_opsize(p1:tdef):topsize; - begin - case p1.size of - 1:def_opsize:=S_B; - 2:def_opsize:=S_W; - 4:def_opsize:=S_L; - 8:def_opsize:=S_L; - else - InternalError(130820001); - end; - end; + + procedure TSparcAddNode.pass_2; {is also being used for "xor", and "mul", "sub", or and comparative operators} var popeax,popedx,pushedfpu,mboverflow,cmpop:Boolean; op:TAsmOp; power:LongInt; - OpSize:TOpSize; + OpSize:TcgSize; unsigned:Boolean;{true, if unsigned types are compared} extra_not:Boolean; cgop:TOpCg; begin -{to make it more readable, string and set (not smallset!) have their own -procedures } + { to make it more readable, string and set (not smallset!) have their own + procedures } case left.resulttype.def.deftype of orddef: if is_boolean(left.resulttype.def)and is_boolean(right.resulttype.def) @@ -1070,7 +1060,7 @@ procedures } cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln]; unsigned:=not(is_signed(left.resulttype.def))or not(is_signed(right.resulttype.def)); - opsize:=def_opsize(left.resulttype.def); + opsize:=def_cgsize(left.resulttype.def); pass_left_and_right; { set result location } if not cmpop @@ -1079,8 +1069,7 @@ procedures } else location_reset(location,LOC_FLAGS,OS_NO); load_left_right(cmpop,(cs_check_overflow in aktlocalswitches)and(nodetype in [addn,subn,muln])); - if(location.register.enum = R_NO)and not(cmpop) - then + if (location.register.number = NR_NO) and not(cmpop) then location.register := rg.getregisterint(exprasmlist,OS_INT); if not(cs_check_overflow in aktlocalswitches)or cmpop or (nodetype in [orn,andn,xorn]) then @@ -1122,22 +1111,18 @@ procedures } CGMessage(type_e_mismatch); end; { Convert flags to register first } - if(left.location.loc=LOC_FLAGS) - then - location_force_reg(exprasmlist,left.location,opsize_2_cgsize[opsize],false); - if (right.location.loc=LOC_FLAGS) - then - location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false); + if (left.location.loc=LOC_FLAGS) then + location_force_reg(exprasmlist,left.location,opsize,false); + if (right.location.loc=LOC_FLAGS) then + location_force_reg(exprasmlist,right.location,opsize,false); left_must_be_reg(OpSize,false); - if not cmpOp - then + if not cmpOp then emit_generic_code(op,opsize,unsigned,extra_not,mboverflow) else emit_compare(unsigned); location_freetemp(exprasmlist,right.location); location_release(exprasmlist,right.location); - if cmpop and(left.location.loc<>LOC_CREGISTER) - then + if cmpop and (left.location.loc<>LOC_CREGISTER) then begin location_freetemp(exprasmlist,left.location); location_release(exprasmlist,left.location); @@ -1176,12 +1161,18 @@ procedure TSparcAddNode.pass_left_and_right; left.location.register := tmpreg; end; end; + begin cAddNode:=TSparcAddNode; end. { $Log$ - Revision 1.13 2003-05-07 15:05:37 mazen + Revision 1.14 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.13 2003/05/07 15:05:37 mazen * fixed generated code for compare instructions Revision 1.12 2003/05/06 21:37:58 mazen diff --git a/compiler/sparc/ncpumat.pas b/compiler/sparc/ncpumat.pas index f2c4df986b..800274d27e 100644 --- a/compiler/sparc/ncpumat.pas +++ b/compiler/sparc/ncpumat.pas @@ -150,7 +150,7 @@ implementation rg.UnGetRegisterInt(exprasmlist,divider); end; { free used registers } - if numerator.enum <> resultreg.enum then + if numerator.number <> resultreg.number then rg.ungetregisterint(exprasmlist,numerator); { set result location } location.loc:=LOC_REGISTER; @@ -479,7 +479,12 @@ begin end. { $Log$ - Revision 1.7 2003-03-15 22:51:58 mazen + Revision 1.8 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.7 2003/03/15 22:51:58 mazen * remaking sparc rtl compile Revision 1.6 2003/03/10 21:59:54 mazen diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas index 8cff7719ab..5c500ef8ad 100644 --- a/compiler/x86/aasmcpu.pas +++ b/compiler/x86/aasmcpu.pas @@ -85,7 +85,7 @@ interface OT_FPU0 = $01000800; { FPU stack register zero } OT_REG_SMASK = $00070000; { special register operands: these may be treated differently } { a mask for the following } - OT_REG_ACCUM = $00211000; { accumulator: AL, AX or EAX } + OT_REG_ACCUM = $00211000; { FUNCTION_RETURN_REG: AL, AX or EAX } OT_REG_AL = $00211001; { REG_ACCUM | BITSxx } OT_REG_AX = $00211002; { ditto } OT_REG_EAX = $00211004; { and again } @@ -2024,7 +2024,12 @@ implementation end. { $Log$ - Revision 1.3 2003-05-22 21:33:31 peter + Revision 1.4 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.3 2003/05/22 21:33:31 peter * removed some unit dependencies Revision 1.2 2002/04/25 16:12:09 florian diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas index 8f9c8782f2..d2aef70845 100644 --- a/compiler/x86/cgx86.pas +++ b/compiler/x86/cgx86.pas @@ -309,9 +309,14 @@ unit cgx86; class function tcgx86.reg_cgsize(const reg: tregister): tcgsize; const - regsize_2_cgsize: array[S_B..S_L] of tcgsize = (OS_8,OS_16,OS_32); + opsize_2_cgsize: array[topsize] of tcgsize = (OS_NO, + OS_8,OS_16,OS_32,OS_NO,OS_NO,OS_NO, + OS_32,OS_64,OS_64, + OS_F32,OS_F64,OS_F80,OS_F32,OS_F64,OS_NO,OS_NO, + OS_NO,OS_NO,OS_NO + ); begin - result := regsize_2_cgsize[reg2opsize(reg)]; + result := opsize_2_cgsize[reg2opsize(reg)]; end; @@ -1941,7 +1946,12 @@ unit cgx86; end. { $Log$ - Revision 1.47 2003-05-22 21:33:31 peter + Revision 1.48 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.47 2003/05/22 21:33:31 peter * removed some unit dependencies Revision 1.46 2003/05/16 14:33:31 peter diff --git a/compiler/x86/cpubase.pas b/compiler/x86/cpubase.pas index ac3358040c..97c6808d95 100644 --- a/compiler/x86/cpubase.pas +++ b/compiler/x86/cpubase.pas @@ -487,9 +487,6 @@ uses max_operands = 3; - lvaluelocations = [LOC_REFERENCE,LOC_CFPUREGISTER, - LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER]; - {# Constant defining possibly all registers which might require saving } ALL_REGISTERS = [firstreg..lastreg]; ALL_INTREGISTERS = [1..255]; @@ -715,7 +712,12 @@ implementation end. { $Log$ - Revision 1.4 2003-04-30 20:53:32 florian + Revision 1.5 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.4 2003/04/30 20:53:32 florian * error when address of an abstract method is taken * fixed some x86-64 problems * merged some more x86-64 and i386 code @@ -798,10 +800,10 @@ end. + very basic support for float128 type (x86-64 only) Revision 1.34 2002/11/17 18:26:16 mazen - * fixed a compilation bug accmulator-->accumulator, in definition of return_result_reg + * fixed a compilation bug accmulator-->FUNCTION_RETURN_REG, in definition of return_result_reg Revision 1.33 2002/11/17 17:49:08 mazen - + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one + + return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one Revision 1.32 2002/10/05 12:43:29 carl * fixes for Delphi 6 compilation diff --git a/compiler/x86/rax86.pas b/compiler/x86/rax86.pas index 9f15d6d66d..ae71f63a73 100644 --- a/compiler/x86/rax86.pas +++ b/compiler/x86/rax86.pas @@ -42,11 +42,15 @@ Procedure FWaitWarning; type T386Operand=class(TOperand) + opsize : topsize; + Procedure SetSize(_size:longint;force:boolean);override; Procedure SetCorrectSize(opcode:tasmop);override; end; T386Instruction=class(TInstruction) OpOrder : TOperandOrder; + opsize : topsize; + constructor Create; { Operand sizes } procedure AddReferenceSizes; procedure SetInstructionOpsize; @@ -85,7 +89,7 @@ implementation uses globtype,globals,systems,verbose, cpuinfo, - itx86att; + itx86att,cgx86; {$define ATTOP} {$define INTELOP} @@ -196,20 +200,27 @@ end; T386Operand *****************************************************************************} +Procedure T386Operand.SetSize(_size:longint;force:boolean); +begin + inherited SetSize(_size,force); + opsize:=TCGSize2Opsize[size]; +end; + + Procedure T386Operand.SetCorrectSize(opcode:tasmop); begin if gas_needsuffix[opcode]=attsufFPU then begin - case size of - S_L : size:=S_FS; - S_IQ : size:=S_FL; + case opsize of + S_L : opsize:=S_FS; + S_IQ : opsize:=S_FL; end; end else if gas_needsuffix[opcode]=attsufFPUint then begin - case size of - S_W : size:=S_IS; - S_L : size:=S_IL; + case opsize of + S_W : opsize:=S_IS; + S_L : opsize:=S_IL; end; end; end; @@ -219,6 +230,13 @@ end; T386Instruction *****************************************************************************} +constructor T386Instruction.Create; +begin + inherited Create; + Opsize:=S_NO; +end; + + procedure T386Instruction.SwapOperands; begin Inherited SwapOperands; @@ -242,7 +260,7 @@ begin for i:=1to ops do begin operands[i].SetCorrectSize(opcode); - if (operands[i].size=S_NO) then + if t386operand(operands[i]).opsize=S_NO then begin case operands[i].Opr.Typ of OPR_REFERENCE : @@ -265,19 +283,19 @@ begin { if no register then take the opsize (which is available with ATT), if not availble then give an error } if opsize<>S_NO then - operands[i].size:=opsize + t386operand(operands[i]).opsize:=opsize else begin Message(asmr_e_unable_to_determine_reference_size); { recovery } - operands[i].size:=S_L; + t386operand(operands[i]).opsize:=S_L; end; end; end else begin if opsize<>S_NO then - operands[i].size:=opsize + t386operand(operands[i]).opsize:=opsize end; end; OPR_SYMBOL : @@ -292,7 +310,7 @@ begin operands[i].opr.ref.symbol:=s; operands[i].opr.ref.offset:=so; end; - operands[i].size:=S_L; + t386operand(operands[i]).opsize:=S_L; end; end; end; @@ -319,20 +337,20 @@ begin (operands[1].opr.reg.number<=nlastsreg))) then opsize:=S_L else - opsize:=operands[1].size; + opsize:=t386operand(operands[1]).opsize; 2 : begin case opcode of A_MOVZX,A_MOVSX : begin - case operands[1].size of + case t386operand(operands[1]).opsize of S_W : - case operands[2].size of + case t386operand(operands[2]).opsize of S_L : opsize:=S_WL; end; S_B : - case operands[2].size of + case t386operand(operands[2]).opsize of S_W : opsize:=S_BW; S_L : @@ -344,13 +362,13 @@ begin 32 bit register or memory, so no opsize is correct here PM } exit; A_OUT : - opsize:=operands[1].size; + opsize:=t386operand(operands[1]).opsize; else - opsize:=operands[2].size; + opsize:=t386operand(operands[2]).opsize; end; end; 3 : - opsize:=operands[3].size; + opsize:=t386operand(operands[3]).opsize; end; end; @@ -391,11 +409,11 @@ begin begin case opsize of S_BW : - sizeerr:=(operands[1].size<>S_B) or (operands[2].size<>S_W); + sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_W); S_BL : - sizeerr:=(operands[1].size<>S_B) or (operands[2].size<>S_L); + sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_L); S_WL : - sizeerr:=(operands[1].size<>S_W) or (operands[2].size<>S_L); + sizeerr:=(t386operand(operands[1]).opsize<>S_W) or (t386operand(operands[2]).opsize<>S_L); end; end; end @@ -404,8 +422,8 @@ begin for i:=1 to ops do begin if (operands[i].opr.typ<>OPR_CONSTANT) and - (operands[i].size in [S_B,S_W,S_L]) and - (operands[i].size<>opsize) then + (t386operand(operands[i]).opsize in [S_B,S_W,S_L]) and + (t386operand(operands[i]).opsize<>opsize) then sizeerr:=true; end; end; @@ -483,19 +501,21 @@ begin else begin if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then - siz:=operands[1].size + siz:=t386operand(operands[1]).opsize else - siz:=operands[Ops].size; + siz:=t386operand(operands[Ops]).opsize; { MOVD should be of size S_LQ or S_QL, but these do not exist PM } - if (ops=2) and (operands[1].size<>S_NO) and - (operands[2].size<>S_NO) and (operands[1].size<>operands[2].size) then + if (ops=2) and + (t386operand(operands[1]).opsize<>S_NO) and + (t386operand(operands[2]).opsize<>S_NO) and + (t386operand(operands[1]).opsize<>t386operand(operands[2]).opsize) then siz:=S_NO; end; if ((opcode=A_MOVD)or (opcode=A_CVTSI2SS)) and - ((operands[1].size=S_NO) or - (operands[2].size=S_NO)) then + ((t386operand(operands[1]).opsize=S_NO) or + (t386operand(operands[2]).opsize=S_NO)) then siz:=S_NO; { NASM does not support FADD without args as alias of FADDP @@ -636,10 +656,10 @@ begin OPR_REFERENCE: begin ai.loadref(i-1,operands[i].opr.ref); - if operands[i].size<>S_NO then + if t386operand(operands[i]).opsize<>S_NO then begin asize:=0; - case operands[i].size of + case t386operand(operands[i]).opsize of S_B : asize:=OT_BITS8; S_W, S_IS : @@ -684,7 +704,12 @@ end; end. { $Log$ - Revision 1.2 2003-05-22 21:33:31 peter + Revision 1.3 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.2 2003/05/22 21:33:31 peter * removed some unit dependencies Revision 1.1 2003/04/30 15:45:35 florian diff --git a/compiler/x86_64/cpubase.inc b/compiler/x86_64/cpubase.inc index 9fd04520a6..cf21994c2f 100644 --- a/compiler/x86_64/cpubase.inc +++ b/compiler/x86_64/cpubase.inc @@ -163,29 +163,26 @@ const *****************************************************************************} {# Stack pointer register } - stack_pointer_reg = R_RSP; NR_STACK_POINTER_REG = NR_RSP; {# Frame pointer register } - frame_pointer_reg = R_RBP; NR_FRAME_POINTER_REG = NR_RBP; { Register for addressing absolute data in a position independant way, such as in PIC code. The exact meaning is ABI specific. For further information look at GCC source : PIC_OFFSET_TABLE_REGNUM } - pic_offset_reg = R_EBX; - accumulator = R_RAX; - RS_ACCUMULATOR = RS_RAX; - NR_ACCUMULATOR = NR_RAX; - { the return_result_reg, is used inside the called function to store its return - value when that is a scalar value otherwise a pointer to the address of the - result is placed inside it } - return_result_reg = accumulator; - RS_RETURN_RESULT_REG = RS_ACCUMULATOR; - NR_RETURN_RESULT_REG = NR_ACCUMULATOR; - - { the function_result_reg contains the function result after a call to a scalar - function othewise it contains a pointer to the returned result} - function_result_reg = accumulator; + NR_PIC_OFFSET_REG = NR_EBX; + { Results are returned in this register (32-bit values) } + NR_FUNCTION_RETURN_REG = NR_RAX; + RS_FUNCTION_RETURN_REG = RS_RAX; + { High part of 64bit return value } + NR_FUNCTION_RETURNHIGH_REG = NR_NONE; + RS_FUNCTION_RETURNHIGH_REG = RS_NONE; + { The value returned from a function is available in this register } + NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG; + RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG; + { The high part of 64bit value returned from a function is available in this register } + NR_FUNCTION_RESULTHIGH_REG = NR_FUNCTION_RETURNHIGH_REG; + RS_FUNCTION_RESULTHIGH_REG = RS_FUNCTION_RETURNHIGH_REG; fpu_result_reg = R_ST; mmresultreg = R_MM0; @@ -214,7 +211,12 @@ const { $Log$ - Revision 1.3 2003-04-30 15:45:35 florian + Revision 1.4 2003-05-30 23:57:08 peter + * more sparc cleanup + * accumulator removed, splitted in function_return_reg (called) and + function_result_reg (caller) + + Revision 1.3 2003/04/30 15:45:35 florian * merged more x86-64/i386 code Revision 1.2 2002/04/25 16:12:09 florian