rax64att.pas 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. {
  2. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  3. Does the parsing for the i386 GNU AS 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 rax64att;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. raatt,rax86att,aasmtai;
  22. type
  23. tx8664attreader = class(tx86attreader)
  24. actsehdirective: TAsmSehDirective;
  25. procedure handleopcode;override;
  26. function is_targetdirective(const s:string):boolean;override;
  27. procedure handletargetdirective;override;
  28. end;
  29. implementation
  30. uses
  31. cutils,globtype,rabase,systems,rax86,aasmcpu,cgbase,procinfo,symconst,verbose;
  32. procedure tx8664attreader.handleopcode;
  33. var
  34. instr : Tx86Instruction;
  35. begin
  36. instr:=Tx86attInstruction.Create(Tx86Operand);
  37. BuildOpcode(instr);
  38. instr.AddReferenceSizes;
  39. instr.SetInstructionOpsize;
  40. instr.CheckOperandSizes;
  41. instr.FixupOpcode;
  42. instr.ConcatInstruction(curlist);
  43. instr.Free;
  44. end;
  45. const
  46. { x86_64 subset of SEH directives. .seh_proc and .seh_endproc excluded
  47. because they are generated automatically when needed. }
  48. recognized_directives: set of TAsmSehDirective=[
  49. ash_endprologue,ash_handler,ash_handlerdata,
  50. ash_setframe,ash_stackalloc,ash_pushreg,
  51. ash_savereg,ash_savexmm,ash_pushframe
  52. ];
  53. { max offset and bitmask for .seh_savereg and .seh_setframe }
  54. maxoffset: array[boolean] of aint=(high(dword), 240);
  55. modulo: array[boolean] of integer=(7, 15);
  56. function tx8664attreader.is_targetdirective(const s:string):boolean;
  57. var
  58. i: TAsmSehDirective;
  59. begin
  60. result:=false;
  61. if target_info.system<>system_x86_64_win64 then
  62. exit;
  63. for i:=low(TAsmSehDirective) to high(TAsmSehDirective) do
  64. begin
  65. if not (i in recognized_directives) then
  66. continue;
  67. if s=sehdirectivestr[i] then
  68. begin
  69. actsehdirective:=i;
  70. result:=true;
  71. break;
  72. end;
  73. end;
  74. { allow SEH directives only in pure assember routines }
  75. if result and not (po_assembler in current_procinfo.procdef.procoptions) then
  76. begin
  77. Message(asmr_e_seh_in_pure_asm_only);
  78. result:=false;
  79. end;
  80. end;
  81. procedure tx8664attreader.handletargetdirective;
  82. var
  83. hreg: TRegister;
  84. hnum: aint;
  85. flags: integer;
  86. ai: tai_seh_directive;
  87. hs: string;
  88. err: boolean;
  89. begin
  90. if actasmtoken<>AS_TARGET_DIRECTIVE then
  91. InternalError(2011100201);
  92. Consume(AS_TARGET_DIRECTIVE);
  93. Include(current_procinfo.flags,pi_has_unwind_info);
  94. case actsehdirective of
  95. { TODO: .seh_pushframe is supposed to have a boolean parameter,
  96. but GAS 2.21 does not support it. }
  97. ash_endprologue,
  98. ash_pushframe,
  99. ash_handlerdata:
  100. curlist.concat(cai_seh_directive.create(actsehdirective));
  101. ash_handler:
  102. begin
  103. hs:=actasmpattern;
  104. Consume(AS_ID);
  105. flags:=0;
  106. err:=false;
  107. while actasmtoken=AS_COMMA do
  108. begin
  109. Consume(AS_COMMA);
  110. if actasmtoken=AS_AT then
  111. begin
  112. Consume(AS_AT);
  113. if actasmtoken=AS_ID then
  114. begin
  115. uppervar(actasmpattern);
  116. if actasmpattern='EXCEPT' then
  117. flags:=flags or 1
  118. else if actasmpattern='UNWIND' then
  119. flags:=flags or 2
  120. else
  121. err:=true;
  122. Consume(AS_ID);
  123. end
  124. else
  125. err:=true;
  126. end
  127. else
  128. err:=true;
  129. if err then
  130. begin
  131. Message(asmr_e_syntax_error);
  132. RecoverConsume(false);
  133. exit;
  134. end;
  135. end;
  136. ai:=cai_seh_directive.create_name(ash_handler,hs);
  137. ai.data.flags:=flags;
  138. curlist.concat(ai);
  139. end;
  140. ash_stackalloc:
  141. begin
  142. hnum:=BuildConstExpression(false,false);
  143. if (hnum<0) or (hnum>high(dword)) or ((hnum and 7)<>0) then
  144. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc])
  145. else
  146. curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum));
  147. end;
  148. ash_pushreg:
  149. begin
  150. hreg:=actasmregister;
  151. Consume(AS_REGISTER);
  152. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
  153. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_pushreg])
  154. else
  155. curlist.concat(cai_seh_directive.create_reg(ash_pushreg,hreg));
  156. end;
  157. ash_setframe,
  158. ash_savereg:
  159. begin
  160. hreg:=actasmregister;
  161. Consume(AS_REGISTER);
  162. if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
  163. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
  164. Consume(AS_COMMA);
  165. hnum:=BuildConstExpression(false,false);
  166. if (hnum<0) or (hnum>maxoffset[actsehdirective=ash_setframe]) or
  167. ((hnum and modulo[actsehdirective=ash_setframe])<>0) then
  168. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective])
  169. else
  170. curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
  171. end;
  172. ash_savexmm:
  173. begin
  174. hreg:=actasmregister;
  175. Consume(AS_REGISTER);
  176. if (getregtype(hreg)<>R_MMREGISTER) then
  177. Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_savexmm]);
  178. Consume(AS_COMMA);
  179. hnum:=BuildConstExpression(false,false);
  180. if (hnum<0) or (hnum>high(dword)) or ((hnum and 15)<>0) then
  181. Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_savexmm])
  182. else
  183. curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
  184. end;
  185. else
  186. InternalError(2011100202);
  187. end;
  188. if actasmtoken<>AS_SEPARATOR then
  189. Consume(AS_SEPARATOR);
  190. end;
  191. const
  192. asmmode_x86_64_gas_info : tasmmodeinfo =
  193. (
  194. id : asmmode_x86_64_gas;
  195. idtxt : 'GAS';
  196. casmreader : tx8664attreader;
  197. );
  198. { Added to be compatible with i386 }
  199. asmmode_x86_64_att_info : tasmmodeinfo =
  200. (
  201. id : asmmode_x86_64_att;
  202. idtxt : 'ATT';
  203. casmreader : tx8664attreader;
  204. );
  205. asmmode_x86_64_standard_info : tasmmodeinfo =
  206. (
  207. id : asmmode_standard;
  208. idtxt : 'STANDARD';
  209. casmreader : tx8664attreader;
  210. );
  211. initialization
  212. RegisterAsmMode(asmmode_x86_64_gas_info);
  213. RegisterAsmMode(asmmode_x86_64_att_info);
  214. RegisterAsmMode(asmmode_x86_64_standard_info);
  215. end.