{ Copyright (c) 1998-2006 by Carl Eric Codere and Peter Vreman Does the parsing for the x86-64 intel styled inline assembler. 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. **************************************************************************** } Unit rax64int; {$i fpcdefs.inc} interface uses aasmtai, rax86int; type tx8664intreader = class(tx86intreader) actsehdirective: TAsmSehDirective; function is_targetdirective(const s:string):boolean;override; procedure HandleTargetDirective;override; end; implementation uses globtype, cutils, systems, verbose, cgbase, symconst, procinfo, rabase; const { x86_64 subset of SEH directives. .seh_proc and .seh_endproc excluded because they are generated automatically when needed. } recognized_directives: set of TAsmSehDirective=[ ash_endprologue,ash_handler,ash_handlerdata, ash_setframe,ash_stackalloc,ash_pushreg, ash_savereg,ash_savexmm,ash_pushframe{, ash_pushnv,ash_savenv } ]; { max offset and bitmask for .seh_savereg and .seh_setframe } maxoffset: array[boolean] of aint=(high(dword), 240); modulo: array[boolean] of integer=(7, 15); function tx8664intreader.is_targetdirective(const s:string):boolean; var i: TAsmSehDirective; begin result:=false; if target_info.system<>system_x86_64_win64 then exit; for i:=low(TAsmSehDirective) to high(TAsmSehDirective) do begin if not (i in recognized_directives) then continue; if s=sehdirectivestr[i] then begin actsehdirective:=i; result:=true; break; end; end; { allow SEH directives only in pure assember routines } if result and not (po_assembler in current_procinfo.procdef.procoptions) then begin Message(asmr_e_seh_in_pure_asm_only); result:=false; end; end; procedure tx8664intreader.HandleTargetDirective; var hreg: TRegister; hnum: aint; flags: integer; ai: tai_seh_directive; hs: string; err: boolean; begin if actasmtoken<>AS_TARGET_DIRECTIVE then InternalError(2011100201); Consume(AS_TARGET_DIRECTIVE); Include(current_procinfo.flags,pi_has_unwind_info); case actsehdirective of { TODO: .seh_pushframe is supposed to have a boolean parameter, but GAS 2.21 does not support it. } ash_endprologue, ash_pushframe, ash_handlerdata: curlist.concat(cai_seh_directive.create(actsehdirective)); ash_handler: begin hs:=actasmpattern; Consume(AS_ID); flags:=0; err:=false; while actasmtoken=AS_COMMA do begin Consume(AS_COMMA); if actasmtoken=AS_ID then begin uppervar(actasmpattern); if actasmpattern='@EXCEPT' then flags:=flags or 1 else if actasmpattern='@UNWIND' then flags:=flags or 2 else err:=true; Consume(AS_ID); end else err:=true; if err then begin Message(asmr_e_syntax_error); RecoverConsume(false); exit; end; end; ai:=cai_seh_directive.create_name(ash_handler,hs); ai.data.flags:=flags; curlist.concat(ai); end; ash_stackalloc: begin hnum:=BuildConstExpression;//(false,false); if (hnum<0) or (hnum>high(dword)) or ((hnum and 7)<>0) then Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc]) else curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum)); end; //ash_pushnv, ash_pushreg: begin hreg:=actasmregister; Consume(AS_REGISTER); if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_pushreg]) else curlist.concat(cai_seh_directive.create_reg(ash_pushreg,hreg)); end; ash_setframe, ash_savereg: begin hreg:=actasmregister; Consume(AS_REGISTER); if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]); Consume(AS_COMMA); hnum:=BuildConstExpression;//(false,false); if (hnum<0) or (hnum>maxoffset[actsehdirective=ash_setframe]) or ((hnum mod modulo[actsehdirective=ash_setframe])<>0) then Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective]) else curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum)); end; //ash_savenv, ash_savexmm: begin hreg:=actasmregister; Consume(AS_REGISTER); if (getregtype(hreg)<>R_MMREGISTER) then Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_savexmm]); Consume(AS_COMMA); hnum:=BuildConstExpression;//(false,false); if (hnum<0) or (hnum>high(dword)) or ((hnum and 15)<>0) then Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_savexmm]) else curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum)); end; else InternalError(2018022401); end; if actasmtoken<>AS_SEPARATOR then Consume(AS_SEPARATOR); end; const asmmode_x86_64_intel_info : tasmmodeinfo = ( id : asmmode_x86_64_intel; idtxt : 'INTEL'; casmreader : tx8664intreader; ); initialization RegisterAsmMode(asmmode_x86_64_intel_info); end.