diff options
Diffstat (limited to 'compiler/alpha/radirect.pas')
-rw-r--r-- | compiler/alpha/radirect.pas | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/compiler/alpha/radirect.pas b/compiler/alpha/radirect.pas new file mode 100644 index 0000000000..68f56bc747 --- /dev/null +++ b/compiler/alpha/radirect.pas @@ -0,0 +1,313 @@ +{ + Copyright (c) 1998-2002 by Florian Klaempfl + + Reads inline Alpha assembler and writes the lines direct to the output + + 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 + (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 + 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 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} +{ + This unit reads Alpha inline assembler and writes the lines direct to the output file. +} +unit radirect; + +{$i fpcdefs.inc} + +interface + + uses + node; + + function assemble : tnode; + + implementation + + uses + { common } + cutils, + { global } + globals,verbose, + systems, + { aasm } + aasmbase,aasmtai,aasmcpu, + { symtable } + symconst,symbase,symtype,symsym,symtable,defbase, + { pass 1 } + nbas, + { parser } + scanner, + { codegen } + cgbase, + { constants } + agaxpgas, + cpubase + ; + + function assemble : tnode; + + var + retstr,s,hs : string; + c : char; + ende : boolean; + srsym,sym : tsym; + srsymtable : tsymtable; + code : TAAsmoutput; + i,l : longint; + + procedure writeasmline; + var + i : longint; + begin + i:=length(s); + while (i>0) and (s[i] in [' ',#9]) do + dec(i); + s[0]:=chr(i); + if s<>'' then + code.concat(Tai_direct.Create(strpnew(s))); + { consider it set function set if the offset was loaded } + if assigned(aktprocdef.funcretsym) and + (pos(retstr,upper(s))>0) then + tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned; + s:=''; + end; + + begin + ende:=false; + s:=''; + if assigned(aktprocdef.funcretsym) and + is_fpu(aktprocdef.rettype.def) then + tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned; + { !!!!! + if (not is_void(aktprocdef.rettype.def)) then + retstr:=upper(tostr(procinfo^.return_offset)+'('+gas_reg2str[procinfo^.framepointer]+')') + else + } + retstr:=''; + + c:=current_scanner.asmgetchar; + code:=TAAsmoutput.Create; + while not(ende) do + begin + { wrong placement + current_scanner.gettokenpos; } + case c of + 'A'..'Z','a'..'z','_': + begin + current_scanner.gettokenpos; + i:=0; + hs:=''; + while ((ord(c)>=ord('A')) and (ord(c)<=ord('Z'))) + or ((ord(c)>=ord('a')) and (ord(c)<=ord('z'))) + or ((ord(c)>=ord('0')) and (ord(c)<=ord('9'))) + or (c='_') do + begin + inc(i); + hs[i]:=c; + c:=current_scanner.asmgetchar; + end; + hs[0]:=chr(i); + if upper(hs)='END' then + ende:=true + else + begin + if c=':' then + begin + searchsym(upper(hs),srsym,srsymtable); + if srsym<>nil then + if (srsym.typ = labelsym) then + Begin + hs:=tlabelsym(srsym).lab.name; + tlabelsym(srsym).lab.is_set:=true; + end + else + Message(asmr_w_using_defined_as_local); + end + else + { access to local variables } + if assigned(aktprocdef) then + begin + { I don't know yet, what the ppc port requires } + { we'll see how things settle down } + + { is the last written character an special } + { char ? } + { !!! + if (s[length(s)]='%') and + ret_in_acc(aktprocdef.rettype.def) and + ((pos('AX',upper(hs))>0) or + (pos('AL',upper(hs))>0)) then + tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned; + } + if ((s[length(s)]<>'0') or (hs[1]<>'x')) then + begin + if assigned(aktprocdef.localst) and + (lexlevel >= normal_function_level) then + sym:=tsym(aktprocdef.localst.search(upper(hs))) + else + sym:=nil; + if assigned(sym) then + begin + if (sym.typ=labelsym) then + Begin + hs:=tlabelsym(sym).lab.name; + end + else if sym.typ=varsym then + begin + if (vo_is_external in tvarsym(sym).varoptions) then + hs:=tvarsym(sym).mangledname + else + begin + if (tvarsym(sym).reg<>R_NO) then + hs:=gas_reg2str[procinfo.framepointer] + else + hs:=tostr(tvarsym(sym).address)+ + '('+gas_reg2str[procinfo.framepointer]+')'; + end; + end + else + { call to local function } + if (sym.typ=procsym) and (pos('BL',upper(s))>0) then + hs:=tprocsym(sym).first_procdef.mangledname; + end + else + begin + if assigned(aktprocdef.parast) then + sym:=tsym(aktprocdef.parast.search(upper(hs))) + else + sym:=nil; + if assigned(sym) then + begin + if sym.typ=varsym then + begin + l:=tvarsym(sym).address; + { set offset } + inc(l,aktprocdef.parast.address_fixup); + hs:=tostr(l)+'('+gas_reg2str[procinfo.framepointer]+')'; + if pos(',',s) > 0 then + tvarsym(sym).varstate:=vs_used; + end; + end + { I added that but it creates a problem in line.ppi + because there is a local label wbuffer and + a static variable WBUFFER ... + what would you decide, florian ?} + else + begin + searchsym(upper(hs),sym,srsymtable); + if assigned(sym) and (sym.owner.symtabletype in [globalsymtable,staticsymtable]) then + begin + case sym.typ of + varsym : + begin + Message2(asmr_h_direct_global_to_mangled,hs,tvarsym(sym).mangledname); + hs:=tvarsym(sym).mangledname; + inc(tvarsym(sym).refs); + end; + typedconstsym : + begin + Message2(asmr_h_direct_global_to_mangled,hs,ttypedconstsym(sym).mangledname); + hs:=ttypedconstsym(sym).mangledname; + end; + procsym : + begin + { procs can be called or the address can be loaded } + if (pos('BL',upper(s))>0) {or (pos('LEA',upper(s))>0))} then + begin + if Tprocsym(sym).procdef_count>1 then + Message1(asmr_w_direct_global_is_overloaded_func,hs); + Message2(asmr_h_direct_global_to_mangled,hs,tprocsym(sym).first_procdef.mangledname); + hs:=tprocsym(sym).first_procdef.mangledname; + end; + end; + else + Message(asmr_e_wrong_sym_type); + end; + end +{$ifdef dummy} + else if upper(hs)='__SELF' then + begin + if assigned(procinfo^._class) then + hs:=tostr(procinfo^.selfpointer_offset)+ + '('+gas_reg2str[procinfo^.framepointer]+')' + else + Message(asmr_e_cannot_use_SELF_outside_a_method); + end + else if upper(hs)='__RESULT' then + begin + if (not is_void(aktprocdef.rettype.def)) then + hs:=retstr + else + Message(asmr_e_void_function); + end + { implement old stack/frame pointer access for nested procedures } + {!!!! + else if upper(hs)='__OLDSP' then + begin + { complicate to check there } + { we do it: } + if lexlevel>normal_function_level then + hs:=tostr(procinfo^.framepointer_offset)+ + '('+gas_reg2str[procinfo^.framepointer]+')' + else + Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure); + end; + } + end; +{$endif dummy} + end; + end; + end; + end; + s:=s+hs; + end; + end; + '{',';',#10,#13: + begin + if pos(retstr,s) > 0 then + tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned; + writeasmline; + c:=current_scanner.asmgetchar; + end; + #26: + Message(scan_f_end_of_file); + else + begin + current_scanner.gettokenpos; + inc(byte(s[0])); + s[length(s)]:=c; + c:=current_scanner.asmgetchar; + end; + end; + end; + writeasmline; + assemble:=casmnode.create(code); + end; + +{***************************************************************************** + Initialize +*****************************************************************************} + +const + asmmode_ppc_direct_info : tasmmodeinfo = + ( + id : asmmode_direct; + idtxt : 'DIRECT' + ); + +initialization + RegisterAsmMode(asmmode_ppc_direct_info); + +end. |