rax64int.pas 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. {
  2. Copyright (c) 1998-2006 by Carl Eric Codere and Peter Vreman
  3. Does the parsing for the x86-64 intel styled inline assembler.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. Unit rax64int;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. aasmtai,
  22. rax86int;
  23. type
  24. tx8664intreader = class(tx86intreader)
  25. actsehdirective: TAsmSehDirective;
  26. function is_targetdirective(const s:string):boolean;override;
  27. procedure HandleTargetDirective;override;
  28. end;
  29. implementation
  30. uses
  31. globtype,
  32. cutils,
  33. systems,
  34. verbose,
  35. cgbase,
  36. symconst,
  37. procinfo,
  38. rabase;
  39. const
  40. { x86_64 subset of SEH directives. .seh_proc and .seh_endproc excluded
  41. because they are generated automatically when needed. }
  42. recognized_directives: set of TAsmSehDirective=[
  43. ash_endprologue,ash_handler,ash_handlerdata,
  44. ash_setframe,ash_stackalloc,ash_pushreg,
  45. ash_savereg,ash_savexmm,ash_pushframe{,
  46. ash_pushnv,ash_savenv }
  47. ];
  48. { max offset and bitmask for .seh_savereg and .seh_setframe }
  49. maxoffset: array[boolean] of aint=(high(dword), 240);
  50. modulo: array[boolean] of integer=(7, 15);
  51. function tx8664intreader.is_targetdirective(const s:string):boolean;
  52. var
  53. i: TAsmSehDirective;
  54. begin
  55. result:=false;
  56. if target_info.system<>system_x86_64_win64 then exit;
  57. for i:=low(TAsmSehDirective) to high(TAsmSehDirective) do
  58. begin
  59. if not (i in recognized_directives) then
  60. continue;
  61. if s=sehdirectivestr[i] then
  62. begin
  63. actsehdirective:=i;
  64. result:=true;
  65. break;
  66. end;
  67. end;
  68. { allow SEH directives only in pure assember routines }
  69. if result and not (po_assembler in current_procinfo.procdef.procoptions) then
  70. begin
  71. Message(asmr_e_seh_in_pure_asm_only);
  72. result:=false;
  73. end;
  74. end;
  75. procedure tx8664intreader.HandleTargetDirective;
  76. var
  77. hreg: TRegister;
  78. hnum: aint;
  79. flags: integer;
  80. ai: tai_seh_directive;
  81. hs: string;
  82. err: boolean;
  83. begin
  84. if actasmtoken<>AS_TARGET_DIRECTIVE then
  85. InternalError(2011100201);
  86. Consume(AS_TARGET_DIRECTIVE);
  87. Include(current_procinfo.flags,pi_has_unwind_info);
  88. case actsehdirective of
  89. { TODO: .seh_pushframe is supposed to have a boolean parameter,
  90. but GAS 2.21 does not support it. }
  91. ash_endprologue,
  92. ash_pushframe,
  93. ash_handlerdata:
  94. curlist.concat(cai_seh_directive.create(actsehdirective));
  95. ash_handler:
  96. begin
  97. hs:=actasmpattern;
  98. Consume(AS_ID);
  99. flags:=0;
  100. err:=false;
  101. while actasmtoken=AS_COMMA do
  102. begin
  103. Consume(AS_COMMA);
  104. if actasmtoken=AS_ID then
  105. begin
  106. uppervar(actasmpattern);
  107. if actasmpattern='@EXCEPT' then
  108. flags:=flags or 1
  109. else if actasmpattern='@UNWIND' then
  110. flags:=flags or 2
  111. else
  112. err:=true;
  113. Consume(AS_ID);
  114. end
  115. else
  116. err:=true;
  117. if err then
  118. begin
  119. Message(asmr_e_syntax_error);
  120. RecoverConsume(false);
  121. exit;
  122. end;
  123. end;
  124. ai:=cai_seh_directive.create_name(ash_handler,hs);
  125. ai.data.flags:=flags;
  126. curlist.concat(ai);
  127. end;
  128. ash_stackalloc:
  129. begin
  130. hnum:=BuildConstExpression;//(false,false);
  131. if (hnum<0) or (hnum>high(dword)) or ((hnum and 7)<>0) then
  132. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc])
  133. else
  134. curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum));
  135. end;
  136. //ash_pushnv,
  137. ash_pushreg:
  138. begin
  139. hreg:=actasmregister;
  140. Consume(AS_REGISTER);
  141. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
  142. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_pushreg])
  143. else
  144. curlist.concat(cai_seh_directive.create_reg(ash_pushreg,hreg));
  145. end;
  146. ash_setframe,
  147. ash_savereg:
  148. begin
  149. hreg:=actasmregister;
  150. Consume(AS_REGISTER);
  151. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
  152. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  153. Consume(AS_COMMA);
  154. hnum:=BuildConstExpression;//(false,false);
  155. if (hnum<0) or (hnum>maxoffset[actsehdirective=ash_setframe]) or
  156. ((hnum mod modulo[actsehdirective=ash_setframe])<>0) then
  157. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective])
  158. else
  159. curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
  160. end;
  161. //ash_savenv,
  162. ash_savexmm:
  163. begin
  164. hreg:=actasmregister;
  165. Consume(AS_REGISTER);
  166. if (getregtype(hreg)<>R_MMREGISTER) then
  167. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_savexmm]);
  168. Consume(AS_COMMA);
  169. hnum:=BuildConstExpression;//(false,false);
  170. if (hnum<0) or (hnum>high(dword)) or ((hnum and 15)<>0) then
  171. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_savexmm])
  172. else
  173. curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
  174. end;
  175. else
  176. InternalError(2018022401);
  177. end;
  178. if actasmtoken<>AS_SEPARATOR then
  179. Consume(AS_SEPARATOR);
  180. end;
  181. const
  182. asmmode_x86_64_intel_info : tasmmodeinfo =
  183. (
  184. id : asmmode_x86_64_intel;
  185. idtxt : 'INTEL';
  186. casmreader : tx8664intreader;
  187. );
  188. initialization
  189. RegisterAsmMode(asmmode_x86_64_intel_info);
  190. end.