cgcpu.pas 49 KB

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