cpupara.pas 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. Generates the argument location information for 680x0
  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 bymethodpointer
  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. { Generates the argument location information for 680x0.
  18. }
  19. unit cpupara;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. globtype,
  24. cpubase,
  25. symconst,symdef,symsym,
  26. parabase,paramgr;
  27. type
  28. { Returns the location for the nr-st 32 Bit int parameter
  29. if every parameter before is an 32 Bit int parameter as well
  30. and if the calling conventions for the helper routines of the
  31. rtl are used.
  32. }
  33. tm68kparamanager = class(tparamanager)
  34. procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
  35. function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
  36. private
  37. function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
  38. end;
  39. implementation
  40. uses
  41. verbose,
  42. globals,
  43. systems,
  44. cpuinfo,cgbase,
  45. defutil;
  46. procedure tm68kparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);
  47. var
  48. paraloc : pcgparalocation;
  49. begin
  50. if nr<1 then
  51. internalerror(2002070801);
  52. cgpara.reset;
  53. cgpara.size:=OS_INT;
  54. cgpara.alignment:=std_param_align;
  55. paraloc:=cgpara.add_location;
  56. with paraloc^ do
  57. begin
  58. { warning : THIS ONLY WORKS WITH INTERNAL ROUTINES,
  59. WHICH MUST ALWAYS PASS 4-BYTE PARAMETERS!!
  60. }
  61. loc:=LOC_REFERENCE;
  62. reference.index:=NR_STACK_POINTER_REG;
  63. reference.offset:=target_info.first_parm_offset+nr*4;
  64. end;
  65. end;
  66. function tm68kparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
  67. var
  68. paraloc : pcgparalocation;
  69. hp : tparavarsym;
  70. paracgsize : tcgsize;
  71. paralen : longint;
  72. parasize : longint;
  73. i : longint;
  74. begin
  75. parasize:=0;
  76. for i:=0 to p.paras.count-1 do
  77. begin
  78. hp:=tparavarsym(p.paras[i]);
  79. hp.paraloc[side].reset;
  80. { currently only support C-style array of const }
  81. if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
  82. is_array_of_const(hp.vartype.def) then
  83. begin
  84. paraloc:=hp.paraloc[side].add_location;
  85. { hack: the paraloc must be valid, but is not actually used }
  86. paraloc^.loc:=LOC_REFERENCE;
  87. if side=callerside then
  88. paraloc^.reference.index:=NR_STACK_POINTER_REG
  89. else
  90. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  91. paraloc^.size:=OS_ADDR;
  92. paraloc^.reference.offset:=0;
  93. break;
  94. end;
  95. if push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption) then
  96. paracgsize:=OS_ADDR
  97. else
  98. begin
  99. paracgsize:=def_cgsize(hp.vartype.def);
  100. if paracgsize=OS_NO then
  101. paracgsize:=OS_ADDR;
  102. end;
  103. hp.paraloc[side].size:=paracgsize;
  104. hp.paraloc[side].Alignment:=std_param_align;
  105. paraloc:=hp.paraloc[side].add_location;
  106. paraloc^.size:=paracgsize;
  107. paraloc^.loc:=LOC_REFERENCE;
  108. if side=callerside then
  109. paraloc^.reference.index:=NR_STACK_POINTER_REG
  110. else
  111. paraloc^.reference.index:=NR_FRAME_POINTER_REG;
  112. paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
  113. end;
  114. result:=parasize;
  115. end;
  116. function tm68kparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
  117. var
  118. paraloc : pcgparalocation;
  119. begin
  120. result:=false;
  121. case target_info.system of
  122. system_m68k_amiga:
  123. begin
  124. p.paraloc[callerside].alignment:=4;
  125. paraloc:=p.paraloc[callerside].add_location;
  126. paraloc^.loc:=LOC_REGISTER;
  127. paraloc^.size:=def_cgsize(p.vartype.def);
  128. { pattern is always uppercase'd }
  129. if s='D0' then
  130. paraloc^.register:=NR_D0
  131. else if s='D1' then
  132. paraloc^.register:=NR_D1
  133. else if s='D2' then
  134. paraloc^.register:=NR_D2
  135. else if s='D3' then
  136. paraloc^.register:=NR_D3
  137. else if s='D4' then
  138. paraloc^.register:=NR_D4
  139. else if s='D5' then
  140. paraloc^.register:=NR_D5
  141. else if s='D6' then
  142. paraloc^.register:=NR_D6
  143. else if s='D7' then
  144. paraloc^.register:=NR_D7
  145. else if s='A0' then
  146. paraloc^.register:=NR_A0
  147. else if s='A1' then
  148. paraloc^.register:=NR_A1
  149. else if s='A2' then
  150. paraloc^.register:=NR_A2
  151. else if s='A3' then
  152. paraloc^.register:=NR_A3
  153. else if s='A4' then
  154. paraloc^.register:=NR_A4
  155. else if s='A5' then
  156. paraloc^.register:=NR_A5
  157. { 'A6' is problematic, since it's the frame pointer in fpc,
  158. so it should be saved before a call! }
  159. else if s='A6' then
  160. paraloc^.register:=NR_A6
  161. { 'A7' is the stack pointer on 68k, can't be overwritten by API calls }
  162. else
  163. exit;
  164. { copy to callee side }
  165. p.paraloc[calleeside].add_location^:=paraloc^;
  166. end;
  167. else
  168. internalerror(200405092);
  169. end;
  170. result:=true;
  171. end;
  172. begin
  173. paramanager:=tm68kparamanager.create;
  174. end.