rax64att.pas 8.2 KB

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