diff --git a/compiler/powerpc/agppcmpw.pas b/compiler/powerpc/agppcmpw.pas index 4563487655..0c40c59d70 100644 --- a/compiler/powerpc/agppcmpw.pas +++ b/compiler/powerpc/agppcmpw.pas @@ -70,7 +70,11 @@ interface const line_length = 70; - use_PR = false; {Whether internal references should be xxx[PR] } + + {Whether internal procedure references should be xxx[PR]: } + use_PR = false; + + const_storage_class = '[RW]'; function ReplaceForbiddenChars(var s: string):Boolean; @@ -721,10 +725,20 @@ function getreferencestring(var ref : treference) : string; else AsmWriteLn(#9'export'#9+s); - AsmWriteLn(#9'csect'#9+s+'[TC]'); - AsmWriteLn(PadTabs(s+':',#0)+'ds.b '+tostr(tai_datablock(hp).size)); - {TODO: ? PadTabs(s,#0) } + if not macos_direct_globals then + begin + AsmWriteLn(#9'toc'); + AsmWriteLn(#9'tc'#9+s+'[TC], '+s+'[RW]'); + AsmWriteLn(#9'csect'#9+s+'[RW]'); + AsmWriteLn(#9'ds.b '+tostr(tai_datablock(hp).size)); + end + else + begin + AsmWriteLn(#9'csect'#9+s+'[TC]'); + AsmWriteLn(PadTabs(s+':',#0)+'ds.b '+tostr(tai_datablock(hp).size)); + {TODO: ? PadTabs(s,#0) } + end; end; ait_const_32bit, ait_const_8bit, @@ -765,10 +779,15 @@ function getreferencestring(var ref : treference) : string; if use_PR then AsmWriteLn(#9'dc.l'#9'.'+ s +'[PR]') else - AsmWriteLn(#9'dc.l'#9'.'+ s) + AsmWriteLn(#9'dc.l'#9 + s + '[DS]') end else - AsmWriteLn(#9'dc.l'#9+ s); + begin + if macos_direct_globals then + AsmWriteLn(#9'dc.l'#9+s) + else + AsmWriteLn(#9'dc.l'#9+s+const_storage_class); + end; (* TODO: the following might need to be included. Temporaily we generate an error @@ -872,18 +891,22 @@ function getreferencestring(var ref : treference) : string; begin s:= tai_label(hp).l.name; ReplaceForbiddenChars(s); - if s[1] <> '@' then - AsmWriteLn(#9'csect'#9+s+'[TC]'); - - AsmWrite(s); - {if assigned(hp.next) and not(tai(hp.next).typ in - [ait_const_32bit,ait_const_16bit,ait_const_8bit, - ait_const_symbol,ait_const_rva, - ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then - AsmWriteLn(':') + if s[1] = '@' then + AsmWriteLn(s+':') else - DoNotSplitLine:=true;} - AsmWriteLn(':'); + begin + if not macos_direct_globals then + begin + AsmWriteLn(#9'toc'); + AsmWriteLn(#9'tc'#9+s+'[TC], '+s+const_storage_class); + AsmWriteLn(#9'csect'#9+s+const_storage_class); + end + else + begin + AsmWriteLn(#9'csect'#9+s+'[TC]'); + AsmWriteLn(PadTabs(s+':',#0)); + end; + end; end; end; ait_direct: @@ -903,10 +926,20 @@ function getreferencestring(var ref : treference) : string; if replaced then AsmWriteLn(#9'export'#9+s+' => '''+tai_symbol(hp).sym.name+'''') else - AsmWriteLn(#9'export'#9+s); - AsmWriteLn(#9'csect'#9+s+'[TC]'); - AsmWrite(s); - AsmWriteLn(':'); + AsmWriteLn(#9'export'#9+s+'[RW]'); + + + if not macos_direct_globals then + begin + AsmWriteLn(#9'toc'); + AsmWriteLn(#9'tc'#9+s+'[TC], '+s+ const_storage_class); + AsmWriteLn(#9'csect'#9+s+ const_storage_class); + end + else + begin + AsmWriteLn(#9'csect'#9+s+'[TC]'); + AsmWriteLn(s+':'); + end; end; end; ait_symbol_end: @@ -1008,7 +1041,11 @@ ait_stab_function_name : ; if ReplaceForbiddenChars(s) then currentasmlist.AsmWriteLn(#9'import'#9+s+' <= '''+p.name+'''') else - currentasmlist.AsmWriteLn(#9'import'#9+s); + begin + currentasmlist.AsmWriteLn(#9'import'#9+s+'[RW]'); + currentasmlist.AsmWriteLn(#9'toc'); + currentasmlist.AsmWriteLn(#9'tc'#9+s+'[TC],'+s+'[RW]'); + end; end; end; end; @@ -1059,7 +1096,7 @@ ait_stab_function_name : ; AsmLn; *) - AsmWriteLn(#9'STRING ASIS'); {Interpret strings just to be the content between the quotes.} + AsmWriteLn(#9'string asis'); {Interpret strings just to be the content between the quotes.} AsmLn; end; @@ -1122,7 +1159,11 @@ initialization end. { $Log$ - Revision 1.17 2003-01-08 18:43:57 daniel + Revision 1.18 2003-01-13 17:17:50 olle + * changed global var access, TOC now contain pointers to globals + * fixed handling of function pointers + + Revision 1.17 2003/01/08 18:43:57 daniel * Tregister changed into a record Revision 1.16 2002/11/28 10:56:07 olle diff --git a/compiler/powerpc/cgcpu.pas b/compiler/powerpc/cgcpu.pas index 946c8ce312..7fe3c5dc30 100644 --- a/compiler/powerpc/cgcpu.pas +++ b/compiler/powerpc/cgcpu.pas @@ -242,41 +242,82 @@ const end; - { calling a code fragment by name } + { calling a procedure by name } procedure tcgppc.a_call_name(list : taasmoutput;const s : string); var href : treference; begin + {MacOS: The linker on MacOS (PPCLink) inserts a call to glue code, + if it is a cross-TOC call. If so, it also replaces the NOP + with some restore code.} list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s))); if target_info.system=system_powerpc_macos then list.concat(taicpu.op_none(A_NOP)); procinfo.flags:=procinfo.flags or pi_do_call; end; - + { calling a procedure by address } procedure tcgppc.a_call_reg(list : taasmoutput;reg: tregister); + + var + tmpreg : tregister; + tmpref : treference; + begin - list.concat(taicpu.op_reg(A_MTCTR,reg)); - list.concat(taicpu.op_none(A_BCTRL)); if target_info.system=system_powerpc_macos then - list.concat(taicpu.op_none(A_NOP)); + begin + {Generate instruction to load the procedure address from + the transition vector.} + //TODO: Support cross-TOC calls. + tmpreg := get_scratch_reg_int(list); + reference_reset(tmpref); + tmpref.offset := 0; + //tmpref.symaddr := refs_full; + tmpref.base:= reg; + list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref)); + list.concat(taicpu.op_reg(A_MTCTR,tmpreg)); + free_scratch_reg(list,tmpreg); + end + else + list.concat(taicpu.op_reg(A_MTCTR,reg)); + list.concat(taicpu.op_none(A_BCTRL)); + //if target_info.system=system_powerpc_macos then + // //NOP is not needed here. + // list.concat(taicpu.op_none(A_NOP)); procinfo.flags:=procinfo.flags or pi_do_call; + //list.concat(tai_comment.create(strpnew('***** a_call_reg'))); end; - { calling a code fragment through a reference } + { calling a procedure by address } procedure tcgppc.a_call_ref(list : taasmoutput;const ref : treference); + var tmpreg : tregister; + tmpref : treference; + begin tmpreg := get_scratch_reg_int(list); a_load_ref_reg(list,OS_ADDR,ref,tmpreg); + if target_info.system=system_powerpc_macos then + begin + {Generate instruction to load the procedure address from + the transition vector.} + //TODO: Support cross-TOC calls. + reference_reset(tmpref); + tmpref.offset := 0; + //tmpref.symaddr := refs_full; + tmpref.base:= tmpreg; + list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref)); + end; list.concat(taicpu.op_reg(A_MTCTR,tmpreg)); free_scratch_reg(list,tmpreg); list.concat(taicpu.op_none(A_BCTRL)); - if target_info.system=system_powerpc_macos then - list.concat(taicpu.op_none(A_NOP)); + //if target_info.system=system_powerpc_macos then + // //NOP is not needed here. + // list.concat(taicpu.op_none(A_NOP)); procinfo.flags:=procinfo.flags or pi_do_call; + //list.concat(tai_comment.create(strpnew('***** a_call_ref'))); end; {********************** load instructions ********************} @@ -1428,7 +1469,7 @@ const var ref2, tmpref: treference; freereg: boolean; - r2:Tregister; + r2,tmpreg:Tregister; begin ref2 := ref; @@ -1440,14 +1481,35 @@ const if ref2.base.enum <> R_NO then internalerror(2002103102); //TODO: Implement this if needed - reference_reset(tmpref); - tmpref.offset := ref2.offset; - tmpref.symbol := ref2.symbol; - tmpref.symaddr := refs_full; - tmpref.base.enum := R_NO; - r2.enum:=R_TOC; - list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r2,tmpref)); - end + if macos_direct_globals then + begin + reference_reset(tmpref); + tmpref.offset := ref2.offset; + tmpref.symbol := ref2.symbol; + tmpref.symaddr := refs_full; + tmpref.base.enum := R_NO; + r2.enum:=R_TOC; + list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r2,tmpref)); + end + else + begin + tmpreg := get_scratch_reg_address(list); + reference_reset(tmpref); + tmpref.symbol := ref2.symbol; + tmpref.offset := ref2.offset; + tmpref.symaddr := refs_full; + tmpref.base.enum:= R_TOC; + list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref)); + + reference_reset(tmpref); + tmpref.offset := 0; + tmpref.symaddr := refs_full; + tmpref.base:= tmpreg; + list.concat(taicpu.op_reg_ref(A_LA,r,tmpref)); + free_scratch_reg(list,tmpreg); + end; + //list.concat(tai_comment.create(strpnew('*** a_loadaddr_ref_reg'))); + end else begin @@ -1826,35 +1888,80 @@ const begin if ref.base.enum <> R_NO then begin - {Generates - add tempreg, ref.base, RTOC - op reg, symbolplusoffset, tempreg - which is eqvivalent to the more comprehensive - addi tempreg, RTOC, symbolplusoffset - add tempreg, ref.base, RTOC - op reg, tempreg - but which saves one instruction.} + if macos_direct_globals then + begin + {Generates + add tempreg, ref.base, RTOC + op reg, symbolplusoffset, tempreg + which is eqvivalent to the more comprehensive + addi tempreg, RTOC, symbolplusoffset + add tempreg, ref.base, tempreg + op reg, tempreg + but which saves one instruction.} - tmpreg := get_scratch_reg_address(list); - reference_reset(tmpref); - tmpref.symbol := ref.symbol; - tmpref.offset := ref.offset; - tmpref.symaddr := refs_full; - tmpref.base:= tmpreg; + tmpreg := get_scratch_reg_address(list); + reference_reset(tmpref); + tmpref.symbol := ref.symbol; + tmpref.offset := ref.offset; + tmpref.symaddr := refs_full; + tmpref.base:= tmpreg; - r.enum:=R_TOC; - list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg, - ref.base,r)); - list.concat(taicpu.op_reg_ref(op,reg,tmpref)); + r.enum:=R_TOC; + list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg, + ref.base,r)); + list.concat(taicpu.op_reg_ref(op,reg,tmpref)); + end + else + begin + tmpreg := get_scratch_reg_address(list); + reference_reset(tmpref); + tmpref.symbol := ref.symbol; + tmpref.offset := ref.offset; + tmpref.symaddr := refs_full; + tmpref.base.enum:= R_TOC; + list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref)); + list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg, + ref.base,tmpreg)); + + reference_reset(tmpref); + tmpref.offset := 0; + tmpref.symaddr := refs_full; + tmpref.base:= tmpreg; + list.concat(taicpu.op_reg_ref(op,reg,tmpref)); + + end; + + //list.concat(tai_comment.create(strpnew('**** a_load_store 1'))); end else begin - reference_reset(tmpref); - tmpref.symbol := ref.symbol; - tmpref.offset := ref.offset; - tmpref.symaddr := refs_full; - tmpref.base.enum:= R_TOC; - list.concat(taicpu.op_reg_ref(op,reg,tmpref)); + if macos_direct_globals then + begin + reference_reset(tmpref); + tmpref.symbol := ref.symbol; + tmpref.offset := ref.offset; + tmpref.symaddr := refs_full; + tmpref.base.enum:= R_TOC; + list.concat(taicpu.op_reg_ref(op,reg,tmpref)); + end + else + begin + tmpreg := get_scratch_reg_address(list); + reference_reset(tmpref); + tmpref.symbol := ref.symbol; + tmpref.offset := ref.offset; + tmpref.symaddr := refs_full; + tmpref.base.enum:= R_TOC; + list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref)); + + reference_reset(tmpref); + tmpref.offset := 0; + tmpref.symaddr := refs_full; + tmpref.base:= tmpreg; + list.concat(taicpu.op_reg_ref(op,reg,tmpref)); + + end; + //list.concat(tai_comment.create(strpnew('*** a_load_store 2'))); end; end else @@ -2000,7 +2107,11 @@ begin end. { $Log$ - Revision 1.69 2003-01-09 22:00:53 florian + Revision 1.70 2003-01-13 17:17:50 olle + * changed global var access, TOC now contain pointers to globals + * fixed handling of function pointers + + Revision 1.69 2003/01/09 22:00:53 florian * fixed some PowerPC issues Revision 1.68 2003/01/08 18:43:58 daniel diff --git a/compiler/powerpc/cpubase.pas b/compiler/powerpc/cpubase.pas index 8c8fb869af..c4e8298d36 100644 --- a/compiler/powerpc/cpubase.pas +++ b/compiler/powerpc/cpubase.pas @@ -112,7 +112,7 @@ uses R_CR,R_CR0,R_CR1,R_CR2,R_CR3,R_CR4,R_CR5,R_CR6,R_CR7, R_XER,R_LR,R_CTR,R_FPSCR ); - + Tregister=record enum:Toldregister; number:word; @@ -309,6 +309,11 @@ uses const symaddr2str: array[trefsymaddr] of string[3] = ('','@ha','@l'); + const + { MacOS only. Whether the direct data area (TOC) directly contain + global variables. Otherwise it contains pointers to global variables. } + macos_direct_globals = false; + {***************************************************************************** Operand *****************************************************************************} @@ -755,7 +760,11 @@ implementation end. { $Log$ - Revision 1.40 2003-01-09 15:49:56 daniel + Revision 1.41 2003-01-13 17:17:50 olle + * changed global var access, TOC now contain pointers to globals + * fixed handling of function pointers + + Revision 1.40 2003/01/09 15:49:56 daniel * Added register conversion Revision 1.39 2003/01/08 18:43:58 daniel