cgcpu.pas 47 KB

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