cgcpu.pas 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  1. {
  2. Copyright (c) 2008 by Florian Klaempfl
  3. Member of the Free Pascal development team
  4. This unit implements the code generator for the AVR
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,symtype,symdef,
  23. cgbase,cgutils,cgobj,
  24. aasmbase,aasmcpu,aasmtai,aasmdata,
  25. parabase,
  26. cpubase,cpuinfo,node,cg64f32,rgcpu;
  27. type
  28. { tcgavr }
  29. tcgavr = class(tcg)
  30. { true, if the next arithmetic operation should modify the flags }
  31. cgsetflags : boolean;
  32. procedure init_register_allocators;override;
  33. procedure done_register_allocators;override;
  34. function getintregister(list:TAsmList;size:Tcgsize):Tregister;override;
  35. procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);override;
  36. procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
  37. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
  38. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  39. procedure a_call_reg(list : TAsmList;reg: tregister);override;
  40. procedure a_call_ref(list : TAsmList;ref: treference);override;
  41. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
  42. procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  43. { move instructions }
  44. procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);override;
  45. procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
  46. procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
  47. procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
  48. { comparison operations }
  49. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  50. l : tasmlabel);override;
  51. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  52. procedure a_jmp_name(list : TAsmList;const s : string); override;
  53. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  54. procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
  55. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
  56. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  57. procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
  58. procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
  59. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
  60. procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);override;
  61. procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint);
  62. procedure g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean);
  63. procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
  64. // procedure g_save_registers(list : TAsmList);override;
  65. // procedure g_restore_registers(list : TAsmList);override;
  66. procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  67. procedure fixref(list : TAsmList;var ref : treference);
  68. function normalize_ref(list:TAsmList;ref: treference):treference;
  69. procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  70. procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  71. procedure a_adjust_sp(list: TAsmList; value: longint);
  72. end;
  73. tcg64favr = class(tcg64f32)
  74. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  75. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  76. end;
  77. procedure create_codegen;
  78. const
  79. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,
  80. A_NONE,A_MUL,A_MULS,A_NEG,A_COM,A_OR,
  81. A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_ROL,A_ROR);
  82. implementation
  83. uses
  84. globals,verbose,systems,cutils,
  85. fmodule,
  86. symconst,symsym,
  87. tgobj,
  88. procinfo,cpupi,
  89. paramgr;
  90. procedure tcgavr.init_register_allocators;
  91. begin
  92. inherited init_register_allocators;
  93. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
  94. [RS_R0,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
  95. RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
  96. RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25],first_int_imreg,[]);
  97. { rg[R_ADDRESSREGISTER]:=trgintcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE,
  98. [RS_R26,RS_R30],first_int_imreg,[]); }
  99. end;
  100. procedure tcgavr.done_register_allocators;
  101. begin
  102. rg[R_INTREGISTER].free;
  103. // rg[R_ADDRESSREGISTER].free;
  104. inherited done_register_allocators;
  105. end;
  106. function tcgavr.getintregister(list: TAsmList; size: Tcgsize): Tregister;
  107. var
  108. tmp1,tmp2,tmp3 : TRegister;
  109. begin
  110. case size of
  111. OS_8,OS_S8:
  112. Result:=inherited getintregister(list, size);
  113. OS_16,OS_S16:
  114. begin
  115. Result:=inherited getintregister(list, OS_8);
  116. { ensure that the high register can be retrieved by
  117. GetNextReg
  118. }
  119. if inherited getintregister(list, OS_8)<>GetNextReg(Result) then
  120. internalerror(2011021331);
  121. end;
  122. OS_32,OS_S32:
  123. begin
  124. Result:=inherited getintregister(list, OS_8);
  125. tmp1:=inherited getintregister(list, OS_8);
  126. { ensure that the high register can be retrieved by
  127. GetNextReg
  128. }
  129. if tmp1<>GetNextReg(Result) then
  130. internalerror(2011021332);
  131. tmp2:=inherited getintregister(list, OS_8);
  132. { ensure that the upper register can be retrieved by
  133. GetNextReg
  134. }
  135. if tmp2<>GetNextReg(tmp1) then
  136. internalerror(2011021333);
  137. tmp3:=inherited getintregister(list, OS_8);
  138. { ensure that the upper register can be retrieved by
  139. GetNextReg
  140. }
  141. if tmp3<>GetNextReg(tmp2) then
  142. internalerror(2011021334);
  143. end;
  144. else
  145. internalerror(2011021330);
  146. end;
  147. end;
  148. procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);
  149. var
  150. ref: treference;
  151. begin
  152. paraloc.check_simple_location;
  153. paramanager.allocparaloc(list,paraloc.location);
  154. case paraloc.location^.loc of
  155. LOC_REGISTER,LOC_CREGISTER:
  156. a_load_const_reg(list,size,a,paraloc.location^.register);
  157. LOC_REFERENCE:
  158. begin
  159. reference_reset(ref,paraloc.alignment);
  160. ref.base:=paraloc.location^.reference.index;
  161. ref.offset:=paraloc.location^.reference.offset;
  162. a_load_const_ref(list,size,a,ref);
  163. end;
  164. else
  165. internalerror(2002081101);
  166. end;
  167. end;
  168. procedure tcgavr.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
  169. var
  170. tmpref, ref: treference;
  171. location: pcgparalocation;
  172. sizeleft: aint;
  173. begin
  174. location := paraloc.location;
  175. tmpref := r;
  176. sizeleft := paraloc.intsize;
  177. while assigned(location) do
  178. begin
  179. paramanager.allocparaloc(list,location);
  180. case location^.loc of
  181. LOC_REGISTER,LOC_CREGISTER:
  182. a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
  183. LOC_REFERENCE:
  184. begin
  185. reference_reset_base(ref,location^.reference.index,location^.reference.offset,paraloc.alignment);
  186. { doubles in softemu mode have a strange order of registers and references }
  187. if location^.size=OS_32 then
  188. g_concatcopy(list,tmpref,ref,4)
  189. else
  190. begin
  191. g_concatcopy(list,tmpref,ref,sizeleft);
  192. if assigned(location^.next) then
  193. internalerror(2005010710);
  194. end;
  195. end;
  196. LOC_VOID:
  197. begin
  198. // nothing to do
  199. end;
  200. else
  201. internalerror(2002081103);
  202. end;
  203. inc(tmpref.offset,tcgsize2size[location^.size]);
  204. dec(sizeleft,tcgsize2size[location^.size]);
  205. location := location^.next;
  206. end;
  207. end;
  208. procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
  209. var
  210. ref: treference;
  211. tmpreg: tregister;
  212. begin
  213. paraloc.check_simple_location;
  214. paramanager.allocparaloc(list,paraloc.location);
  215. case paraloc.location^.loc of
  216. LOC_REGISTER,LOC_CREGISTER:
  217. a_loadaddr_ref_reg(list,r,paraloc.location^.register);
  218. LOC_REFERENCE:
  219. begin
  220. reference_reset(ref,paraloc.alignment);
  221. ref.base := paraloc.location^.reference.index;
  222. ref.offset := paraloc.location^.reference.offset;
  223. tmpreg := getintregister(list,OS_ADDR);
  224. a_loadaddr_ref_reg(list,r,tmpreg);
  225. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  226. end;
  227. else
  228. internalerror(2002080701);
  229. end;
  230. end;
  231. procedure tcgavr.a_call_name(list : TAsmList;const s : string; weak: boolean);
  232. begin
  233. list.concat(taicpu.op_sym(A_RCALL,current_asmdata.RefAsmSymbol(s)));
  234. {
  235. the compiler does not properly set this flag anymore in pass 1, and
  236. for now we only need it after pass 2 (I hope) (JM)
  237. if not(pi_do_call in current_procinfo.flags) then
  238. internalerror(2003060703);
  239. }
  240. include(current_procinfo.flags,pi_do_call);
  241. end;
  242. procedure tcgavr.a_call_reg(list : TAsmList;reg: tregister);
  243. begin
  244. a_reg_alloc(list,NR_ZLO);
  245. a_reg_alloc(list,NR_ZHI);
  246. list.concat(taicpu.op_reg_reg(A_MOV,NR_ZLO,reg));
  247. list.concat(taicpu.op_reg_reg(A_MOV,NR_ZHI,GetHigh(reg)));
  248. list.concat(taicpu.op_none(A_ICALL));
  249. a_reg_dealloc(list,NR_ZLO);
  250. a_reg_dealloc(list,NR_ZHI);
  251. include(current_procinfo.flags,pi_do_call);
  252. end;
  253. procedure tcgavr.a_call_ref(list : TAsmList;ref: treference);
  254. begin
  255. a_reg_alloc(list,NR_ZLO);
  256. a_reg_alloc(list,NR_ZHI);
  257. a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_ZLO);
  258. list.concat(taicpu.op_none(A_ICALL));
  259. a_reg_dealloc(list,NR_ZLO);
  260. a_reg_dealloc(list,NR_ZHI);
  261. include(current_procinfo.flags,pi_do_call);
  262. end;
  263. procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
  264. var
  265. mask : qword;
  266. shift : byte;
  267. i : byte;
  268. tmpreg : tregister;
  269. begin
  270. mask:=$ff;
  271. shift:=0;
  272. case op of
  273. OP_OR:
  274. begin
  275. for i:=1 to tcgsize2size[size] do
  276. begin
  277. list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift));
  278. reg:=GetNextReg(reg);
  279. mask:=mask shl 8;
  280. inc(shift,8);
  281. end;
  282. end;
  283. OP_AND:
  284. begin
  285. for i:=1 to tcgsize2size[size] do
  286. begin
  287. list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift));
  288. reg:=GetNextReg(reg);
  289. mask:=mask shl 8;
  290. inc(shift,8);
  291. end;
  292. end;
  293. OP_SUB:
  294. begin
  295. list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
  296. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  297. begin
  298. for i:=2 to tcgsize2size[size] do
  299. begin
  300. reg:=GetNextReg(reg);
  301. mask:=mask shl 8;
  302. inc(shift,8);
  303. list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift));
  304. end;
  305. end;
  306. end;
  307. else
  308. begin
  309. tmpreg:=getintregister(list,size);
  310. a_load_const_reg(list,size,a,tmpreg);
  311. a_op_reg_reg(list,op,size,tmpreg,reg);
  312. end;
  313. end;
  314. end;
  315. procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  316. var
  317. tmpreg: tregister;
  318. i : integer;
  319. instr : taicpu;
  320. paraloc1,paraloc2,paraloc3 : TCGPara;
  321. begin
  322. case op of
  323. OP_ADD:
  324. begin
  325. if src<>dst then
  326. a_load_reg_reg(list,size,size,src,dst);
  327. list.concat(taicpu.op_reg_reg(A_ADD,dst,src));
  328. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  329. begin
  330. for i:=2 to tcgsize2size[size] do
  331. begin
  332. dst:=GetNextReg(dst);
  333. src:=GetNextReg(src);
  334. list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
  335. end;
  336. end
  337. else
  338. end;
  339. OP_SUB:
  340. begin
  341. if src<>dst then
  342. a_load_reg_reg(list,size,size,src,dst);
  343. list.concat(taicpu.op_reg_reg(A_SUB,dst,src));
  344. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  345. begin
  346. for i:=2 to tcgsize2size[size] do
  347. begin
  348. dst:=GetNextReg(dst);
  349. src:=GetNextReg(src);
  350. list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
  351. end;
  352. end;
  353. end;
  354. OP_NEG:
  355. begin
  356. if src<>dst then
  357. a_load_reg_reg(list,size,size,src,dst);
  358. if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
  359. begin
  360. tmpreg:=GetNextReg(dst);
  361. for i:=2 to tcgsize2size[size] do
  362. begin
  363. list.concat(taicpu.op_reg(A_COM,tmpreg));
  364. tmpreg:=GetNextReg(tmpreg);
  365. end;
  366. list.concat(taicpu.op_reg(A_NEG,dst));
  367. tmpreg:=GetNextReg(dst);
  368. for i:=2 to tcgsize2size[size] do
  369. begin
  370. list.concat(taicpu.op_const_reg(A_SBCI,-1,dst));
  371. tmpreg:=GetNextReg(tmpreg);
  372. end;
  373. end
  374. else
  375. list.concat(taicpu.op_reg(A_NEG,dst));
  376. end;
  377. OP_NOT:
  378. begin
  379. for i:=1 to tcgsize2size[size] do
  380. begin
  381. if src<>dst then
  382. a_load_reg_reg(list,OS_8,OS_8,src,dst);
  383. list.concat(taicpu.op_reg(A_COM,dst));
  384. src:=GetNextReg(src);
  385. dst:=GetNextReg(dst);
  386. end;
  387. end;
  388. OP_MUL,OP_IMUL:
  389. begin
  390. if size in [OS_8,OS_S8] then
  391. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src))
  392. else if size=OS_16 then
  393. begin
  394. paraloc1.init;
  395. paraloc2.init;
  396. paraloc3.init;
  397. paramanager.getintparaloc(pocall_default,1,paraloc1);
  398. paramanager.getintparaloc(pocall_default,2,paraloc2);
  399. paramanager.getintparaloc(pocall_default,3,paraloc3);
  400. a_load_const_cgpara(list,OS_8,0,paraloc3);
  401. a_load_reg_cgpara(list,OS_16,src,paraloc2);
  402. a_load_reg_cgpara(list,OS_16,dst,paraloc1);
  403. paramanager.freecgpara(list,paraloc3);
  404. paramanager.freecgpara(list,paraloc2);
  405. paramanager.freecgpara(list,paraloc1);
  406. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  407. a_call_name(list,'FPC_MUL_WORD',false);
  408. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  409. cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
  410. cg.a_load_reg_reg(list,OS_16,OS_16,NR_FUNCTION_RESULT_REG,dst);
  411. paraloc3.done;
  412. paraloc2.done;
  413. paraloc1.done;
  414. end
  415. else
  416. internalerror(2011022002);
  417. end;
  418. OP_DIV,OP_IDIV:
  419. { special stuff, needs separate handling inside code }
  420. { generator }
  421. internalerror(2011022001);
  422. OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
  423. begin
  424. { TODO : Shift operators }
  425. end;
  426. OP_AND,OP_OR,OP_XOR:
  427. begin
  428. if src<>dst then
  429. a_load_reg_reg(list,size,size,src,dst);
  430. for i:=1 to tcgsize2size[size] do
  431. begin
  432. list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
  433. dst:=GetNextReg(dst);
  434. src:=GetNextReg(src);
  435. end;
  436. end;
  437. else
  438. internalerror(2011022004);
  439. end;
  440. end;
  441. procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);
  442. var
  443. mask : qword;
  444. shift : byte;
  445. i : byte;
  446. begin
  447. mask:=$ff;
  448. shift:=0;
  449. for i:=1 to tcgsize2size[size] do
  450. begin
  451. list.concat(taicpu.op_reg_const(A_LDI,reg,(qword(a) and mask) shr shift));
  452. mask:=mask shl 8;
  453. inc(shift,8);
  454. reg:=GetNextReg(reg);
  455. end;
  456. end;
  457. function tcgavr.normalize_ref(list:TAsmList;ref: treference):treference;
  458. var
  459. tmpreg : tregister;
  460. tmpref : treference;
  461. l : tasmlabel;
  462. begin
  463. tmpreg:=NR_NO;
  464. Result:=ref;
  465. if ref.addressmode<>AM_UNCHANGED then
  466. internalerror(2011021701);
  467. { Be sure to have a base register }
  468. if (ref.base=NR_NO) then
  469. begin
  470. { only symbol+offset? }
  471. if ref.index=NR_NO then
  472. exit;
  473. ref.base:=ref.index;
  474. ref.index:=NR_NO;
  475. end;
  476. if assigned(ref.symbol) or (ref.offset<>0) then
  477. begin
  478. tmpreg:=getaddressregister(list);
  479. reference_reset(tmpref,0);
  480. tmpref.symbol:=ref.symbol;
  481. tmpref.offset:=lo(word(ref.offset));
  482. tmpref.refaddr:=addr_lo8;
  483. list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
  484. tmpref.offset:=hi(word(ref.offset));
  485. tmpref.refaddr:=addr_hi8;
  486. list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
  487. if (ref.base<>NR_NO) then
  488. begin
  489. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  490. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  491. end;
  492. if (ref.index<>NR_NO) then
  493. begin
  494. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  495. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  496. end;
  497. ref.base:=tmpreg;
  498. ref.index:=NR_NO;
  499. end
  500. else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
  501. begin
  502. tmpreg:=getaddressregister(list);
  503. list.concat(taicpu.op_reg_reg(A_MOVW,tmpreg,ref.index));
  504. list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
  505. list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
  506. ref.base:=tmpreg;
  507. ref.index:=NR_NO;
  508. end;
  509. Result:=ref;
  510. end;
  511. procedure tcgavr.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
  512. var
  513. href : treference;
  514. conv_done: boolean;
  515. tmpreg : tregister;
  516. i : integer;
  517. begin
  518. href:=normalize_ref(list,Ref);
  519. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  520. internalerror(2011021307);
  521. conv_done:=false;
  522. if tosize<>fromsize then
  523. begin
  524. conv_done:=true;
  525. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  526. fromsize:=tosize;
  527. case fromsize of
  528. OS_8:
  529. begin
  530. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  531. href.addressmode:=AM_POSTINCREMENT;
  532. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  533. for i:=2 to tcgsize2size[tosize] do
  534. begin
  535. if (href.offset<>0) or assigned(href.symbol) then
  536. inc(href.offset);
  537. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  538. href.addressmode:=AM_POSTINCREMENT
  539. else
  540. href.addressmode:=AM_UNCHANGED;
  541. list.concat(taicpu.op_ref_reg(A_ST,href,NR_R1));
  542. end;
  543. end;
  544. OS_S8:
  545. begin
  546. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  547. href.addressmode:=AM_POSTINCREMENT;
  548. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  549. if tcgsize2size[tosize]>1 then
  550. begin
  551. tmpreg:=getintregister(list,OS_8);
  552. list.concat(taicpu.op_reg(A_CLR,tmpreg));
  553. list.concat(taicpu.op_reg_const(A_SBIC,reg,7));
  554. list.concat(taicpu.op_reg(A_COM,tmpreg));
  555. for i:=2 to tcgsize2size[tosize] do
  556. begin
  557. if (href.offset<>0) or assigned(href.symbol) then
  558. inc(href.offset);
  559. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  560. href.addressmode:=AM_POSTINCREMENT
  561. else
  562. href.addressmode:=AM_UNCHANGED;
  563. list.concat(taicpu.op_ref_reg(A_ST,href,tmpreg));
  564. end;
  565. end;
  566. end;
  567. OS_16:
  568. begin
  569. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  570. href.addressmode:=AM_POSTINCREMENT;
  571. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  572. if (href.offset<>0) or assigned(href.symbol) then
  573. inc(href.offset)
  574. else if (href.base<>NR_NO) and (tcgsize2size[fromsize]>2) then
  575. href.addressmode:=AM_POSTINCREMENT
  576. else
  577. href.addressmode:=AM_UNCHANGED;
  578. reg:=GetNextReg(reg);
  579. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  580. for i:=3 to tcgsize2size[tosize] do
  581. begin
  582. if (href.offset<>0) or assigned(href.symbol) then
  583. inc(href.offset);
  584. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  585. href.addressmode:=AM_POSTINCREMENT
  586. else
  587. href.addressmode:=AM_UNCHANGED;
  588. list.concat(taicpu.op_ref_reg(A_ST,href,NR_R1));
  589. end;
  590. end;
  591. OS_S16:
  592. begin
  593. if (href.base<>NR_NO) and (tcgsize2size[tosize]>1) then
  594. href.addressmode:=AM_POSTINCREMENT;
  595. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  596. if (href.offset<>0) or assigned(href.symbol) then
  597. inc(href.offset)
  598. else if (href.base<>NR_NO) and (tcgsize2size[fromsize]>2) then
  599. href.addressmode:=AM_POSTINCREMENT
  600. else
  601. href.addressmode:=AM_UNCHANGED;
  602. reg:=GetNextReg(reg);
  603. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  604. if tcgsize2size[tosize]>2 then
  605. begin
  606. tmpreg:=getintregister(list,OS_8);
  607. list.concat(taicpu.op_reg(A_CLR,tmpreg));
  608. list.concat(taicpu.op_reg_const(A_SBIC,reg,7));
  609. list.concat(taicpu.op_reg(A_COM,tmpreg));
  610. for i:=3 to tcgsize2size[tosize] do
  611. begin
  612. if (href.offset<>0) or assigned(href.symbol) then
  613. inc(href.offset);
  614. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  615. href.addressmode:=AM_POSTINCREMENT
  616. else
  617. href.addressmode:=AM_UNCHANGED;
  618. list.concat(taicpu.op_ref_reg(A_ST,href,tmpreg));
  619. end;
  620. end;
  621. end;
  622. else
  623. conv_done:=false;
  624. end;
  625. end;
  626. if not conv_done then
  627. begin
  628. for i:=1 to tcgsize2size[fromsize] do
  629. begin
  630. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  631. href.addressmode:=AM_POSTINCREMENT
  632. else
  633. href.addressmode:=AM_UNCHANGED;
  634. list.concat(taicpu.op_ref_reg(A_ST,href,reg));
  635. if (href.offset<>0) or assigned(href.symbol) then
  636. inc(href.offset);
  637. reg:=GetNextReg(reg);
  638. end;
  639. end;
  640. end;
  641. procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
  642. const Ref : treference;reg : tregister);
  643. var
  644. href : treference;
  645. conv_done: boolean;
  646. tmpreg : tregister;
  647. i : integer;
  648. begin
  649. href:=normalize_ref(list,Ref);
  650. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  651. internalerror(2011021307);
  652. conv_done:=false;
  653. if tosize<>fromsize then
  654. begin
  655. conv_done:=true;
  656. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  657. fromsize:=tosize;
  658. case fromsize of
  659. OS_8:
  660. begin
  661. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  662. for i:=2 to tcgsize2size[tosize] do
  663. begin
  664. reg:=GetNextReg(reg);
  665. list.concat(taicpu.op_reg(A_CLR,reg));
  666. end;
  667. end;
  668. OS_S8:
  669. begin
  670. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  671. tmpreg:=reg;
  672. if tcgsize2size[tosize]>1 then
  673. begin
  674. reg:=GetNextReg(reg);
  675. list.concat(taicpu.op_reg(A_CLR,reg));
  676. list.concat(taicpu.op_reg_const(A_SBIC,tmpreg,7));
  677. list.concat(taicpu.op_reg(A_COM,reg));
  678. tmpreg:=reg;
  679. for i:=3 to tcgsize2size[tosize] do
  680. begin
  681. reg:=GetNextReg(reg);
  682. emit_mov(list,reg,tmpreg);
  683. end;
  684. end;
  685. end;
  686. OS_16:
  687. begin
  688. if href.base<>NR_NO then
  689. href.addressmode:=AM_POSTINCREMENT;
  690. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  691. if (href.offset<>0) or assigned(href.symbol) then
  692. inc(href.offset);
  693. href.addressmode:=AM_UNCHANGED;
  694. reg:=GetNextReg(reg);
  695. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  696. for i:=3 to tcgsize2size[tosize] do
  697. begin
  698. reg:=GetNextReg(reg);
  699. list.concat(taicpu.op_reg(A_CLR,reg));
  700. end;
  701. end;
  702. OS_S16:
  703. begin
  704. if href.base<>NR_NO then
  705. href.addressmode:=AM_POSTINCREMENT;
  706. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  707. if (href.offset<>0) or assigned(href.symbol) then
  708. inc(href.offset);
  709. href.addressmode:=AM_UNCHANGED;
  710. reg:=GetNextReg(reg);
  711. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  712. tmpreg:=reg;
  713. reg:=GetNextReg(reg);
  714. list.concat(taicpu.op_reg(A_CLR,reg));
  715. list.concat(taicpu.op_reg_const(A_SBIC,tmpreg,7));
  716. list.concat(taicpu.op_reg(A_COM,reg));
  717. tmpreg:=reg;
  718. for i:=4 to tcgsize2size[tosize] do
  719. begin
  720. reg:=GetNextReg(reg);
  721. emit_mov(list,reg,tmpreg);
  722. end;
  723. end;
  724. else
  725. conv_done:=false;
  726. end;
  727. end;
  728. if not conv_done then
  729. begin
  730. for i:=1 to tcgsize2size[fromsize] do
  731. begin
  732. if (href.base<>NR_NO) and (i<tcgsize2size[fromsize]) then
  733. href.addressmode:=AM_POSTINCREMENT
  734. else
  735. href.addressmode:=AM_UNCHANGED;
  736. list.concat(taicpu.op_reg_ref(A_LD,reg,href));
  737. if (href.offset<>0) or assigned(href.symbol) then
  738. inc(href.offset);
  739. reg:=GetNextReg(reg);
  740. end;
  741. end;
  742. end;
  743. procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
  744. var
  745. conv_done: boolean;
  746. tmpreg : tregister;
  747. i : integer;
  748. begin
  749. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  750. internalerror(2011021310);
  751. conv_done:=false;
  752. if tosize<>fromsize then
  753. begin
  754. conv_done:=true;
  755. if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  756. fromsize:=tosize;
  757. case fromsize of
  758. OS_8:
  759. begin
  760. emit_mov(list,reg2,reg1);
  761. for i:=2 to tcgsize2size[tosize] do
  762. begin
  763. reg2:=GetNextReg(reg2);
  764. list.concat(taicpu.op_reg(A_CLR,reg2));
  765. end;
  766. end;
  767. OS_S8:
  768. begin
  769. { dest is always at least 16 bit at this point }
  770. emit_mov(list,reg2,reg1);
  771. reg2:=GetNextReg(reg2);
  772. list.concat(taicpu.op_reg(A_CLR,reg2));
  773. list.concat(taicpu.op_reg_const(A_SBIC,reg1,7));
  774. list.concat(taicpu.op_reg(A_COM,reg2));
  775. tmpreg:=reg2;
  776. for i:=3 to tcgsize2size[tosize] do
  777. begin
  778. reg2:=GetNextReg(reg2);
  779. emit_mov(list,reg2,tmpreg);
  780. end;
  781. end;
  782. OS_16:
  783. begin
  784. emit_mov(list,reg2,reg1);
  785. reg1:=GetNextReg(reg1);
  786. reg2:=GetNextReg(reg2);
  787. emit_mov(list,reg2,reg1);
  788. for i:=3 to tcgsize2size[tosize] do
  789. begin
  790. reg2:=GetNextReg(reg2);
  791. list.concat(taicpu.op_reg(A_CLR,reg2));
  792. end;
  793. end;
  794. OS_S16:
  795. begin
  796. { dest is always at least 32 bit at this point }
  797. emit_mov(list,reg2,reg1);
  798. reg1:=GetNextReg(reg1);
  799. reg2:=GetNextReg(reg2);
  800. emit_mov(list,reg2,reg1);
  801. reg2:=GetNextReg(reg2);
  802. list.concat(taicpu.op_reg(A_CLR,reg2));
  803. list.concat(taicpu.op_reg_const(A_SBIC,reg1,7));
  804. list.concat(taicpu.op_reg(A_COM,reg2));
  805. tmpreg:=reg2;
  806. for i:=4 to tcgsize2size[tosize] do
  807. begin
  808. reg2:=GetNextReg(reg2);
  809. emit_mov(list,reg2,tmpreg);
  810. end;
  811. end;
  812. else
  813. conv_done:=false;
  814. end;
  815. end;
  816. if not conv_done and (reg1<>reg2) then
  817. begin
  818. for i:=1 to tcgsize2size[fromsize] do
  819. begin
  820. emit_mov(list,reg2,reg1);
  821. reg1:=GetNextReg(reg1);
  822. reg2:=GetNextReg(reg2);
  823. end;
  824. end;
  825. end;
  826. { comparison operations }
  827. procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
  828. l : tasmlabel);
  829. begin
  830. { TODO : a_cmp_const_reg_label }
  831. end;
  832. procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
  833. begin
  834. { TODO : a_cmp_reg_reg_label }
  835. end;
  836. procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
  837. begin
  838. internalerror(2011021313);
  839. end;
  840. procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
  841. var
  842. ai : taicpu;
  843. begin
  844. ai:=taicpu.op_sym(A_JMP,l);
  845. ai.is_jmp:=true;
  846. list.concat(ai);
  847. end;
  848. procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
  849. var
  850. ai : taicpu;
  851. begin
  852. ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
  853. ai.is_jmp:=true;
  854. list.concat(ai);
  855. end;
  856. procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
  857. begin
  858. { TODO : implement g_flags2reg }
  859. end;
  860. procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
  861. var
  862. i : integer;
  863. begin
  864. case value of
  865. 0:
  866. ;
  867. -14..-1:
  868. begin
  869. if ((-value) mod 2)<>0 then
  870. list.concat(taicpu.op_reg(A_PUSH,NR_R0));
  871. for i:=1 to (-value) div 2 do
  872. list.concat(taicpu.op_const(A_RCALL,0));
  873. end;
  874. 1..7:
  875. begin
  876. for i:=1 to value do
  877. list.concat(taicpu.op_reg(A_POP,NR_R0));
  878. end;
  879. else
  880. begin
  881. list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
  882. list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
  883. // get SREG
  884. list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
  885. // block interrupts
  886. list.concat(taicpu.op_none(A_CLI));
  887. // write high SP
  888. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
  889. // release interrupts
  890. list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
  891. // write low SP
  892. list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
  893. end;
  894. end;
  895. end;
  896. procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  897. var
  898. regs : tcpuregisterset;
  899. reg : tsuperregister;
  900. begin
  901. if not(nostackframe) then
  902. begin
  903. { save int registers }
  904. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  905. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  906. regs:=regs+[RS_R28,RS_R29];
  907. for reg:=RS_R31 downto RS_R0 do
  908. if reg in regs then
  909. list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  910. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  911. begin
  912. list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
  913. list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
  914. end
  915. else
  916. { the framepointer cannot be omitted on avr because sp
  917. is not a register but part of the i/o map
  918. }
  919. internalerror(2011021901);
  920. a_adjust_sp(list,-localsize);
  921. end;
  922. end;
  923. procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
  924. var
  925. regs : tcpuregisterset;
  926. reg : TSuperRegister;
  927. LocalSize : longint;
  928. begin
  929. if not(nostackframe) then
  930. begin
  931. if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
  932. begin
  933. LocalSize:=current_procinfo.calc_stackframe_size;
  934. a_adjust_sp(list,LocalSize);
  935. regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
  936. for reg:=RS_R0 to RS_R31 do
  937. if reg in regs then
  938. list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
  939. end
  940. else
  941. { the framepointer cannot be omitted on avr because sp
  942. is not a register but part of the i/o map
  943. }
  944. internalerror(2011021902);
  945. end;
  946. list.concat(taicpu.op_none(A_RET));
  947. end;
  948. procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
  949. begin
  950. { TODO : a_loadaddr_ref_reg }
  951. end;
  952. procedure tcgavr.fixref(list : TAsmList;var ref : treference);
  953. begin
  954. internalerror(2011021320);
  955. end;
  956. procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint);
  957. var
  958. paraloc1,paraloc2,paraloc3 : TCGPara;
  959. begin
  960. paraloc1.init;
  961. paraloc2.init;
  962. paraloc3.init;
  963. paramanager.getintparaloc(pocall_default,1,paraloc1);
  964. paramanager.getintparaloc(pocall_default,2,paraloc2);
  965. paramanager.getintparaloc(pocall_default,3,paraloc3);
  966. a_load_const_cgpara(list,OS_INT,len,paraloc3);
  967. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  968. a_loadaddr_ref_cgpara(list,source,paraloc1);
  969. paramanager.freecgpara(list,paraloc3);
  970. paramanager.freecgpara(list,paraloc2);
  971. paramanager.freecgpara(list,paraloc1);
  972. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  973. a_call_name_static(list,'FPC_MOVE');
  974. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  975. paraloc3.done;
  976. paraloc2.done;
  977. paraloc1.done;
  978. end;
  979. procedure tcgavr.g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean);
  980. begin
  981. internalerror(2011021321);
  982. end;
  983. procedure tcgavr.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);
  984. begin
  985. g_concatcopy_internal(list,source,dest,len,false);
  986. end;
  987. procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);
  988. var
  989. countreg,tmpreg : tregister;
  990. srcref,dstref : treference;
  991. copysize,countregsize : tcgsize;
  992. l : TAsmLabel;
  993. i : longint;
  994. begin
  995. current_asmdata.getjumplabel(l);
  996. if len>16 then
  997. begin
  998. reference_reset(srcref,0);
  999. reference_reset(dstref,0);
  1000. { TODO : load refs! }
  1001. copysize:=OS_8;
  1002. if len<256 then
  1003. countregsize:=OS_8
  1004. else if len<65536 then
  1005. countregsize:=OS_16
  1006. else
  1007. internalerror(2011022007);
  1008. countreg:=getintregister(list,countregsize);
  1009. a_load_const_reg(list,countregsize,len,countreg);
  1010. cg.a_label(list,l);
  1011. tmpreg:=getintregister(list,copysize);
  1012. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  1013. list.concat(taicpu.op_ref_reg(A_ST,dstref,tmpreg));
  1014. a_op_const_reg(list,OP_SUB,countregsize,1,countreg);
  1015. a_jmp_flags(list,F_NE,l);
  1016. end
  1017. else
  1018. begin
  1019. for i:=1 to len do
  1020. begin
  1021. srcref:=normalize_ref(list,source);
  1022. dstref:=normalize_ref(list,source);
  1023. copysize:=OS_8;
  1024. tmpreg:=getintregister(list,copysize);
  1025. if (srcref.base<>NR_NO) and (i<len) then
  1026. srcref.addressmode:=AM_POSTINCREMENT
  1027. else
  1028. srcref.addressmode:=AM_UNCHANGED;
  1029. if (dstref.base<>NR_NO) and (i<len) then
  1030. dstref.addressmode:=AM_POSTINCREMENT
  1031. else
  1032. dstref.addressmode:=AM_UNCHANGED;
  1033. list.concat(taicpu.op_reg_ref(A_LD,tmpreg,srcref));
  1034. list.concat(taicpu.op_ref_reg(A_ST,dstref,tmpreg));
  1035. if (dstref.offset<>0) or assigned(dstref.symbol) then
  1036. inc(dstref.offset);
  1037. if (srcref.offset<>0) or assigned(srcref.symbol) then
  1038. inc(srcref.offset);
  1039. end;
  1040. end;
  1041. end;
  1042. procedure tcgavr.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
  1043. var
  1044. hl : tasmlabel;
  1045. ai : taicpu;
  1046. cond : TAsmCond;
  1047. begin
  1048. if not(cs_check_overflow in current_settings.localswitches) then
  1049. exit;
  1050. current_asmdata.getjumplabel(hl);
  1051. if not ((def.typ=pointerdef) or
  1052. ((def.typ=orddef) and
  1053. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,pasbool]))) then
  1054. cond:=C_VC
  1055. else
  1056. cond:=C_CC;
  1057. ai:=Taicpu.Op_Sym(A_BRxx,hl);
  1058. ai.SetCondition(cond);
  1059. ai.is_jmp:=true;
  1060. list.concat(ai);
  1061. a_call_name(list,'FPC_OVERFLOW',false);
  1062. a_label(list,hl);
  1063. end;
  1064. procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
  1065. var
  1066. ai : taicpu;
  1067. begin
  1068. { TODO : fix a_jmp_cond }
  1069. {
  1070. ai:=Taicpu.Op_sym(A_BRxx,l);
  1071. case cond of
  1072. OC_EQ:
  1073. ai.SetCondition(C_EQ);
  1074. OC_GT
  1075. OC_LT
  1076. OC_GTE
  1077. OC_LTE
  1078. OC_NE
  1079. OC_BE
  1080. OC_B
  1081. OC_AE
  1082. OC_A:
  1083. ai.is_jmp:=true;
  1084. list.concat(ai);
  1085. }
  1086. end;
  1087. procedure tcgavr.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
  1088. begin
  1089. internalerror(2011021324);
  1090. end;
  1091. procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
  1092. var
  1093. instr: taicpu;
  1094. begin
  1095. instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
  1096. list.Concat(instr);
  1097. { Notify the register allocator that we have written a move instruction so
  1098. it can try to eliminate it. }
  1099. add_move_instruction(instr);
  1100. end;
  1101. procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  1102. begin
  1103. { TODO : a_op64_reg_reg }
  1104. end;
  1105. procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  1106. begin
  1107. { TODO : a_op64_const_reg }
  1108. end;
  1109. procedure create_codegen;
  1110. begin
  1111. cg:=tcgavr.create;
  1112. cg64:=tcg64favr.create;
  1113. end;
  1114. end.