cgcpu.pas 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  1. {
  2. $Id$
  3. Copyright (c) 2003 by Florian Klaempfl
  4. Member of the Free Pascal development team
  5. This unit implements the code generator for the ARM
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit cgcpu;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. symtype,
  24. cgbase,cgobj,
  25. aasmbase,aasmcpu,aasmtai,
  26. cpubase,cpuinfo,node,cg64f32,rgcpu;
  27. type
  28. tcgarm = class(tcg)
  29. rgint,
  30. rgmm,
  31. rgfpu : trgcpu;
  32. procedure init_register_allocators;override;
  33. procedure done_register_allocators;override;
  34. procedure ungetreference(list:Taasmoutput;const r:Treference);override;
  35. function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
  36. function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
  37. function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
  38. procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
  39. procedure ungetregister(list:Taasmoutput;r:Tregister);override;
  40. procedure add_move_instruction(instr:Taicpu);override;
  41. procedure do_register_allocation(list:Taasmoutput;headertai:tai);override;
  42. procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
  43. procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
  44. function uses_registers(rt:Tregistertype):boolean;override;
  45. procedure a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);override;
  46. procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);override;
  47. procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);override;
  48. procedure a_call_name(list : taasmoutput;const s : string);override;
  49. procedure a_call_reg(list : taasmoutput;reg: tregister); override;
  50. procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister); override;
  51. procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  52. procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  53. size: tcgsize; a: aword; src, dst: tregister); override;
  54. procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  55. size: tcgsize; src1, src2, dst: tregister); override;
  56. { move instructions }
  57. procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aword;reg : tregister);override;
  58. procedure a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  59. procedure a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  60. procedure a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  61. { fpu move instructions }
  62. procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
  63. procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
  64. procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
  65. { comparison operations }
  66. procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  67. l : tasmlabel);override;
  68. procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  69. procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
  70. procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
  71. procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  72. procedure g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aword);override;
  73. procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
  74. procedure g_return_from_proc(list : taasmoutput;parasize : aword); override;
  75. procedure g_restore_frame_pointer(list : taasmoutput);override;
  76. procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
  77. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
  78. procedure g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef); override;
  79. procedure g_save_standard_registers(list : taasmoutput);override;
  80. procedure g_restore_standard_registers(list : taasmoutput);override;
  81. procedure g_save_all_registers(list : taasmoutput);override;
  82. procedure g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);override;
  83. procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  84. procedure fixref(list : taasmoutput;var ref : treference);
  85. procedure handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  86. end;
  87. tcg64farm = class(tcg64f32)
  88. procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
  89. procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);override;
  90. procedure a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;regsrc,regdst : tregister64);override;
  91. procedure a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);override;
  92. end;
  93. const
  94. OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
  95. C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
  96. function is_shifter_const(d : dword;var imm_shift : byte) : boolean;
  97. implementation
  98. uses
  99. globtype,globals,verbose,systems,cutils,
  100. symconst,symdef,symsym,
  101. tgobj,
  102. procinfo,cpupi;
  103. procedure tcgarm.ungetreference(list:Taasmoutput;const r:Treference);
  104. begin
  105. if r.base<>NR_NO then
  106. ungetregister(list,r.base);
  107. if r.index<>NR_NO then
  108. ungetregister(list,r.index);
  109. end;
  110. procedure tcgarm.init_register_allocators;
  111. begin
  112. rgint:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
  113. [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
  114. RS_R9,RS_R10,RS_R12],first_int_imreg,[]);
  115. rgfpu:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
  116. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
  117. rgmm:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
  118. [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
  119. end;
  120. procedure tcgarm.done_register_allocators;
  121. begin
  122. rgint.free;
  123. rgfpu.free;
  124. rgmm.free;
  125. end;
  126. function tcgarm.getintregister(list:Taasmoutput;size:Tcgsize):Tregister;
  127. begin
  128. result:=rgint.getregister(list,cgsize2subreg(size));
  129. end;
  130. function tcgarm.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
  131. begin
  132. result:=rgfpu.getregister(list,R_SUBWHOLE);
  133. end;
  134. function tcgarm.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;
  135. begin
  136. result:=rgmm.getregister(list,R_SUBNONE);
  137. end;
  138. procedure tcgarm.getexplicitregister(list:Taasmoutput;r:Tregister);
  139. begin
  140. case getregtype(r) of
  141. R_INTREGISTER :
  142. rgint.getexplicitregister(list,r);
  143. R_MMREGISTER :
  144. rgmm.getexplicitregister(list,r);
  145. R_FPUREGISTER :
  146. rgfpu.getexplicitregister(list,r);
  147. else
  148. internalerror(200310091);
  149. end;
  150. end;
  151. procedure tcgarm.ungetregister(list:Taasmoutput;r:Tregister);
  152. begin
  153. case getregtype(r) of
  154. R_INTREGISTER :
  155. rgint.ungetregister(list,r);
  156. R_FPUREGISTER :
  157. rgfpu.ungetregister(list,r);
  158. R_MMREGISTER :
  159. rgmm.ungetregister(list,r);
  160. else
  161. internalerror(200310091);
  162. end;
  163. end;
  164. procedure tcgarm.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
  165. begin
  166. case rt of
  167. R_INTREGISTER :
  168. rgint.allocexplicitregisters(list,r);
  169. R_FPUREGISTER :
  170. rgfpu.allocexplicitregisters(list,r);
  171. R_MMREGISTER :
  172. rgmm.allocexplicitregisters(list,r);
  173. else
  174. internalerror(200310092);
  175. end;
  176. end;
  177. procedure tcgarm.deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
  178. begin
  179. case rt of
  180. R_INTREGISTER :
  181. rgint.deallocexplicitregisters(list,r);
  182. R_FPUREGISTER :
  183. rgfpu.deallocexplicitregisters(list,r);
  184. R_MMREGISTER :
  185. rgmm.deallocexplicitregisters(list,r);
  186. else
  187. internalerror(200310093);
  188. end;
  189. end;
  190. function tcgarm.uses_registers(rt:Tregistertype):boolean;
  191. begin
  192. case rt of
  193. R_INTREGISTER :
  194. result:=rgint.uses_registers;
  195. R_MMREGISTER :
  196. result:=rgmm.uses_registers;
  197. R_FPUREGISTER :
  198. result:=rgfpu.uses_registers;
  199. else
  200. internalerror(200310094);
  201. end;
  202. end;
  203. procedure tcgarm.add_move_instruction(instr:Taicpu);
  204. begin
  205. rgint.add_move_instruction(instr);
  206. end;
  207. procedure tcgarm.do_register_allocation(list:Taasmoutput;headertai:tai);
  208. begin
  209. { Int }
  210. rgint.check_unreleasedregs;
  211. rgint.do_register_allocation(list,headertai);
  212. rgint.translate_registers(list);
  213. { FPU }
  214. rgfpu.check_unreleasedregs;
  215. rgfpu.do_register_allocation(list,headertai);
  216. rgfpu.translate_registers(list);
  217. { MM }
  218. rgmm.check_unreleasedregs;
  219. rgmm.do_register_allocation(list,headertai);
  220. rgmm.translate_registers(list);
  221. end;
  222. procedure tcgarm.a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);
  223. var
  224. ref: treference;
  225. begin
  226. case locpara.loc of
  227. LOC_REGISTER,LOC_CREGISTER:
  228. a_load_const_reg(list,size,a,locpara.register);
  229. LOC_REFERENCE:
  230. begin
  231. reference_reset(ref);
  232. ref.base:=locpara.reference.index;
  233. ref.offset:=locpara.reference.offset;
  234. a_load_const_ref(list,size,a,ref);
  235. end;
  236. else
  237. internalerror(2002081101);
  238. end;
  239. if locpara.alignment<>0 then
  240. internalerror(2002081102);
  241. end;
  242. procedure tcgarm.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
  243. var
  244. ref: treference;
  245. tmpreg: tregister;
  246. begin
  247. case locpara.loc of
  248. LOC_REGISTER,LOC_CREGISTER:
  249. a_load_ref_reg(list,size,size,r,locpara.register);
  250. LOC_REFERENCE:
  251. begin
  252. reference_reset(ref);
  253. ref.base:=locpara.reference.index;
  254. ref.offset:=locpara.reference.offset;
  255. tmpreg := getintregister(list,size);
  256. a_load_ref_reg(list,size,size,r,tmpreg);
  257. a_load_reg_ref(list,size,size,tmpreg,ref);
  258. ungetregister(list,tmpreg);
  259. end;
  260. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  261. case size of
  262. OS_F32, OS_F64:
  263. a_loadfpu_ref_reg(list,size,r,locpara.register);
  264. else
  265. internalerror(2002072801);
  266. end;
  267. else
  268. internalerror(2002081103);
  269. end;
  270. if locpara.alignment<>0 then
  271. internalerror(2002081104);
  272. end;
  273. procedure tcgarm.a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);
  274. var
  275. ref: treference;
  276. tmpreg: tregister;
  277. begin
  278. case locpara.loc of
  279. LOC_REGISTER,LOC_CREGISTER:
  280. a_loadaddr_ref_reg(list,r,locpara.register);
  281. LOC_REFERENCE:
  282. begin
  283. reference_reset(ref);
  284. ref.base := locpara.reference.index;
  285. ref.offset := locpara.reference.offset;
  286. tmpreg := getintregister(list,OS_ADDR);
  287. a_loadaddr_ref_reg(list,r,tmpreg);
  288. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  289. ungetregister(list,tmpreg);
  290. end;
  291. else
  292. internalerror(2002080701);
  293. end;
  294. end;
  295. procedure tcgarm.a_call_name(list : taasmoutput;const s : string);
  296. begin
  297. list.concat(taicpu.op_sym(A_BL,objectlibrary.newasmsymbol(s)));
  298. if not(pi_do_call in current_procinfo.flags) then
  299. internalerror(2003060703);
  300. end;
  301. procedure tcgarm.a_call_reg(list : taasmoutput;reg: tregister);
  302. var
  303. r : tregister;
  304. begin
  305. list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
  306. if not(pi_do_call in current_procinfo.flags) then
  307. internalerror(2003060704);
  308. end;
  309. procedure tcgarm.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister);
  310. begin
  311. a_op_const_reg_reg(list,op,size,a,reg,reg);
  312. end;
  313. procedure tcgarm.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  314. begin
  315. case op of
  316. OP_NEG:
  317. list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
  318. OP_NOT:
  319. list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
  320. else
  321. a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
  322. end;
  323. end;
  324. const
  325. op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
  326. (A_NONE,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
  327. A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
  328. procedure tcgarm.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  329. size: tcgsize; a: aword; src, dst: tregister);
  330. var
  331. shift : byte;
  332. tmpreg : tregister;
  333. so : tshifterop;
  334. begin
  335. if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
  336. case op of
  337. OP_NEG,OP_NOT,
  338. OP_DIV,OP_IDIV:
  339. internalerror(200308281);
  340. OP_SHL:
  341. begin
  342. if a>32 then
  343. internalerror(200308291);
  344. shifterop_reset(so);
  345. so.shiftmode:=SM_LSL;
  346. so.shiftimm:=a;
  347. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  348. end;
  349. OP_SHR:
  350. begin
  351. if a>32 then
  352. internalerror(200308292);
  353. shifterop_reset(so);
  354. so.shiftmode:=SM_LSR;
  355. so.shiftimm:=a;
  356. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  357. end;
  358. OP_SAR:
  359. begin
  360. if a>32 then
  361. internalerror(200308291);
  362. shifterop_reset(so);
  363. so.shiftmode:=SM_LSL;
  364. so.shiftimm:=a;
  365. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
  366. end;
  367. else
  368. list.concat(taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a));
  369. end
  370. else
  371. begin
  372. { there could be added some more sophisticated optimizations }
  373. if (op in [OP_MUL,OP_IMUL]) and (a=1) then
  374. a_load_reg_reg(list,size,size,src,dst)
  375. else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
  376. a_load_const_reg(list,size,0,dst)
  377. else if (op in [OP_IMUL]) and (a=-1) then
  378. a_op_reg_reg(list,OP_NEG,size,src,dst)
  379. else
  380. begin
  381. tmpreg:=getintregister(list,size);
  382. a_load_const_reg(list,size,a,tmpreg);
  383. a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
  384. ungetregister(list,tmpreg);
  385. end;
  386. end;
  387. end;
  388. procedure tcgarm.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  389. size: tcgsize; src1, src2, dst: tregister);
  390. var
  391. so : tshifterop;
  392. tmpreg : tregister;
  393. begin
  394. case op of
  395. OP_NEG,OP_NOT,
  396. OP_DIV,OP_IDIV:
  397. internalerror(200308281);
  398. OP_SHL:
  399. begin
  400. shifterop_reset(so);
  401. so.rs:=src1;
  402. so.shiftmode:=SM_LSL;
  403. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  404. end;
  405. OP_SHR:
  406. begin
  407. shifterop_reset(so);
  408. so.rs:=src1;
  409. so.shiftmode:=SM_LSR;
  410. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  411. end;
  412. OP_SAR:
  413. begin
  414. shifterop_reset(so);
  415. so.rs:=src1;
  416. so.shiftmode:=SM_ASR;
  417. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
  418. end;
  419. OP_IMUL,
  420. OP_MUL:
  421. begin
  422. { the arm doesn't allow that rd and rm are the same }
  423. if dst=src2 then
  424. begin
  425. if dst<>src1 then
  426. begin
  427. rgint.add_edge(getsupreg(dst),getsupreg(src1));
  428. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2));
  429. end
  430. else
  431. begin
  432. tmpreg:=getintregister(list,size);
  433. a_load_reg_reg(list,size,size,src2,dst);
  434. rgint.add_edge(getsupreg(dst),getsupreg(tmpreg));
  435. ungetregister(list,tmpreg);
  436. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
  437. end;
  438. end
  439. else
  440. begin
  441. rgint.add_edge(getsupreg(dst),getsupreg(src2));
  442. list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
  443. end;
  444. end;
  445. else
  446. list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
  447. end;
  448. end;
  449. function rotl(d : dword;b : byte) : dword;
  450. begin
  451. result:=(d shr (32-b)) or (d shl b);
  452. end;
  453. function is_shifter_const(d : dword;var imm_shift : byte) : boolean;
  454. var
  455. i : longint;
  456. begin
  457. for i:=0 to 15 do
  458. begin
  459. if (d and not(rotl($ff,i*2)))=0 then
  460. begin
  461. imm_shift:=i*2;
  462. result:=true;
  463. exit;
  464. end;
  465. end;
  466. result:=false;
  467. end;
  468. procedure tcgarm.a_load_const_reg(list : taasmoutput; size: tcgsize; a : aword;reg : tregister);
  469. var
  470. imm_shift : byte;
  471. l : tasmlabel;
  472. hr : treference;
  473. begin
  474. if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
  475. internalerror(2002090902);
  476. if is_shifter_const(dword(a),imm_shift) then
  477. list.concat(taicpu.op_reg_const(A_MOV,reg,a))
  478. else if is_shifter_const(dword(not(a)),imm_shift) then
  479. list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
  480. else
  481. begin
  482. objectlibrary.getdatalabel(l);
  483. current_procinfo.aktlocaldata.concat(tai_symbol.Create(l,0));
  484. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
  485. reference_reset(hr);
  486. hr.symbol:=l;
  487. list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
  488. end;
  489. end;
  490. procedure tcgarm.handle_load_store(list:taasmoutput;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference);
  491. var
  492. tmpreg : tregister;
  493. tmpref : treference;
  494. l : tasmlabel;
  495. begin
  496. tmpreg:=NR_NO;
  497. { Be sure to have a base register }
  498. if (ref.base=NR_NO) then
  499. begin
  500. if ref.shiftmode<>SM_None then
  501. internalerror(200308294);
  502. ref.base:=ref.index;
  503. ref.index:=NR_NO;
  504. end;
  505. { absolute symbols can't be handled directly, we've to store the symbol reference
  506. in the text segment and access it pc relative
  507. For now, we assume that references where base or index equals to PC are already
  508. relative, all other references are assumed to be absolute and thus they need
  509. to be handled extra.
  510. A proper solution would be to change refoptions to a set and store the information
  511. if the symbol is absolute or relative there.
  512. }
  513. if (assigned(ref.symbol) and
  514. not(is_pc(ref.base)) and
  515. not(is_pc(ref.index))
  516. ) or
  517. (ref.offset<-4095) or
  518. (ref.offset>4095) or
  519. ((oppostfix in [PF_SB,PF_H,PF_SH]) and
  520. ((ref.offset<-255) or
  521. (ref.offset>255)
  522. )
  523. ) then
  524. begin
  525. { check consts distance }
  526. { !!!! }
  527. { create consts entry }
  528. objectlibrary.getdatalabel(l);
  529. current_procinfo.aktlocaldata.concat(Tai_symbol.Create(l,0));
  530. if assigned(ref.symbol) then
  531. current_procinfo.aktlocaldata.concat(tai_const_symbol.Create_offset(ref.symbol,ref.offset))
  532. else
  533. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  534. { load consts entry }
  535. tmpreg:=getintregister(list,OS_INT);
  536. reference_reset(tmpref);
  537. tmpref.symbol:=l;
  538. tmpref.base:=NR_R15;
  539. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  540. if (ref.base<>NR_NO) then
  541. begin
  542. if ref.index<>NR_NO then
  543. begin
  544. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  545. ref.base:=tmpreg;
  546. end
  547. else
  548. begin
  549. ref.index:=tmpreg;
  550. ref.shiftimm:=0;
  551. ref.signindex:=1;
  552. ref.shiftmode:=SM_None;
  553. end;
  554. end
  555. else
  556. ref.base:=tmpreg;
  557. ref.offset:=0;
  558. ref.symbol:=nil;
  559. end;
  560. { floating point operations have only limited references
  561. we expect here, that a base is already set }
  562. if (op in [A_LDF,A_STF]) and (ref.index<>NR_NO) then
  563. begin
  564. if ref.shiftmode<>SM_none then
  565. internalerror(200309121);
  566. if tmpreg<>NR_NO then
  567. begin
  568. if ref.base=tmpreg then
  569. begin
  570. if ref.signindex<0 then
  571. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index))
  572. else
  573. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index));
  574. ref.index:=NR_NO;
  575. end
  576. else
  577. begin
  578. if ref.signindex<0 then
  579. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.base))
  580. else
  581. list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.base));
  582. ref.index:=NR_NO;
  583. ref.index:=tmpreg;
  584. end;
  585. end
  586. else
  587. begin
  588. tmpreg:=getintregister(list,OS_INT);
  589. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
  590. ref.base:=tmpreg;
  591. ref.index:=NR_NO;
  592. end;
  593. end;
  594. list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
  595. if (tmpreg<>NR_NO) then
  596. ungetregister(list,tmpreg);
  597. end;
  598. procedure tcgarm.a_load_reg_ref(list : taasmoutput; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  599. var
  600. oppostfix:toppostfix;
  601. begin
  602. case ToSize of
  603. { signed integer registers }
  604. OS_8,
  605. OS_S8:
  606. oppostfix:=PF_B;
  607. OS_16,
  608. OS_S16:
  609. oppostfix:=PF_H;
  610. OS_32,
  611. OS_S32:
  612. oppostfix:=PF_None;
  613. else
  614. InternalError(200308295);
  615. end;
  616. handle_load_store(list,A_STR,oppostfix,reg,ref);
  617. end;
  618. procedure tcgarm.a_load_ref_reg(list : taasmoutput; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
  619. var
  620. oppostfix:toppostfix;
  621. begin
  622. case FromSize of
  623. { signed integer registers }
  624. OS_8:
  625. oppostfix:=PF_B;
  626. OS_S8:
  627. oppostfix:=PF_SB;
  628. OS_16:
  629. oppostfix:=PF_H;
  630. OS_S16:
  631. oppostfix:=PF_SH;
  632. OS_32,
  633. OS_S32:
  634. oppostfix:=PF_None;
  635. else
  636. InternalError(200308291);
  637. end;
  638. handle_load_store(list,A_LDR,oppostfix,reg,ref);
  639. end;
  640. procedure tcgarm.a_load_reg_reg(list : taasmoutput; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  641. var
  642. instr: taicpu;
  643. so : tshifterop;
  644. begin
  645. shifterop_reset(so);
  646. if (reg1<>reg2) or
  647. (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
  648. ((tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  649. (tosize <> fromsize) and
  650. not(fromsize in [OS_32,OS_S32])) then
  651. begin
  652. case tosize of
  653. OS_8:
  654. list.concat(taicpu.op_reg_reg_const(A_AND,
  655. reg2,reg1,$ff));
  656. OS_S8:
  657. begin
  658. so.shiftmode:=SM_LSL;
  659. so.shiftimm:=24;
  660. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  661. so.shiftmode:=SM_ASR;
  662. so.shiftimm:=24;
  663. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  664. end;
  665. OS_16:
  666. begin
  667. so.shiftmode:=SM_LSL;
  668. so.shiftimm:=16;
  669. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  670. so.shiftmode:=SM_LSR;
  671. so.shiftimm:=16;
  672. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  673. end;
  674. OS_S16:
  675. begin
  676. so.shiftmode:=SM_LSL;
  677. so.shiftimm:=16;
  678. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg1,so));
  679. so.shiftmode:=SM_ASR;
  680. so.shiftimm:=16;
  681. list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg2,so));
  682. end;
  683. OS_32,OS_S32:
  684. begin
  685. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  686. list.concat(instr);
  687. add_move_instruction(instr);
  688. end;
  689. else internalerror(2002090901);
  690. end;
  691. end;
  692. end;
  693. procedure tcgarm.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
  694. begin
  695. list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[size]));
  696. end;
  697. procedure tcgarm.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  698. var
  699. oppostfix:toppostfix;
  700. begin
  701. case size of
  702. OS_F32:
  703. oppostfix:=PF_S;
  704. OS_F64:
  705. oppostfix:=PF_D;
  706. OS_F80:
  707. oppostfix:=PF_E;
  708. else
  709. InternalError(200309021);
  710. end;
  711. handle_load_store(list,A_LDF,oppostfix,reg,ref);
  712. end;
  713. procedure tcgarm.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  714. var
  715. oppostfix:toppostfix;
  716. begin
  717. case size of
  718. OS_F32:
  719. oppostfix:=PF_S;
  720. OS_F64:
  721. oppostfix:=PF_D;
  722. OS_F80:
  723. oppostfix:=PF_E;
  724. else
  725. InternalError(200309021);
  726. end;
  727. handle_load_store(list,A_STF,oppostfix,reg,ref);
  728. end;
  729. { comparison operations }
  730. procedure tcgarm.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  731. l : tasmlabel);
  732. var
  733. tmpreg : tregister;
  734. b : byte;
  735. begin
  736. if is_shifter_const(a,b) then
  737. list.concat(taicpu.op_reg_const(A_CMN,reg,a))
  738. { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
  739. and CMP reg,$7fffffff regarding the flags according to the ARM manual }
  740. else if is_shifter_const(not(a),b) and (a<>$7fffffff) and (a<>$ffffffff) then
  741. list.concat(taicpu.op_reg_const(A_CMN,reg,not(a)))
  742. else
  743. begin
  744. tmpreg:=getintregister(list,size);
  745. a_load_const_reg(list,size,a,tmpreg);
  746. list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
  747. ungetregister(list,tmpreg);
  748. end;
  749. a_jmp_cond(list,cmp_op,l);
  750. end;
  751. procedure tcgarm.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  752. begin
  753. list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
  754. a_jmp_cond(list,cmp_op,l);
  755. end;
  756. procedure tcgarm.a_jmp_always(list : taasmoutput;l: tasmlabel);
  757. begin
  758. list.concat(taicpu.op_sym(A_B,objectlibrary.newasmsymbol(l.name)));
  759. end;
  760. procedure tcgarm.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  761. var
  762. ai : taicpu;
  763. begin
  764. ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
  765. ai.is_jmp:=true;
  766. list.concat(ai);
  767. end;
  768. procedure tcgarm.g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister);
  769. var
  770. ai : taicpu;
  771. begin
  772. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
  773. list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond[flags_to_cond(f)]));
  774. end;
  775. procedure tcgarm.g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aword);
  776. begin
  777. end;
  778. procedure tcgarm.g_stackframe_entry(list : taasmoutput;localsize : longint);
  779. var
  780. ref : treference;
  781. shift : byte;
  782. begin
  783. LocalSize:=align(LocalSize,4);
  784. a_reg_alloc(list,NR_STACK_POINTER_REG);
  785. a_reg_alloc(list,NR_FRAME_POINTER_REG);
  786. a_reg_alloc(list,NR_R12);
  787. list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
  788. { save int registers }
  789. reference_reset(ref);
  790. ref.index:=NR_STACK_POINTER_REG;
  791. ref.addressmode:=AM_PREINDEXED;
  792. list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R12,RS_R14,RS_R15]),PF_DB));
  793. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
  794. { allocate necessary stack size }
  795. { don't use a_op_const_reg_reg here because we don't allow register allocations
  796. in the entry/exit code }
  797. if not(is_shifter_const(localsize,shift)) then
  798. begin
  799. a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
  800. list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
  801. a_reg_dealloc(list,NR_R12);
  802. end
  803. else
  804. begin
  805. a_reg_dealloc(list,NR_R12);
  806. list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
  807. end;
  808. end;
  809. procedure tcgarm.g_return_from_proc(list : taasmoutput;parasize : aword);
  810. var
  811. ref : treference;
  812. begin
  813. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  814. list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
  815. else
  816. begin
  817. { restore int registers and return }
  818. reference_reset(ref);
  819. ref.index:=NR_FRAME_POINTER_REG;
  820. list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rgint.used_in_proc-[RS_R0..RS_R3]+[RS_R11,RS_R13,RS_R15]),PF_DB));
  821. end;
  822. end;
  823. procedure tcgarm.g_restore_frame_pointer(list : taasmoutput);
  824. begin
  825. { the frame pointer on the ARM is restored while the ret is executed }
  826. end;
  827. procedure tcgarm.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  828. var
  829. b : byte;
  830. tmpref : treference;
  831. instr : taicpu;
  832. begin
  833. if ref.addressmode<>AM_OFFSET then
  834. internalerror(200309071);
  835. tmpref:=ref;
  836. { Be sure to have a base register }
  837. if (tmpref.base=NR_NO) then
  838. begin
  839. if tmpref.shiftmode<>SM_None then
  840. internalerror(200308294);
  841. if tmpref.signindex<0 then
  842. internalerror(200312023);
  843. tmpref.base:=tmpref.index;
  844. tmpref.index:=NR_NO;
  845. end;
  846. if assigned(tmpref.symbol) or
  847. not((is_shifter_const(dword(tmpref.offset),b)) or
  848. (is_shifter_const(dword(-tmpref.offset),b))
  849. ) then
  850. fixref(list,tmpref);
  851. { expect a base here }
  852. if tmpref.base=NR_NO then
  853. internalerror(200312022);
  854. if tmpref.index<>NR_NO then
  855. begin
  856. if tmpref.shiftmode<>SM_None then
  857. internalerror(200312021);
  858. if tmpref.signindex<0 then
  859. list.concat(taicpu.op_reg_reg_reg(A_SUB,r,tmpref.base,tmpref.index))
  860. else
  861. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,tmpref.base,tmpref.index));
  862. if tmpref.offset>0 then
  863. list.concat(taicpu.op_reg_reg_const(A_ADD,r,r,tmpref.offset))
  864. else if tmpref.offset<0 then
  865. list.concat(taicpu.op_reg_reg_const(A_SUB,r,r,-tmpref.offset));
  866. end
  867. else
  868. begin
  869. if tmpref.offset>0 then
  870. list.concat(taicpu.op_reg_reg_const(A_ADD,r,tmpref.base,tmpref.offset))
  871. else if tmpref.offset<0 then
  872. list.concat(taicpu.op_reg_reg_const(A_SUB,r,tmpref.base,-tmpref.offset))
  873. else
  874. begin
  875. instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
  876. list.concat(instr);
  877. add_move_instruction(instr);
  878. end;
  879. end;
  880. reference_release(list,tmpref);
  881. end;
  882. procedure tcgarm.fixref(list : taasmoutput;var ref : treference);
  883. var
  884. tmpreg : tregister;
  885. tmpref : treference;
  886. l : tasmlabel;
  887. begin
  888. { absolute symbols can't be handled directly, we've to store the symbol reference
  889. in the text segment and access it pc relative
  890. For now, we assume that references where base or index equals to PC are already
  891. relative, all other references are assumed to be absolute and thus they need
  892. to be handled extra.
  893. A proper solution would be to change refoptions to a set and store the information
  894. if the symbol is absolute or relative there.
  895. }
  896. { check consts distance }
  897. {!!!!!}
  898. { create consts entry }
  899. objectlibrary.getdatalabel(l);
  900. current_procinfo.aktlocaldata.concat(Tai_symbol.Create(l,0));
  901. if assigned(ref.symbol) then
  902. current_procinfo.aktlocaldata.concat(tai_const_symbol.Create_offset(ref.symbol,ref.offset))
  903. else
  904. current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
  905. { load consts entry }
  906. reference_reset(tmpref);
  907. tmpreg:=getintregister(list,OS_INT);
  908. tmpref.symbol:=l;
  909. tmpref.base:=NR_PC;
  910. list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
  911. if (ref.base<>NR_NO) then
  912. begin
  913. if ref.index<>NR_NO then
  914. begin
  915. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
  916. ref.base:=tmpreg;
  917. end
  918. else
  919. begin
  920. ref.index:=tmpreg;
  921. ref.shiftimm:=0;
  922. ref.signindex:=1;
  923. ref.shiftmode:=SM_None;
  924. end;
  925. end
  926. else
  927. ref.base:=tmpreg;
  928. ref.offset:=0;
  929. ref.symbol:=nil;
  930. end;
  931. procedure tcgarm.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);
  932. var
  933. srcref,dstref:treference;
  934. srcreg,destreg,countreg,r:tregister;
  935. helpsize:aword;
  936. copysize:byte;
  937. cgsize:Tcgsize;
  938. procedure genloop(count : aword;size : byte);
  939. const
  940. size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
  941. var
  942. l : tasmlabel;
  943. begin
  944. objectlibrary.getdatalabel(l);
  945. a_load_const_reg(list,OS_INT,count,countreg);
  946. list.concat(Tai_symbol.Create(l,0));
  947. srcref.addressmode:=AM_POSTINDEXED;
  948. dstref.addressmode:=AM_POSTINDEXED;
  949. srcref.offset:=size;
  950. dstref.offset:=size;
  951. r:=getintregister(list,size2opsize[size]);
  952. a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
  953. a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
  954. ungetregister(list,r);
  955. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
  956. list.concat(setcondition(taicpu.op_sym(A_B,l),C_NE));
  957. end;
  958. begin
  959. helpsize:=12;
  960. dstref:=dest;
  961. srcref:=source;
  962. if cs_littlesize in aktglobalswitches then
  963. helpsize:=8;
  964. if not loadref and (len<=helpsize) then
  965. begin
  966. copysize:=4;
  967. cgsize:=OS_32;
  968. while len<>0 do
  969. begin
  970. if len<2 then
  971. begin
  972. copysize:=1;
  973. cgsize:=OS_8;
  974. end
  975. else if len<4 then
  976. begin
  977. copysize:=2;
  978. cgsize:=OS_16;
  979. end;
  980. dec(len,copysize);
  981. r:=getintregister(list,cgsize);
  982. a_load_ref_reg(list,cgsize,cgsize,srcref,r);
  983. if (len=0) and delsource then
  984. reference_release(list,source);
  985. a_load_reg_ref(list,cgsize,cgsize,r,dstref);
  986. inc(srcref.offset,copysize);
  987. inc(dstref.offset,copysize);
  988. ungetregister(list,r);
  989. end;
  990. end
  991. else
  992. begin
  993. destreg:=getintregister(list,OS_ADDR);
  994. a_loadaddr_ref_reg(list,dest,destreg);
  995. if delsource then
  996. reference_release(list,srcref);
  997. srcreg:=getintregister(list,OS_ADDR);
  998. if loadref then
  999. a_load_ref_reg(list,OS_ADDR,OS_ADDR,source,srcreg)
  1000. else
  1001. a_loadaddr_ref_reg(list,source,srcreg);
  1002. // srcref.
  1003. countreg:=getintregister(list,OS_32);
  1004. // if cs_littlesize in aktglobalswitches then
  1005. genloop(len,1);
  1006. {
  1007. else
  1008. begin
  1009. helpsize:=len shr 2;
  1010. len:=len and 3;
  1011. if helpsize>1 then
  1012. begin
  1013. a_load_const_reg(list,OS_INT,helpsize,countreg);
  1014. list.concat(Taicpu.op_none(A_REP,S_NO));
  1015. end;
  1016. if helpsize>0 then
  1017. list.concat(Taicpu.op_none(A_MOVSD,S_NO));
  1018. if len>1 then
  1019. begin
  1020. dec(len,2);
  1021. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  1022. end;
  1023. if len=1 then
  1024. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  1025. end;
  1026. }
  1027. ungetregister(list,countreg);
  1028. ungetregister(list,srcreg);
  1029. ungetregister(list,destreg);
  1030. end;
  1031. if delsource then
  1032. tg.ungetiftemp(list,source);
  1033. end;
  1034. procedure tcgarm.g_overflowcheck(list: taasmoutput; const l: tlocation; def: tdef);
  1035. begin
  1036. end;
  1037. procedure tcgarm.g_save_standard_registers(list : taasmoutput);
  1038. begin
  1039. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  1040. end;
  1041. procedure tcgarm.g_restore_standard_registers(list : taasmoutput);
  1042. begin
  1043. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  1044. end;
  1045. procedure tcgarm.g_save_all_registers(list : taasmoutput);
  1046. begin
  1047. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  1048. end;
  1049. procedure tcgarm.g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);
  1050. begin
  1051. { we support only ARM standard calling conventions so this procedure has no use on the ARM }
  1052. end;
  1053. procedure tcgarm.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  1054. var
  1055. ai : taicpu;
  1056. begin
  1057. ai:=Taicpu.Op_sym(A_B,l);
  1058. ai.SetCondition(OpCmp2AsmCond[cond]);
  1059. ai.is_jmp:=true;
  1060. list.concat(ai);
  1061. end;
  1062. procedure tcg64farm.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  1063. var
  1064. tmpreg : tregister;
  1065. begin
  1066. case op of
  1067. OP_NEG:
  1068. begin
  1069. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
  1070. list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
  1071. end;
  1072. else
  1073. a_op64_reg_reg_reg(list,op,regsrc,regdst,regdst);
  1074. end;
  1075. end;
  1076. procedure tcg64farm.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : qword;reg : tregister64);
  1077. begin
  1078. a_op64_const_reg_reg(list,op,value,reg,reg);
  1079. end;
  1080. procedure tcg64farm.a_op64_const_reg_reg(list: taasmoutput;op:TOpCG;value : qword;regsrc,regdst : tregister64);
  1081. var
  1082. tmpreg : tregister;
  1083. b : byte;
  1084. begin
  1085. case op of
  1086. OP_AND,OP_OR,OP_XOR:
  1087. begin
  1088. cg.a_op_const_reg_reg(list,op,OS_32,lo(value),regsrc.reglo,regdst.reglo);
  1089. cg.a_op_const_reg_reg(list,op,OS_32,hi(value),regsrc.reghi,regdst.reghi);
  1090. end;
  1091. OP_ADD:
  1092. begin
  1093. if is_shifter_const(lo(value),b) then
  1094. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1095. else
  1096. begin
  1097. tmpreg:=cg.getintregister(list,OS_32);
  1098. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1099. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1100. cg.ungetregister(list,tmpreg);
  1101. end;
  1102. if is_shifter_const(hi(value),b) then
  1103. list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)))
  1104. else
  1105. begin
  1106. tmpreg:=cg.getintregister(list,OS_32);
  1107. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1108. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
  1109. cg.ungetregister(list,tmpreg);
  1110. end;
  1111. end;
  1112. OP_SUB:
  1113. begin
  1114. if is_shifter_const(lo(value),b) then
  1115. list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
  1116. else
  1117. begin
  1118. tmpreg:=cg.getintregister(list,OS_32);
  1119. cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
  1120. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
  1121. cg.ungetregister(list,tmpreg);
  1122. end;
  1123. if is_shifter_const(hi(value),b) then
  1124. list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,hi(value)))
  1125. else
  1126. begin
  1127. tmpreg:=cg.getintregister(list,OS_32);
  1128. cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
  1129. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
  1130. cg.ungetregister(list,tmpreg);
  1131. end;
  1132. end;
  1133. else
  1134. internalerror(2003083101);
  1135. end;
  1136. end;
  1137. procedure tcg64farm.a_op64_reg_reg_reg(list: taasmoutput;op:TOpCG;regsrc1,regsrc2,regdst : tregister64);
  1138. begin
  1139. case op of
  1140. OP_AND,OP_OR,OP_XOR:
  1141. begin
  1142. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
  1143. cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
  1144. end;
  1145. OP_ADD:
  1146. begin
  1147. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
  1148. list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
  1149. end;
  1150. OP_SUB:
  1151. begin
  1152. list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
  1153. list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
  1154. end;
  1155. else
  1156. internalerror(2003083101);
  1157. end;
  1158. end;
  1159. begin
  1160. cg:=tcgarm.create;
  1161. cg64:=tcg64farm.create;
  1162. end.
  1163. {
  1164. $Log$
  1165. Revision 1.27 2003-12-08 17:43:57 florian
  1166. * fixed ldm/stm arm assembler reading
  1167. * fixed a_load_reg_reg with OS_8 on ARM
  1168. * non supported calling conventions cause only a warning now
  1169. Revision 1.26 2003/12/03 17:39:05 florian
  1170. * fixed several arm calling conventions issues
  1171. * fixed reference reading in the assembler reader
  1172. * fixed a_loadaddr_ref_reg
  1173. Revision 1.25 2003/11/30 19:35:29 florian
  1174. * fixed several arm related problems
  1175. Revision 1.24 2003/11/24 15:17:37 florian
  1176. * changed some types to prevend range check errors
  1177. Revision 1.23 2003/11/21 16:29:26 florian
  1178. * fixed reading of reg. sets in the arm assembler reader
  1179. Revision 1.22 2003/11/07 15:58:32 florian
  1180. * Florian's culmutative nr. 1; contains:
  1181. - invalid calling conventions for a certain cpu are rejected
  1182. - arm softfloat calling conventions
  1183. - -Sp for cpu dependend code generation
  1184. - several arm fixes
  1185. - remaining code for value open array paras on heap
  1186. Revision 1.21 2003/11/02 14:30:03 florian
  1187. * fixed ARM for new reg. allocation scheme
  1188. Revision 1.20 2003/10/11 16:06:42 florian
  1189. * fixed some MMX<->SSE
  1190. * started to fix ppc, needs an overhaul
  1191. + stabs info improve for spilling, not sure if it works correctly/completly
  1192. - MMX_SUPPORT removed from Makefile.fpc
  1193. Revision 1.19 2003/09/11 11:55:00 florian
  1194. * improved arm code generation
  1195. * move some protected and private field around
  1196. * the temp. register for register parameters/arguments are now released
  1197. before the move to the parameter register is done. This improves
  1198. the code in a lot of cases.
  1199. Revision 1.18 2003/09/09 12:53:40 florian
  1200. * some assembling problems fixed
  1201. * improved loadaddr_ref_reg
  1202. Revision 1.17 2003/09/06 16:45:51 florian
  1203. * fixed exit code (no preindexed addressing mode in LDM)
  1204. Revision 1.16 2003/09/06 11:21:50 florian
  1205. * fixed stm and ldm to be usable with preindex operand
  1206. Revision 1.15 2003/09/05 23:57:01 florian
  1207. * arm is working again as before the new register naming scheme was implemented
  1208. Revision 1.14 2003/09/04 21:07:03 florian
  1209. * ARM compiler compiles again
  1210. Revision 1.13 2003/09/04 00:15:29 florian
  1211. * first bunch of adaptions of arm compiler for new register type
  1212. Revision 1.12 2003/09/03 19:10:30 florian
  1213. * initial revision of new register naming
  1214. Revision 1.11 2003/09/03 11:18:37 florian
  1215. * fixed arm concatcopy
  1216. + arm support in the common compiler sources added
  1217. * moved some generic cg code around
  1218. + tfputype added
  1219. * ...
  1220. Revision 1.10 2003/09/01 15:11:16 florian
  1221. * fixed reference handling
  1222. * fixed operand postfix for floating point instructions
  1223. * fixed wrong shifter constant handling
  1224. Revision 1.9 2003/09/01 09:54:57 florian
  1225. * results of work on arm port last weekend
  1226. Revision 1.8 2003/08/29 21:36:28 florian
  1227. * fixed procedure entry/exit code
  1228. * started to fix reference handling
  1229. Revision 1.7 2003/08/28 13:26:10 florian
  1230. * another couple of arm fixes
  1231. Revision 1.6 2003/08/28 00:05:29 florian
  1232. * today's arm patches
  1233. Revision 1.5 2003/08/25 23:20:38 florian
  1234. + started to implement FPU support for the ARM
  1235. * fixed a lot of other things
  1236. Revision 1.4 2003/08/24 12:27:26 florian
  1237. * continued to work on the arm port
  1238. Revision 1.3 2003/08/21 03:14:00 florian
  1239. * arm compiler can be compiled; far from being working
  1240. Revision 1.2 2003/08/20 15:50:12 florian
  1241. * more arm stuff
  1242. Revision 1.1 2003/07/21 16:35:30 florian
  1243. * very basic stuff for the arm
  1244. }