cgcpu.pas 47 KB

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