cgcpu.pas 138 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the code generator for the i8086
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit cgcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. cgbase,cgobj,cg64f32,cgx86,
  23. aasmbase,aasmtai,aasmdata,aasmcpu,
  24. cpubase,parabase,cgutils,
  25. symconst,symdef
  26. ;
  27. type
  28. { tcg8086 }
  29. tcg8086 = class(tcgx86)
  30. procedure init_register_allocators;override;
  31. procedure do_register_allocation(list:TAsmList;headertai:tai);override;
  32. procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
  33. procedure a_call_name_far(list : TAsmList;const s : string; weak: boolean);
  34. procedure a_call_name_static(list : TAsmList;const s : string);override;
  35. procedure a_call_name_static_far(list : TAsmList;const s : string);
  36. procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
  37. procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); override;
  38. procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  39. procedure a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
  40. procedure a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
  41. procedure a_op_ref(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference); override;
  42. procedure push_const(list:TAsmList;size:tcgsize;a:tcgint);
  43. { passing parameter using push instead of mov }
  44. procedure a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
  45. procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);override;
  46. procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);override;
  47. procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);override;
  48. { move instructions }
  49. procedure a_load_const_reg(list : TAsmList; tosize: tcgsize; a : tcgint;reg : tregister);override;
  50. procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);override;
  51. procedure a_load_reg_ref(list : TAsmList;fromsize,tosize: tcgsize; reg : tregister;const ref : treference);override;
  52. { use a_load_ref_reg_internal() instead }
  53. //procedure a_load_ref_reg(list : TAsmList;fromsize,tosize: tcgsize;const ref : treference;reg : tregister);override;
  54. procedure a_load_reg_reg(list : TAsmList;fromsize,tosize: tcgsize;reg1,reg2 : tregister);override;
  55. { comparison operations }
  56. procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
  57. l : tasmlabel);override;
  58. procedure a_cmp_const_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;const ref : treference;
  59. l : tasmlabel);override;
  60. procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  61. procedure a_cmp_ref_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister; l : tasmlabel); override;
  62. procedure a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister; const ref: treference; l : tasmlabel); override;
  63. procedure gen_cmp32_jmp1(list: TAsmList; cmp_op: topcmp; l_skip, l_target: TAsmLabel);
  64. procedure gen_cmp32_jmp2(list: TAsmList; cmp_op: topcmp; l_skip, l_target: TAsmLabel);
  65. procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);override;
  66. procedure g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref: TReference);override;
  67. procedure g_stackpointer_alloc(list : TAsmList;localsize: longint);override;
  68. procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
  69. procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);
  70. procedure g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
  71. procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);override;
  72. procedure get_32bit_ops(op: TOpCG; out op1,op2: TAsmOp);
  73. protected
  74. procedure a_load_ref_reg_internal(list : TAsmList;fromsize,tosize: tcgsize;const ref : treference;reg : tregister;isdirect:boolean);override;
  75. end;
  76. tcg64f8086 = class(tcg64f32)
  77. procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
  78. procedure a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);override;
  79. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  80. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  81. procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
  82. procedure a_op64_ref(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference);override;
  83. private
  84. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  85. end;
  86. procedure create_codegen;
  87. implementation
  88. uses
  89. globals,verbose,systems,cutils,
  90. paramgr,procinfo,fmodule,
  91. rgcpu,rgx86,cpuinfo,
  92. symtype,symsym,symcpu,
  93. tgobj,
  94. hlcgobj;
  95. { Range check must be disabled explicitly as the code uses
  96. implicit typecast to aint troughout }
  97. {$R-}
  98. function use_push(const cgpara:tcgpara):boolean;
  99. begin
  100. result:=(not paramanager.use_fixed_stack) and
  101. assigned(cgpara.location) and
  102. (cgpara.location^.loc=LOC_REFERENCE) and
  103. (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
  104. end;
  105. procedure tcg8086.init_register_allocators;
  106. begin
  107. inherited init_register_allocators;
  108. if cs_create_pic in current_settings.moduleswitches then
  109. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_AX,RS_DX,RS_CX,RS_SI,RS_DI],first_int_imreg,[RS_BP])
  110. else
  111. if (cs_useebp in current_settings.optimizerswitches) and assigned(current_procinfo) and (current_procinfo.framepointer<>NR_BP) then
  112. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_AX,RS_DX,RS_CX,RS_BX,RS_SI,RS_DI,RS_BP],first_int_imreg,[])
  113. else
  114. rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_AX,RS_DX,RS_CX,RS_BX,RS_SI,RS_DI],first_int_imreg,[RS_BP]);
  115. rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
  116. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBWHOLE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
  117. rgfpu:=Trgx86fpu.create;
  118. end;
  119. procedure tcg8086.do_register_allocation(list:TAsmList;headertai:tai);
  120. begin
  121. if (tf_pic_uses_got in target_info.flags) and (pi_needs_got in current_procinfo.flags) then
  122. begin
  123. if getsupreg(current_procinfo.got) < first_int_imreg then
  124. include(rg[R_INTREGISTER].used_in_proc,getsupreg(current_procinfo.got));
  125. end;
  126. inherited do_register_allocation(list,headertai);
  127. end;
  128. procedure tcg8086.a_call_name(list: TAsmList; const s: string; weak: boolean);
  129. begin
  130. if current_settings.x86memorymodel in x86_far_code_models then
  131. a_call_name_far(list,s,weak)
  132. else
  133. a_call_name_near(list,s,weak);
  134. end;
  135. procedure tcg8086.a_call_name_far(list: TAsmList; const s: string;
  136. weak: boolean);
  137. var
  138. sym : tasmsymbol;
  139. begin
  140. if not(weak) then
  141. sym:=current_asmdata.RefAsmSymbol(s,AT_FUNCTION)
  142. else
  143. sym:=current_asmdata.WeakRefAsmSymbol(s,AT_FUNCTION);
  144. list.concat(taicpu.op_sym(A_CALL,S_FAR,sym));
  145. end;
  146. procedure tcg8086.a_call_name_static(list: TAsmList; const s: string);
  147. begin
  148. if current_settings.x86memorymodel in x86_far_code_models then
  149. a_call_name_static_far(list,s)
  150. else
  151. a_call_name_static_near(list,s);
  152. end;
  153. procedure tcg8086.a_call_name_static_far(list: TAsmList; const s: string);
  154. var
  155. sym : tasmsymbol;
  156. begin
  157. sym:=current_asmdata.RefAsmSymbol(s,AT_FUNCTION);
  158. list.concat(taicpu.op_sym(A_CALL,S_FAR,sym));
  159. end;
  160. procedure tcg8086.a_op_const_reg(list: TAsmList; Op: TOpCG; size: TCGSize;
  161. a: tcgint; reg: TRegister);
  162. type
  163. trox32method=(rm_unspecified,rm_unrolledleftloop,rm_unrolledrightloop,
  164. rm_loopleft,rm_loopright,rm_fast_386);
  165. var
  166. tmpreg: tregister;
  167. op1, op2: TAsmOp;
  168. ax_subreg: tregister;
  169. hl_loop_start: tasmlabel;
  170. ai: taicpu;
  171. use_loop, use_186_fast_shift, use_8086_fast_shift,
  172. use_386_fast_shift: Boolean;
  173. rox32method: trox32method=rm_unspecified;
  174. i: Integer;
  175. rol_amount, ror_amount: TCGInt;
  176. begin
  177. optimize_op_const(size, op, a);
  178. check_register_size(size,reg);
  179. if size in [OS_64, OS_S64] then
  180. internalerror(2013030904);
  181. if size in [OS_32, OS_S32] then
  182. begin
  183. case op of
  184. OP_NONE:
  185. begin
  186. { Opcode is optimized away }
  187. end;
  188. OP_MOVE:
  189. begin
  190. { Optimized, replaced with a simple load }
  191. a_load_const_reg(list,size,a,reg);
  192. end;
  193. OP_ADD, OP_SUB:
  194. begin
  195. get_32bit_ops(op, op1, op2);
  196. { Optimization when the low 16-bits of the constant are 0 }
  197. if aint(a and $FFFF) = 0 then
  198. begin
  199. { use a_op_const_reg to allow the use of inc/dec }
  200. a_op_const_reg(list,op,OS_16,aint(a shr 16),GetNextReg(reg));
  201. end
  202. else
  203. begin
  204. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  205. list.concat(taicpu.op_const_reg(op1,S_W,aint(a and $FFFF),reg));
  206. list.concat(taicpu.op_const_reg(op2,S_W,aint(a shr 16),GetNextReg(reg)));
  207. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  208. end;
  209. end;
  210. OP_AND, OP_OR, OP_XOR:
  211. begin
  212. { low word operation }
  213. if aint(a and $FFFF) = aint(0) then
  214. begin
  215. case op of
  216. OP_AND:
  217. a_load_const_reg(list,OS_16,aint(0),reg);
  218. OP_OR,OP_XOR:
  219. {do nothing};
  220. else
  221. InternalError(2013100704);
  222. end;
  223. end
  224. else if aint(a and $FFFF) = aint($FFFF) then
  225. begin
  226. case op of
  227. OP_AND:
  228. {do nothing};
  229. OP_OR:
  230. a_load_const_reg(list,OS_16,aint($FFFF),reg);
  231. OP_XOR:
  232. list.concat(taicpu.op_reg(A_NOT,S_W,reg));
  233. else
  234. InternalError(2013100705);
  235. end;
  236. end
  237. else
  238. a_op_const_reg(list,op,OS_16,aint(a and $FFFF),reg);
  239. { high word operation }
  240. if aint(a shr 16) = aint(0) then
  241. begin
  242. case op of
  243. OP_AND:
  244. a_load_const_reg(list,OS_16,aint(0),GetNextReg(reg));
  245. OP_OR,OP_XOR:
  246. {do nothing};
  247. else
  248. InternalError(2013100706);
  249. end;
  250. end
  251. else if aint(a shr 16) = aint($FFFF) then
  252. begin
  253. case op of
  254. OP_AND:
  255. {do nothing};
  256. OP_OR:
  257. a_load_const_reg(list,OS_16,aint($FFFF),GetNextReg(reg));
  258. OP_XOR:
  259. list.concat(taicpu.op_reg(A_NOT,S_W,GetNextReg(reg)));
  260. else
  261. InternalError(2013100707);
  262. end;
  263. end
  264. else
  265. a_op_const_reg(list,op,OS_16,aint(a shr 16),GetNextReg(reg));
  266. end;
  267. OP_SHR,OP_SHL,OP_SAR:
  268. begin
  269. a:=a and 31;
  270. { for shl with const >= 16, we can just move the low register
  271. to the high reg, then zero the low register, then do the
  272. remaining part of the shift (by const-16) in 16 bit on the
  273. high register. the same thing applies to shr with low and high
  274. reversed. sar is exactly like shr, except that instead of
  275. zeroing the high register, we sar it by 15. }
  276. if a>=16 then
  277. case op of
  278. OP_SHR:
  279. begin
  280. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),reg);
  281. a_load_const_reg(list,OS_16,0,GetNextReg(reg));
  282. a_op_const_reg(list,OP_SHR,OS_16,a-16,reg);
  283. end;
  284. OP_SHL:
  285. begin
  286. a_load_reg_reg(list,OS_16,OS_16,reg,GetNextReg(reg));
  287. a_load_const_reg(list,OS_16,0,reg);
  288. a_op_const_reg(list,OP_SHL,OS_16,a-16,GetNextReg(reg));
  289. end;
  290. OP_SAR:
  291. begin
  292. if a=31 then
  293. begin
  294. a_op_const_reg(list,OP_SAR,OS_16,15,GetNextReg(reg));
  295. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),reg);
  296. end
  297. else
  298. begin
  299. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),reg);
  300. a_op_const_reg(list,OP_SAR,OS_16,15,GetNextReg(reg));
  301. a_op_const_reg(list,OP_SAR,OS_16,a-16,reg);
  302. end;
  303. end;
  304. else
  305. internalerror(2013060201);
  306. end
  307. else if a<>0 then
  308. begin
  309. use_loop:=a>2;
  310. use_386_fast_shift:=(current_settings.cputype>=cpu_386) and (a>1);
  311. use_186_fast_shift:=not use_386_fast_shift
  312. and (current_settings.cputype>=cpu_186) and (a>2)
  313. and not (cs_opt_size in current_settings.optimizerswitches);
  314. use_8086_fast_shift:=(current_settings.cputype<cpu_186) and (a>2)
  315. and not (cs_opt_size in current_settings.optimizerswitches);
  316. if use_386_fast_shift then
  317. begin
  318. case op of
  319. OP_SHR:
  320. begin
  321. list.concat(taicpu.op_const_reg_reg(A_SHRD,S_W,a,GetNextReg(reg),reg));
  322. list.concat(taicpu.op_const_reg(A_SHR,S_W,a,GetNextReg(reg)));
  323. end;
  324. OP_SAR:
  325. begin
  326. list.concat(taicpu.op_const_reg_reg(A_SHRD,S_W,a,GetNextReg(reg),reg));
  327. list.concat(taicpu.op_const_reg(A_SAR,S_W,a,GetNextReg(reg)));
  328. end;
  329. OP_SHL:
  330. begin
  331. list.concat(taicpu.op_const_reg_reg(A_SHLD,S_W,a,reg,GetNextReg(reg)));
  332. list.concat(taicpu.op_const_reg(A_SHL,S_W,a,reg));
  333. end;
  334. else
  335. internalerror(2017040401);
  336. end;
  337. end
  338. else if use_186_fast_shift then
  339. begin
  340. tmpreg:=getintregister(list,OS_16);
  341. case op of
  342. OP_SHR:
  343. begin
  344. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),tmpreg);
  345. list.concat(taicpu.op_const_reg(A_SHR,S_W,a,GetNextReg(reg)));
  346. list.concat(taicpu.op_const_reg(A_SHR,S_W,a,reg));
  347. list.concat(taicpu.op_const_reg(A_SHL,S_W,16-a,tmpreg));
  348. list.concat(taicpu.op_reg_reg(A_OR,S_W,tmpreg,reg));
  349. end;
  350. OP_SAR:
  351. begin
  352. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),tmpreg);
  353. list.concat(taicpu.op_const_reg(A_SAR,S_W,a,GetNextReg(reg)));
  354. list.concat(taicpu.op_const_reg(A_SHR,S_W,a,reg));
  355. list.concat(taicpu.op_const_reg(A_SHL,S_W,16-a,tmpreg));
  356. list.concat(taicpu.op_reg_reg(A_OR,S_W,tmpreg,reg));
  357. end;
  358. OP_SHL:
  359. begin
  360. a_load_reg_reg(list,OS_16,OS_16,reg,tmpreg);
  361. list.concat(taicpu.op_const_reg(A_SHL,S_W,a,reg));
  362. list.concat(taicpu.op_const_reg(A_SHL,S_W,a,GetNextReg(reg)));
  363. list.concat(taicpu.op_const_reg(A_SHR,S_W,16-a,tmpreg));
  364. list.concat(taicpu.op_reg_reg(A_OR,S_W,tmpreg,GetNextReg(reg)));
  365. end;
  366. else
  367. internalerror(2017040301);
  368. end;
  369. end
  370. else if use_8086_fast_shift then
  371. begin
  372. getcpuregister(list,NR_CX);
  373. a_load_const_reg(list,OS_8,a,NR_CL);
  374. tmpreg:=getintregister(list,OS_16);
  375. case op of
  376. OP_SHR:
  377. begin
  378. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),tmpreg);
  379. list.concat(taicpu.op_reg_reg(A_SHR,S_W,NR_CL,GetNextReg(reg)));
  380. list.concat(taicpu.op_reg_reg(A_SHR,S_W,NR_CL,reg));
  381. if a<>8 then
  382. a_load_const_reg(list,OS_8,16-a,NR_CL);
  383. list.concat(taicpu.op_reg_reg(A_SHL,S_W,NR_CL,tmpreg));
  384. list.concat(taicpu.op_reg_reg(A_OR,S_W,tmpreg,reg));
  385. end;
  386. OP_SAR:
  387. begin
  388. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),tmpreg);
  389. list.concat(taicpu.op_reg_reg(A_SAR,S_W,NR_CL,GetNextReg(reg)));
  390. list.concat(taicpu.op_reg_reg(A_SHR,S_W,NR_CL,reg));
  391. if a<>8 then
  392. a_load_const_reg(list,OS_8,16-a,NR_CL);
  393. list.concat(taicpu.op_reg_reg(A_SHL,S_W,NR_CL,tmpreg));
  394. list.concat(taicpu.op_reg_reg(A_OR,S_W,tmpreg,reg));
  395. end;
  396. OP_SHL:
  397. begin
  398. a_load_reg_reg(list,OS_16,OS_16,reg,tmpreg);
  399. list.concat(taicpu.op_reg_reg(A_SHL,S_W,NR_CL,reg));
  400. list.concat(taicpu.op_reg_reg(A_SHL,S_W,NR_CL,GetNextReg(reg)));
  401. if a<>8 then
  402. a_load_const_reg(list,OS_8,16-a,NR_CL);
  403. list.concat(taicpu.op_reg_reg(A_SHR,S_W,NR_CL,tmpreg));
  404. list.concat(taicpu.op_reg_reg(A_OR,S_W,tmpreg,GetNextReg(reg)));
  405. end;
  406. else
  407. internalerror(2017040302);
  408. end;
  409. ungetcpuregister(list,NR_CX);
  410. end
  411. else if use_loop then
  412. begin
  413. getcpuregister(list,NR_CX);
  414. a_load_const_reg(list,OS_16,a,NR_CX);
  415. current_asmdata.getjumplabel(hl_loop_start);
  416. a_label(list,hl_loop_start);
  417. case op of
  418. OP_SHR:
  419. begin
  420. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  421. list.concat(taicpu.op_const_reg(A_SHR,S_W,1,GetNextReg(reg)));
  422. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
  423. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  424. end;
  425. OP_SAR:
  426. begin
  427. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  428. list.concat(taicpu.op_const_reg(A_SAR,S_W,1,GetNextReg(reg)));
  429. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
  430. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  431. end;
  432. OP_SHL:
  433. begin
  434. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  435. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,reg));
  436. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,GetNextReg(reg)));
  437. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  438. end;
  439. else
  440. internalerror(2013030903);
  441. end;
  442. ai:=Taicpu.Op_Sym(A_LOOP,S_W,hl_loop_start);
  443. ai.is_jmp:=true;
  444. list.concat(ai);
  445. ungetcpuregister(list,NR_CX);
  446. end
  447. else
  448. begin
  449. for i:=1 to a do
  450. begin
  451. case op of
  452. OP_SHR:
  453. begin
  454. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  455. list.concat(taicpu.op_const_reg(A_SHR,S_W,1,GetNextReg(reg)));
  456. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
  457. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  458. end;
  459. OP_SAR:
  460. begin
  461. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  462. list.concat(taicpu.op_const_reg(A_SAR,S_W,1,GetNextReg(reg)));
  463. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
  464. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  465. end;
  466. OP_SHL:
  467. begin
  468. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  469. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,reg));
  470. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,GetNextReg(reg)));
  471. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  472. end;
  473. else
  474. internalerror(2013030907);
  475. end;
  476. end;
  477. end;
  478. end;
  479. end;
  480. OP_ROL,OP_ROR:
  481. begin
  482. a:=a and 31;
  483. if a=0 then
  484. exit;
  485. if op=OP_ROL then
  486. begin
  487. rol_amount:=a;
  488. ror_amount:=32-a;
  489. end
  490. else
  491. begin
  492. rol_amount:=32-a;
  493. ror_amount:=a;
  494. end;
  495. case rol_amount of
  496. 1,17:
  497. rox32method:=rm_unrolledleftloop;
  498. 2,18:
  499. if current_settings.cputype>=cpu_386 then
  500. rox32method:=rm_fast_386
  501. else if not (cs_opt_size in current_settings.optimizerswitches) then
  502. rox32method:=rm_unrolledleftloop
  503. else
  504. rox32method:=rm_loopleft;
  505. 3..8,19..24:
  506. if current_settings.cputype>=cpu_386 then
  507. rox32method:=rm_fast_386
  508. else
  509. rox32method:=rm_loopleft;
  510. 15,31:
  511. rox32method:=rm_unrolledrightloop;
  512. 14,30:
  513. if current_settings.cputype>=cpu_386 then
  514. rox32method:=rm_fast_386
  515. else if not (cs_opt_size in current_settings.optimizerswitches) then
  516. rox32method:=rm_unrolledrightloop
  517. else
  518. { the left loop has a smaller size }
  519. rox32method:=rm_loopleft;
  520. 9..13,25..29:
  521. if current_settings.cputype>=cpu_386 then
  522. rox32method:=rm_fast_386
  523. else if not (cs_opt_size in current_settings.optimizerswitches) then
  524. rox32method:=rm_loopright
  525. else
  526. { the left loop has a smaller size }
  527. rox32method:=rm_loopleft;
  528. 16:
  529. rox32method:=rm_unrolledleftloop;
  530. else
  531. internalerror(2017040601);
  532. end;
  533. case rox32method of
  534. rm_unrolledleftloop:
  535. begin
  536. if rol_amount>=16 then
  537. begin
  538. list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
  539. dec(rol_amount,16);
  540. end;
  541. for i:=1 to rol_amount do
  542. begin
  543. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  544. list.Concat(taicpu.op_const_reg(A_SHL,S_W,1,GetNextReg(reg)));
  545. list.Concat(taicpu.op_const_reg(A_RCL,S_W,1,reg));
  546. list.Concat(taicpu.op_const_reg(A_ADC,S_W,0,GetNextReg(reg)));
  547. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  548. end;
  549. end;
  550. rm_unrolledrightloop:
  551. begin
  552. if ror_amount>=16 then
  553. begin
  554. list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
  555. dec(ror_amount,16);
  556. end;
  557. tmpreg:=getintregister(list,OS_16);
  558. for i:=1 to ror_amount do
  559. begin
  560. a_load_reg_reg(list,OS_16,OS_16,reg,tmpreg);
  561. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  562. list.Concat(taicpu.op_const_reg(A_SHR,S_W,1,tmpreg));
  563. list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,GetNextReg(reg)));
  564. list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
  565. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  566. end;
  567. end;
  568. rm_loopleft:
  569. begin
  570. if (rol_amount>=16) and not (cs_opt_size in current_settings.optimizerswitches) then
  571. begin
  572. list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
  573. dec(rol_amount,16);
  574. if rol_amount=0 then
  575. exit;
  576. end;
  577. getcpuregister(list,NR_CX);
  578. a_load_const_reg(list,OS_16,rol_amount,NR_CX);
  579. current_asmdata.getjumplabel(hl_loop_start);
  580. a_label(list,hl_loop_start);
  581. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  582. list.Concat(taicpu.op_const_reg(A_SHL,S_W,1,GetNextReg(reg)));
  583. list.Concat(taicpu.op_const_reg(A_RCL,S_W,1,reg));
  584. list.Concat(taicpu.op_const_reg(A_ADC,S_W,0,GetNextReg(reg)));
  585. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  586. ai:=Taicpu.Op_Sym(A_LOOP,S_W,hl_loop_start);
  587. ai.is_jmp:=true;
  588. list.concat(ai);
  589. ungetcpuregister(list,NR_CX);
  590. end;
  591. rm_loopright:
  592. begin
  593. if (ror_amount>=16) and not (cs_opt_size in current_settings.optimizerswitches) then
  594. begin
  595. list.Concat(taicpu.op_reg_reg(A_XCHG,S_W,reg,GetNextReg(reg)));
  596. dec(ror_amount,16);
  597. if ror_amount=0 then
  598. exit;
  599. end;
  600. getcpuregister(list,NR_CX);
  601. a_load_const_reg(list,OS_16,ror_amount,NR_CX);
  602. current_asmdata.getjumplabel(hl_loop_start);
  603. a_label(list,hl_loop_start);
  604. tmpreg:=getintregister(list,OS_16);
  605. a_load_reg_reg(list,OS_16,OS_16,reg,tmpreg);
  606. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  607. list.Concat(taicpu.op_const_reg(A_SHR,S_W,1,tmpreg));
  608. list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,GetNextReg(reg)));
  609. list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,reg));
  610. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  611. ai:=Taicpu.Op_Sym(A_LOOP,S_W,hl_loop_start);
  612. ai.is_jmp:=true;
  613. list.concat(ai);
  614. ungetcpuregister(list,NR_CX);
  615. end;
  616. rm_fast_386:
  617. begin
  618. tmpreg:=getintregister(list,OS_16);
  619. a_load_reg_reg(list,OS_16,OS_16,GetNextReg(reg),tmpreg);
  620. if op=OP_ROL then
  621. begin
  622. list.Concat(taicpu.op_const_reg_reg(A_SHLD,S_W,rol_amount,reg,GetNextReg(reg)));
  623. list.Concat(taicpu.op_const_reg_reg(A_SHLD,S_W,rol_amount,tmpreg,reg));
  624. end
  625. else
  626. begin
  627. list.Concat(taicpu.op_const_reg_reg(A_SHRD,S_W,ror_amount,reg,GetNextReg(reg)));
  628. list.Concat(taicpu.op_const_reg_reg(A_SHRD,S_W,ror_amount,tmpreg,reg));
  629. end;
  630. end;
  631. else
  632. internalerror(2017040602);
  633. end;
  634. end;
  635. else
  636. begin
  637. tmpreg:=getintregister(list,size);
  638. a_load_const_reg(list,size,a,tmpreg);
  639. a_op_reg_reg(list,op,size,tmpreg,reg);
  640. end;
  641. end;
  642. end
  643. else
  644. begin
  645. { size <= 16-bit }
  646. { 8086 doesn't support 'imul reg,const', so we handle it here }
  647. if (current_settings.cputype<cpu_186) and (op in [OP_MUL,OP_IMUL]) then
  648. begin
  649. if op = OP_IMUL then
  650. begin
  651. if size in [OS_16,OS_S16] then
  652. ax_subreg := NR_AX
  653. else
  654. if size in [OS_8,OS_S8] then
  655. ax_subreg := NR_AL
  656. else
  657. internalerror(2013050102);
  658. getcpuregister(list,NR_AX);
  659. a_load_const_reg(list,size,a,ax_subreg);
  660. if size in [OS_16,OS_S16] then
  661. getcpuregister(list,NR_DX);
  662. { prefer MUL over IMUL when overflow checking is off, }
  663. { because it's faster on the 8086 & 8088 }
  664. if not (cs_check_overflow in current_settings.localswitches) then
  665. list.concat(taicpu.op_reg(A_MUL,TCgSize2OpSize[size],reg))
  666. else
  667. list.concat(taicpu.op_reg(A_IMUL,TCgSize2OpSize[size],reg));
  668. if size in [OS_16,OS_S16] then
  669. ungetcpuregister(list,NR_DX);
  670. a_load_reg_reg(list,size,size,ax_subreg,reg);
  671. ungetcpuregister(list,NR_AX);
  672. exit;
  673. end
  674. else
  675. { OP_MUL should be handled specifically in the code }
  676. { generator because of the silly register usage restraints }
  677. internalerror(2001092208);
  678. end
  679. else
  680. inherited a_op_const_reg(list, Op, size, a, reg);
  681. end;
  682. end;
  683. procedure tcg8086.a_op_const_ref(list: TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference);
  684. var
  685. tmpref: treference;
  686. op1,op2: TAsmOp;
  687. tmpreg: TRegister;
  688. begin
  689. optimize_op_const(size, op, a);
  690. tmpref:=ref;
  691. make_simple_ref(list,tmpref);
  692. if size in [OS_64, OS_S64] then
  693. internalerror(2013050801);
  694. if size in [OS_32, OS_S32] then
  695. begin
  696. case Op of
  697. OP_NONE :
  698. begin
  699. { Opcode is optimized away }
  700. end;
  701. OP_MOVE :
  702. begin
  703. { Optimized, replaced with a simple load }
  704. a_load_const_ref(list,size,a,ref);
  705. end;
  706. OP_ADD, OP_SUB:
  707. begin
  708. get_32bit_ops(op, op1, op2);
  709. { Optimization when the low 16-bits of the constant are 0 }
  710. if aint(a and $FFFF) = 0 then
  711. begin
  712. inc(tmpref.offset, 2);
  713. { use a_op_const_ref to allow the use of inc/dec }
  714. a_op_const_ref(list,op,OS_16,aint(a shr 16),tmpref);
  715. end
  716. else
  717. begin
  718. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  719. list.concat(taicpu.op_const_ref(op1,S_W,aint(a and $FFFF),tmpref));
  720. inc(tmpref.offset, 2);
  721. list.concat(taicpu.op_const_ref(op2,S_W,aint(a shr 16),tmpref));
  722. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  723. end;
  724. end;
  725. OP_AND, OP_OR, OP_XOR:
  726. begin
  727. { low word operation }
  728. if aint(a and $FFFF) = aint(0) then
  729. begin
  730. case op of
  731. OP_AND:
  732. a_load_const_ref(list,OS_16,aint(0),ref);
  733. OP_OR,OP_XOR:
  734. {do nothing};
  735. else
  736. InternalError(2013100708);
  737. end;
  738. end
  739. else if aint(a and $FFFF) = aint($FFFF) then
  740. begin
  741. case op of
  742. OP_AND:
  743. {do nothing};
  744. OP_OR:
  745. a_load_const_ref(list,OS_16,aint($FFFF),tmpref);
  746. OP_XOR:
  747. list.concat(taicpu.op_ref(A_NOT,S_W,tmpref));
  748. else
  749. InternalError(2013100709);
  750. end;
  751. end
  752. else
  753. a_op_const_ref(list,op,OS_16,aint(a and $FFFF),tmpref);
  754. { high word operation }
  755. inc(tmpref.offset, 2);
  756. if aint(a shr 16) = aint(0) then
  757. begin
  758. case op of
  759. OP_AND:
  760. a_load_const_ref(list,OS_16,aint(0),tmpref);
  761. OP_OR,OP_XOR:
  762. {do nothing};
  763. else
  764. InternalError(2013100710);
  765. end;
  766. end
  767. else if aint(a shr 16) = aint($FFFF) then
  768. begin
  769. case op of
  770. OP_AND:
  771. {do nothing};
  772. OP_OR:
  773. a_load_const_ref(list,OS_16,aint($FFFF),tmpref);
  774. OP_XOR:
  775. list.concat(taicpu.op_ref(A_NOT,S_W,tmpref));
  776. else
  777. InternalError(2013100711);
  778. end;
  779. end
  780. else
  781. a_op_const_ref(list,op,OS_16,aint(a shr 16),tmpref);
  782. end;
  783. OP_SHR,OP_SHL,OP_SAR:
  784. begin
  785. a:=a and 31;
  786. if a=1 then
  787. begin
  788. case op of
  789. OP_SHR:
  790. begin
  791. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  792. inc(tmpref.offset, 2);
  793. list.concat(taicpu.op_const_ref(A_SHR,S_W,1,tmpref));
  794. dec(tmpref.offset, 2);
  795. list.concat(taicpu.op_const_ref(A_RCR,S_W,1,tmpref));
  796. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  797. end;
  798. OP_SAR:
  799. begin
  800. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  801. inc(tmpref.offset, 2);
  802. list.concat(taicpu.op_const_ref(A_SAR,S_W,1,tmpref));
  803. dec(tmpref.offset, 2);
  804. list.concat(taicpu.op_const_ref(A_RCR,S_W,1,tmpref));
  805. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  806. end;
  807. OP_SHL:
  808. begin
  809. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  810. list.concat(taicpu.op_const_ref(A_SHL,S_W,1,tmpref));
  811. inc(tmpref.offset, 2);
  812. list.concat(taicpu.op_const_ref(A_RCL,S_W,1,tmpref));
  813. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  814. end;
  815. else
  816. internalerror(2015042501);
  817. end;
  818. end
  819. else
  820. begin
  821. tmpreg:=getintregister(list,size);
  822. a_load_ref_reg(list,size,size,ref,tmpreg);
  823. a_op_const_reg(list,Op,size,a,tmpreg);
  824. a_load_reg_ref(list,size,size,tmpreg,ref);
  825. end;
  826. end;
  827. OP_ROL,OP_ROR:
  828. begin
  829. tmpreg:=getintregister(list,size);
  830. a_load_ref_reg(list,size,size,ref,tmpreg);
  831. a_op_const_reg(list,Op,size,a,tmpreg);
  832. a_load_reg_ref(list,size,size,tmpreg,ref);
  833. end;
  834. else
  835. internalerror(2013050802);
  836. end;
  837. end
  838. else
  839. inherited a_op_const_ref(list,Op,size,a,tmpref);
  840. end;
  841. procedure tcg8086.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize;
  842. src, dst: TRegister);
  843. var
  844. op1, op2: TAsmOp;
  845. hl_skip, hl_loop_start: TAsmLabel;
  846. ai: taicpu;
  847. tmpreg: TRegister;
  848. begin
  849. check_register_size(size,src);
  850. check_register_size(size,dst);
  851. if size in [OS_64, OS_S64] then
  852. internalerror(2013030902);
  853. if size in [OS_32, OS_S32] then
  854. begin
  855. case op of
  856. OP_NEG:
  857. begin
  858. if src<>dst then
  859. a_load_reg_reg(list,size,size,src,dst);
  860. list.concat(taicpu.op_reg(A_NOT, S_W, GetNextReg(dst)));
  861. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  862. list.concat(taicpu.op_reg(A_NEG, S_W, dst));
  863. list.concat(taicpu.op_const_reg(A_SBB, S_W,-1, GetNextReg(dst)));
  864. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  865. end;
  866. OP_NOT:
  867. begin
  868. if src<>dst then
  869. a_load_reg_reg(list,size,size,src,dst);
  870. list.concat(taicpu.op_reg(A_NOT, S_W, dst));
  871. list.concat(taicpu.op_reg(A_NOT, S_W, GetNextReg(dst)));
  872. end;
  873. OP_ADD,OP_SUB,OP_XOR,OP_OR,OP_AND:
  874. begin
  875. get_32bit_ops(op, op1, op2);
  876. if op in [OP_ADD,OP_SUB] then
  877. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  878. list.concat(taicpu.op_reg_reg(op1, S_W, src, dst));
  879. list.concat(taicpu.op_reg_reg(op2, S_W, GetNextReg(src), GetNextReg(dst)));
  880. if op in [OP_ADD,OP_SUB] then
  881. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  882. end;
  883. OP_SHR,OP_SHL,OP_SAR:
  884. begin
  885. getcpuregister(list,NR_CX);
  886. a_load_reg_reg(list,size,OS_16,src,NR_CX);
  887. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  888. list.concat(taicpu.op_const_reg(A_AND,S_W,$1f,NR_CX));
  889. current_asmdata.getjumplabel(hl_skip);
  890. ai:=Taicpu.Op_Sym(A_Jcc,S_NO,hl_skip);
  891. ai.SetCondition(C_Z);
  892. ai.is_jmp:=true;
  893. list.concat(ai);
  894. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  895. current_asmdata.getjumplabel(hl_loop_start);
  896. a_label(list,hl_loop_start);
  897. case op of
  898. OP_SHR:
  899. begin
  900. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  901. list.concat(taicpu.op_const_reg(A_SHR,S_W,1,GetNextReg(dst)));
  902. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,dst));
  903. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  904. end;
  905. OP_SAR:
  906. begin
  907. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  908. list.concat(taicpu.op_const_reg(A_SAR,S_W,1,GetNextReg(dst)));
  909. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,dst));
  910. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  911. end;
  912. OP_SHL:
  913. begin
  914. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  915. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,dst));
  916. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,GetNextReg(dst)));
  917. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  918. end;
  919. else
  920. internalerror(2013030908);
  921. end;
  922. ai:=Taicpu.Op_Sym(A_LOOP,S_W,hl_loop_start);
  923. ai.is_jmp:=true;
  924. list.concat(ai);
  925. a_label(list,hl_skip);
  926. ungetcpuregister(list,NR_CX);
  927. end;
  928. OP_ROL,OP_ROR:
  929. begin
  930. getcpuregister(list,NR_CX);
  931. a_load_reg_reg(list,size,OS_16,src,NR_CX);
  932. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  933. list.concat(taicpu.op_const_reg(A_AND,S_W,$1f,NR_CX));
  934. current_asmdata.getjumplabel(hl_skip);
  935. ai:=Taicpu.Op_Sym(A_Jcc,S_NO,hl_skip);
  936. ai.SetCondition(C_Z);
  937. ai.is_jmp:=true;
  938. list.concat(ai);
  939. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  940. current_asmdata.getjumplabel(hl_loop_start);
  941. a_label(list,hl_loop_start);
  942. case op of
  943. OP_ROL:
  944. begin
  945. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  946. list.Concat(taicpu.op_const_reg(A_SHL,S_W,1,GetNextReg(dst)));
  947. list.Concat(taicpu.op_const_reg(A_RCL,S_W,1,dst));
  948. list.Concat(taicpu.op_const_reg(A_ADC,S_W,0,GetNextReg(dst)));
  949. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  950. end;
  951. OP_ROR:
  952. begin
  953. tmpreg:=getintregister(list,OS_16);
  954. a_load_reg_reg(list,OS_16,OS_16,dst,tmpreg);
  955. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  956. list.Concat(taicpu.op_const_reg(A_SHR,S_W,1,tmpreg));
  957. list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,GetNextReg(dst)));
  958. list.Concat(taicpu.op_const_reg(A_RCR,S_W,1,dst));
  959. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  960. end;
  961. else
  962. internalerror(2017042502);
  963. end;
  964. ai:=Taicpu.Op_Sym(A_LOOP,S_W,hl_loop_start);
  965. ai.is_jmp:=true;
  966. list.concat(ai);
  967. a_label(list,hl_skip);
  968. ungetcpuregister(list,NR_CX);
  969. end;
  970. else
  971. internalerror(2013030905);
  972. end;
  973. end
  974. else
  975. inherited a_op_reg_reg(list, Op, size, src, dst);
  976. end;
  977. procedure tcg8086.a_op_ref_reg(list: TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
  978. var
  979. tmpref : treference;
  980. op1, op2: TAsmOp;
  981. begin
  982. tmpref:=ref;
  983. make_simple_ref(list,tmpref);
  984. check_register_size(size,reg);
  985. if size in [OS_64, OS_S64] then
  986. internalerror(2013030906);
  987. if size in [OS_32, OS_S32] then
  988. begin
  989. case op of
  990. OP_ADD,OP_SUB,OP_XOR,OP_OR,OP_AND:
  991. begin
  992. get_32bit_ops(op, op1, op2);
  993. if op in [OP_ADD,OP_SUB] then
  994. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  995. list.concat(taicpu.op_ref_reg(op1, S_W, tmpref, reg));
  996. inc(tmpref.offset, 2);
  997. list.concat(taicpu.op_ref_reg(op2, S_W, tmpref, GetNextReg(reg)));
  998. if op in [OP_ADD,OP_SUB] then
  999. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1000. end;
  1001. else
  1002. internalerror(2013050701);
  1003. end;
  1004. end
  1005. else
  1006. inherited a_op_ref_reg(list,Op,size,tmpref,reg);
  1007. end;
  1008. procedure tcg8086.a_op_reg_ref(list: TAsmList; Op: TOpCG; size: TCGSize; reg: TRegister; const ref: TReference);
  1009. var
  1010. tmpref: treference;
  1011. op1,op2: TAsmOp;
  1012. hl_skip, hl_loop_start: TAsmLabel;
  1013. ai: taicpu;
  1014. tmpreg: TRegister;
  1015. begin
  1016. tmpref:=ref;
  1017. make_simple_ref(list,tmpref);
  1018. if not (op in [OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR]) then
  1019. check_register_size(size,reg);
  1020. if size in [OS_64, OS_S64] then
  1021. internalerror(2013050803);
  1022. if size in [OS_32, OS_S32] then
  1023. begin
  1024. case op of
  1025. OP_NEG,OP_NOT:
  1026. inherited;
  1027. OP_IMUL:
  1028. begin
  1029. { this one needs a load/imul/store, which is the default }
  1030. inherited a_op_ref_reg(list,op,size,tmpref,reg);
  1031. end;
  1032. OP_MUL,OP_DIV,OP_IDIV:
  1033. { special stuff, needs separate handling inside code }
  1034. { generator }
  1035. internalerror(2001092304);
  1036. OP_ADD,OP_SUB,OP_XOR,OP_OR,OP_AND:
  1037. begin
  1038. get_32bit_ops(op, op1, op2);
  1039. if op in [OP_ADD,OP_SUB] then
  1040. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1041. list.concat(taicpu.op_reg_ref(op1, S_W, reg, tmpref));
  1042. inc(tmpref.offset, 2);
  1043. list.concat(taicpu.op_reg_ref(op2, S_W, GetNextReg(reg), tmpref));
  1044. if op in [OP_ADD,OP_SUB] then
  1045. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1046. end;
  1047. OP_SHR,OP_SHL,OP_SAR:
  1048. begin
  1049. getcpuregister(list,NR_CX);
  1050. a_load_reg_reg(list,size,OS_16,reg,NR_CX);
  1051. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1052. list.concat(taicpu.op_const_reg(A_AND,S_W,$1f,NR_CX));
  1053. current_asmdata.getjumplabel(hl_skip);
  1054. ai:=Taicpu.Op_Sym(A_Jcc,S_NO,hl_skip);
  1055. ai.SetCondition(C_Z);
  1056. ai.is_jmp:=true;
  1057. list.concat(ai);
  1058. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1059. current_asmdata.getjumplabel(hl_loop_start);
  1060. a_label(list,hl_loop_start);
  1061. case op of
  1062. OP_SHR:
  1063. begin
  1064. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1065. inc(tmpref.offset, 2);
  1066. list.concat(taicpu.op_const_ref(A_SHR,S_W,1,tmpref));
  1067. dec(tmpref.offset, 2);
  1068. list.concat(taicpu.op_const_ref(A_RCR,S_W,1,tmpref));
  1069. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1070. end;
  1071. OP_SAR:
  1072. begin
  1073. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1074. inc(tmpref.offset, 2);
  1075. list.concat(taicpu.op_const_ref(A_SAR,S_W,1,tmpref));
  1076. dec(tmpref.offset, 2);
  1077. list.concat(taicpu.op_const_ref(A_RCR,S_W,1,tmpref));
  1078. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1079. end;
  1080. OP_SHL:
  1081. begin
  1082. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1083. list.concat(taicpu.op_const_ref(A_SHL,S_W,1,tmpref));
  1084. inc(tmpref.offset, 2);
  1085. list.concat(taicpu.op_const_ref(A_RCL,S_W,1,tmpref));
  1086. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1087. end;
  1088. else
  1089. internalerror(2013030909);
  1090. end;
  1091. ai:=Taicpu.Op_Sym(A_LOOP,S_W,hl_loop_start);
  1092. ai.is_jmp:=true;
  1093. list.concat(ai);
  1094. a_label(list,hl_skip);
  1095. ungetcpuregister(list,NR_CX);
  1096. end;
  1097. OP_ROL,OP_ROR:
  1098. begin
  1099. tmpreg:=getintregister(list,size);
  1100. a_load_ref_reg(list,size,size,ref,tmpreg);
  1101. a_op_reg_reg(list,Op,size,reg,tmpreg);
  1102. a_load_reg_ref(list,size,size,tmpreg,ref);
  1103. end;
  1104. else
  1105. internalerror(2013050804);
  1106. end;
  1107. end
  1108. else
  1109. inherited a_op_reg_ref(list,Op,size,reg,tmpref);
  1110. end;
  1111. procedure tcg8086.a_op_ref(list: TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference);
  1112. var
  1113. tmpref: treference;
  1114. begin
  1115. tmpref:=ref;
  1116. make_simple_ref(list,tmpref);
  1117. if size in [OS_64, OS_S64] then
  1118. internalerror(2013050805);
  1119. if size in [OS_32, OS_S32] then
  1120. begin
  1121. case op of
  1122. OP_NEG:
  1123. begin
  1124. inc(tmpref.offset, 2);
  1125. list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
  1126. dec(tmpref.offset, 2);
  1127. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1128. list.concat(taicpu.op_ref(A_NEG, S_W, tmpref));
  1129. inc(tmpref.offset, 2);
  1130. list.concat(taicpu.op_const_ref(A_SBB, S_W,-1, tmpref));
  1131. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1132. end;
  1133. OP_NOT:
  1134. begin
  1135. list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
  1136. inc(tmpref.offset, 2);
  1137. list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
  1138. end;
  1139. else
  1140. internalerror(2020050709);
  1141. end;
  1142. end
  1143. else
  1144. inherited;
  1145. end;
  1146. procedure tcg8086.push_const(list: TAsmList; size: tcgsize; a: tcgint);
  1147. var
  1148. tmpreg: TRegister;
  1149. begin
  1150. if not (size in [OS_16,OS_S16]) then
  1151. internalerror(2013043001);
  1152. if current_settings.cputype < cpu_186 then
  1153. begin
  1154. tmpreg:=getintregister(list,size);
  1155. a_load_const_reg(list,size,a,tmpreg);
  1156. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1157. end
  1158. else
  1159. list.concat(taicpu.op_const(A_PUSH,TCGSize2OpSize[size],a));
  1160. end;
  1161. procedure tcg8086.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
  1162. procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
  1163. var
  1164. ref : treference;
  1165. begin
  1166. paramanager.allocparaloc(list,paraloc);
  1167. case paraloc^.loc of
  1168. LOC_REGISTER,LOC_CREGISTER:
  1169. a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
  1170. LOC_REFERENCE,LOC_CREFERENCE:
  1171. begin
  1172. reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
  1173. a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
  1174. end;
  1175. else
  1176. internalerror(2002071006);
  1177. end;
  1178. end;
  1179. var
  1180. pushsize,pushsize2 : tcgsize;
  1181. begin
  1182. check_register_size(size,r);
  1183. if use_push(cgpara) then
  1184. begin
  1185. if tcgsize2size[cgpara.Size] > 2 then
  1186. begin
  1187. if tcgsize2size[cgpara.Size] <> 4 then
  1188. internalerror(2013031101);
  1189. if cgpara.location^.Next = nil then
  1190. begin
  1191. if tcgsize2size[cgpara.location^.size] <> 4 then
  1192. internalerror(2013031103);
  1193. end
  1194. else
  1195. begin
  1196. if tcgsize2size[cgpara.location^.size] <> 2 then
  1197. internalerror(2013031104);
  1198. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  1199. internalerror(2013031105);
  1200. if cgpara.location^.Next^.Next <> nil then
  1201. internalerror(2013031106);
  1202. end;
  1203. if tcgsize2size[cgpara.size]>cgpara.alignment then
  1204. pushsize:=cgpara.size
  1205. else
  1206. pushsize:=int_cgsize(cgpara.alignment);
  1207. pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2);
  1208. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2)));
  1209. list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16)));
  1210. end
  1211. else
  1212. begin
  1213. cgpara.check_simple_location;
  1214. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  1215. pushsize:=cgpara.location^.size
  1216. else
  1217. pushsize:=int_cgsize(cgpara.alignment);
  1218. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
  1219. end;
  1220. end
  1221. else
  1222. begin
  1223. if tcgsize2size[cgpara.Size]=4 then
  1224. begin
  1225. if (cgpara.location^.Next=nil) or
  1226. (tcgsize2size[cgpara.location^.size]<>2) or
  1227. (tcgsize2size[cgpara.location^.Next^.size]<>2) or
  1228. (cgpara.location^.Next^.Next<>nil) or
  1229. (cgpara.location^.shiftval<>0) then
  1230. internalerror(2013031102);
  1231. load_para_loc(r,cgpara.Location);
  1232. load_para_loc(GetNextReg(r),cgpara.Location^.Next);
  1233. end
  1234. else
  1235. inherited a_load_reg_cgpara(list,size,r,cgpara);
  1236. end;
  1237. end;
  1238. procedure tcg8086.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);
  1239. var
  1240. pushsize : tcgsize;
  1241. begin
  1242. if use_push(cgpara) then
  1243. begin
  1244. if tcgsize2size[cgpara.Size] > 2 then
  1245. begin
  1246. if tcgsize2size[cgpara.Size] <> 4 then
  1247. internalerror(2013031107);
  1248. if cgpara.location^.Next = nil then
  1249. begin
  1250. if tcgsize2size[cgpara.location^.size] <> 4 then
  1251. internalerror(2013031108);
  1252. end
  1253. else
  1254. begin
  1255. if tcgsize2size[cgpara.location^.size] <> 2 then
  1256. internalerror(2013031109);
  1257. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  1258. internalerror(2013031110);
  1259. if cgpara.location^.Next^.Next <> nil then
  1260. internalerror(2013031111);
  1261. end;
  1262. if (cgpara.alignment <> 4) and (cgpara.alignment <> 2) then
  1263. internalerror(2013031112);
  1264. push_const(list,OS_16,a shr 16);
  1265. push_const(list,OS_16,a and $FFFF);
  1266. end
  1267. else
  1268. begin
  1269. cgpara.check_simple_location;
  1270. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  1271. pushsize:=cgpara.location^.size
  1272. else
  1273. pushsize:=int_cgsize(cgpara.alignment);
  1274. push_const(list,pushsize,a);
  1275. end;
  1276. end
  1277. else if (tcgsize2size[cgpara.Size]>2) and
  1278. (cgpara.location^.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  1279. (cgpara.location^.Next<>nil) then
  1280. begin
  1281. if (tcgsize2size[cgpara.Size]<>4) or
  1282. (tcgsize2size[cgpara.location^.Size]<>2) or
  1283. not (cgpara.location^.Next^.Loc in [LOC_REGISTER,LOC_CREGISTER]) or
  1284. (tcgsize2size[cgpara.location^.Next^.Size]<>2) or
  1285. (cgpara.location^.Next^.Next<>nil) then
  1286. internalerror(2018041801);
  1287. a_load_const_reg(list,cgpara.location^.size,a and $FFFF,cgpara.location^.register);
  1288. a_load_const_reg(list,cgpara.location^.Next^.size,a shr 16,cgpara.location^.Next^.register);
  1289. end
  1290. else
  1291. inherited a_load_const_cgpara(list,size,a,cgpara);
  1292. end;
  1293. procedure tcg8086.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);
  1294. procedure pushdata(paraloc:pcgparalocation;ofs:tcgint);
  1295. var
  1296. pushsize : tcgsize;
  1297. opsize : topsize;
  1298. tmpreg : tregister;
  1299. href,tmpref: treference;
  1300. begin
  1301. if not assigned(paraloc) then
  1302. exit;
  1303. if (paraloc^.loc<>LOC_REFERENCE) or
  1304. (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
  1305. (tcgsize2size[paraloc^.size]>4) then
  1306. internalerror(200501162);
  1307. { Pushes are needed in reverse order, add the size of the
  1308. current location to the offset where to load from. This
  1309. prevents wrong calculations for the last location when
  1310. the size is not a power of 2 }
  1311. if assigned(paraloc^.next) then
  1312. pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
  1313. { Push the data starting at ofs }
  1314. href:=r;
  1315. inc(href.offset,ofs);
  1316. if tcgsize2size[paraloc^.size]>cgpara.alignment then
  1317. pushsize:=paraloc^.size
  1318. else
  1319. pushsize:=int_cgsize(cgpara.alignment);
  1320. opsize:=TCgsize2opsize[pushsize];
  1321. { for go32v2 we obtain OS_F32,
  1322. but pushs is not valid, we need pushl }
  1323. if opsize=S_FS then
  1324. opsize:=S_W;
  1325. if tcgsize2size[paraloc^.size]<cgpara.alignment then
  1326. begin
  1327. tmpreg:=getintregister(list,pushsize);
  1328. a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  1329. list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
  1330. end
  1331. else
  1332. begin
  1333. make_simple_ref(list,href);
  1334. if tcgsize2size[pushsize] > 2 then
  1335. begin
  1336. tmpref := href;
  1337. Inc(tmpref.offset, 2);
  1338. list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[int_cgsize(tcgsize2size[pushsize]-2)],tmpref));
  1339. end;
  1340. list.concat(taicpu.op_ref(A_PUSH,opsize,href));
  1341. end;
  1342. end;
  1343. var
  1344. len : tcgint;
  1345. href : treference;
  1346. begin
  1347. { cgpara.size=OS_NO requires a copy on the stack }
  1348. if use_push(cgpara) then
  1349. begin
  1350. { Record copy? }
  1351. if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
  1352. begin
  1353. cgpara.check_simple_location;
  1354. len:=align(cgpara.intsize,cgpara.alignment);
  1355. g_stackpointer_alloc(list,len);
  1356. reference_reset_base(href,NR_STACK_POINTER_REG,0,ctempposinvalid,4,[]);
  1357. g_concatcopy(list,r,href,len);
  1358. end
  1359. else
  1360. begin
  1361. if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
  1362. internalerror(200501161);
  1363. { We need to push the data in reverse order,
  1364. therefor we use a recursive algorithm }
  1365. pushdata(cgpara.location,0);
  1366. end
  1367. end
  1368. else
  1369. inherited a_load_ref_cgpara(list,size,r,cgpara);
  1370. end;
  1371. procedure tcg8086.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);
  1372. var
  1373. tmpreg : tregister;
  1374. tmpref : treference;
  1375. begin
  1376. with r do
  1377. begin
  1378. if use_push(cgpara) then
  1379. begin
  1380. if tcgsize2size[cgpara.Size] > 2 then
  1381. begin
  1382. if tcgsize2size[cgpara.Size] <> 4 then
  1383. internalerror(2014032401);
  1384. if cgpara.location^.Next = nil then
  1385. begin
  1386. if tcgsize2size[cgpara.location^.size] <> 4 then
  1387. internalerror(2014032404);
  1388. end
  1389. else
  1390. begin
  1391. if tcgsize2size[cgpara.location^.size] <> 2 then
  1392. internalerror(2014032405);
  1393. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  1394. internalerror(2014032406);
  1395. if cgpara.location^.Next^.Next <> nil then
  1396. internalerror(2014032407);
  1397. end;
  1398. if cgpara.alignment > 4 then
  1399. internalerror(2014032408);
  1400. if segment<>NR_NO then
  1401. begin
  1402. list.concat(Taicpu.op_reg(A_PUSH,S_W,segment));
  1403. tmpref:=r;
  1404. tmpref.segment:=NR_NO;
  1405. tmpreg:=getaddressregister(list);
  1406. a_loadaddr_ref_reg(list,tmpref,tmpreg);
  1407. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1408. end
  1409. else
  1410. begin
  1411. if (base=NR_NO) and (index=NR_NO) then
  1412. begin
  1413. if assigned(symbol) then
  1414. begin
  1415. tmpref:=r;
  1416. tmpref.refaddr:=addr_seg;
  1417. tmpref.offset:=0;
  1418. if current_settings.cputype < cpu_186 then
  1419. begin
  1420. tmpreg:=getaddressregister(list);
  1421. a_load_ref_reg(list,OS_16,OS_16,tmpref,tmpreg);
  1422. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1423. end
  1424. else
  1425. list.concat(Taicpu.Op_ref(A_PUSH,S_W,tmpref));
  1426. if current_settings.cputype < cpu_186 then
  1427. begin
  1428. tmpreg:=getaddressregister(list);
  1429. a_loadaddr_ref_reg(list,r,tmpreg);
  1430. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1431. end
  1432. else
  1433. list.concat(Taicpu.Op_sym_ofs(A_PUSH,S_W,symbol,offset));
  1434. end
  1435. else
  1436. internalerror(2014032402);
  1437. end
  1438. else if assigned(symbol) then
  1439. begin
  1440. reference_reset_symbol(tmpref,r.symbol,0,r.alignment,r.volatility);
  1441. tmpref.refaddr:=addr_seg;
  1442. if current_settings.cputype < cpu_186 then
  1443. begin
  1444. tmpreg:=getaddressregister(list);
  1445. a_load_ref_reg(list,OS_16,OS_16,tmpref,tmpreg);
  1446. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1447. end
  1448. else
  1449. list.concat(Taicpu.Op_ref(A_PUSH,S_W,tmpref));
  1450. tmpreg:=getaddressregister(list);
  1451. a_loadaddr_ref_reg(list,r,tmpreg);
  1452. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1453. end
  1454. else if base=NR_BP then
  1455. begin
  1456. list.concat(Taicpu.op_reg(A_PUSH,S_W,NR_SS));
  1457. tmpreg:=getaddressregister(list);
  1458. a_loadaddr_ref_reg(list,r,tmpreg);
  1459. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1460. end
  1461. else
  1462. internalerror(2014032403);
  1463. end;
  1464. end
  1465. else
  1466. begin
  1467. cgpara.check_simple_location;
  1468. tmpref:=r;
  1469. tmpref.segment:=NR_NO;
  1470. with tmpref do
  1471. begin
  1472. if (base=NR_NO) and (index=NR_NO) then
  1473. begin
  1474. if assigned(symbol) then
  1475. begin
  1476. if current_settings.cputype < cpu_186 then
  1477. begin
  1478. tmpreg:=getaddressregister(list);
  1479. a_loadaddr_ref_reg(list,tmpref,tmpreg);
  1480. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1481. end
  1482. else
  1483. list.concat(Taicpu.Op_sym_ofs(A_PUSH,S_W,symbol,offset));
  1484. end
  1485. else
  1486. push_const(list,OS_16,offset);
  1487. end
  1488. else if (base=NR_NO) and (index<>NR_NO) and
  1489. (offset=0) and (scalefactor=0) and (symbol=nil) then
  1490. list.concat(Taicpu.Op_reg(A_PUSH,S_W,index))
  1491. else if (base<>NR_NO) and (index=NR_NO) and
  1492. (offset=0) and (symbol=nil) then
  1493. list.concat(Taicpu.Op_reg(A_PUSH,S_W,base))
  1494. else
  1495. begin
  1496. tmpreg:=getaddressregister(list);
  1497. a_loadaddr_ref_reg(list,tmpref,tmpreg);
  1498. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1499. end;
  1500. end;
  1501. end;
  1502. end
  1503. else
  1504. inherited a_loadaddr_ref_cgpara(list,r,cgpara);
  1505. end;
  1506. end;
  1507. procedure tcg8086.a_load_const_reg(list : TAsmList; tosize: tcgsize; a : tcgint;reg : tregister);
  1508. begin
  1509. check_register_size(tosize,reg);
  1510. if tosize in [OS_S32,OS_32] then
  1511. begin
  1512. list.concat(taicpu.op_const_reg(A_MOV,S_W,longint(a and $ffff),reg));
  1513. list.concat(taicpu.op_const_reg(A_MOV,S_W,longint(a shr 16),GetNextReg(reg)));
  1514. end
  1515. else
  1516. list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[tosize],a,reg));
  1517. end;
  1518. procedure tcg8086.a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);
  1519. var
  1520. tmpref : treference;
  1521. begin
  1522. tmpref:=ref;
  1523. make_simple_ref(list,tmpref);
  1524. if tosize in [OS_S32,OS_32] then
  1525. begin
  1526. a_load_const_ref(list,OS_16,longint(a and $ffff),tmpref);
  1527. inc(tmpref.offset,2);
  1528. a_load_const_ref(list,OS_16,longint(a shr 16),tmpref);
  1529. end
  1530. else
  1531. list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[tosize],a,tmpref));
  1532. end;
  1533. procedure tcg8086.a_load_reg_ref(list : TAsmList;fromsize,tosize: tcgsize; reg : tregister;const ref : treference);
  1534. var
  1535. tmpreg : tregister;
  1536. tmpref : treference;
  1537. begin
  1538. tmpref:=ref;
  1539. make_simple_ref(list,tmpref);
  1540. check_register_size(fromsize,reg);
  1541. case tosize of
  1542. OS_8,OS_S8:
  1543. if fromsize in [OS_8,OS_S8] then
  1544. list.concat(taicpu.op_reg_ref(A_MOV, S_B, reg, tmpref))
  1545. else
  1546. internalerror(2013030310);
  1547. OS_16,OS_S16:
  1548. case fromsize of
  1549. OS_8,OS_S8:
  1550. begin
  1551. tmpreg:=getintregister(list,tosize);
  1552. a_load_reg_reg(list,fromsize,tosize,reg,tmpreg);
  1553. a_load_reg_ref(list,tosize,tosize,tmpreg,tmpref);
  1554. end;
  1555. OS_16,OS_S16:
  1556. begin
  1557. list.concat(taicpu.op_reg_ref(A_MOV, S_W, reg, tmpref));
  1558. end;
  1559. else
  1560. internalerror(2013030312);
  1561. end;
  1562. OS_32,OS_S32:
  1563. case fromsize of
  1564. OS_8,OS_S8,OS_S16:
  1565. begin
  1566. tmpreg:=getintregister(list,tosize);
  1567. a_load_reg_reg(list,fromsize,tosize,reg,tmpreg);
  1568. a_load_reg_ref(list,tosize,tosize,tmpreg,tmpref);
  1569. end;
  1570. OS_16:
  1571. begin
  1572. { Preload the ref base to reduce spilling }
  1573. if (tmpref.base<>NR_NO) and
  1574. (tmpref.index<>NR_NO) and
  1575. (getsupreg(tmpref.base)>=first_int_imreg) then
  1576. begin
  1577. tmpreg:=getaddressregister(list);
  1578. a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  1579. tmpref.base:=tmpreg;
  1580. end;
  1581. list.concat(taicpu.op_reg_ref(A_MOV, S_W, reg, tmpref));
  1582. inc(tmpref.offset, 2);
  1583. list.concat(taicpu.op_const_ref(A_MOV, S_W, 0, tmpref));
  1584. end;
  1585. OS_32,OS_S32:
  1586. begin
  1587. { Preload the ref base to a new register to reduce spilling
  1588. Also preload if the first source reg is used as base or index
  1589. to prevent overwriting }
  1590. if ((tmpref.base<>NR_NO) and
  1591. (tmpref.index<>NR_NO) and
  1592. (getsupreg(tmpref.base)>=first_int_imreg)) or
  1593. (tmpref.base=reg) or
  1594. (tmpref.index=reg) then
  1595. begin
  1596. tmpreg:=getaddressregister(list);
  1597. a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  1598. tmpref.base:=tmpreg;
  1599. if tmpref.index=reg then
  1600. begin
  1601. list.concat(taicpu.op_ref_reg(A_LEA, S_W, tmpref, tmpref.base));
  1602. tmpref.index:=NR_NO;
  1603. tmpref.offset:=0;
  1604. tmpref.scalefactor:=0;
  1605. end;
  1606. end;
  1607. list.concat(taicpu.op_reg_ref(A_MOV, S_W, reg, tmpref));
  1608. inc(tmpref.offset, 2);
  1609. list.concat(taicpu.op_reg_ref(A_MOV, S_W, GetNextReg(reg), tmpref));
  1610. end;
  1611. else
  1612. internalerror(2013030313);
  1613. end;
  1614. else
  1615. internalerror(2013030311);
  1616. end;
  1617. end;
  1618. procedure tcg8086.a_load_ref_reg_internal(list : TAsmList;fromsize,tosize: tcgsize;const ref : treference;reg : tregister;isdirect:boolean);
  1619. procedure add_mov(instr: Taicpu);
  1620. begin
  1621. { Notify the register allocator that we have written a move instruction so
  1622. it can try to eliminate it. }
  1623. if (instr.oper[0]^.reg<>current_procinfo.framepointer) and (instr.oper[0]^.reg<>NR_STACK_POINTER_REG) then
  1624. add_move_instruction(instr);
  1625. list.concat(instr);
  1626. end;
  1627. var
  1628. tmpref : treference;
  1629. tmpreg : tregister;
  1630. begin
  1631. tmpref:=ref;
  1632. make_simple_ref(list,tmpref,isdirect);
  1633. check_register_size(tosize,reg);
  1634. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1635. internalerror(2011021302);
  1636. { if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1637. fromsize:=tosize;}
  1638. case tosize of
  1639. OS_8,OS_S8:
  1640. if fromsize in [OS_8,OS_S8] then
  1641. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, reg))
  1642. else
  1643. internalerror(2013030210);
  1644. OS_16,OS_S16:
  1645. case fromsize of
  1646. OS_8:
  1647. begin
  1648. if current_settings.cputype>=cpu_386 then
  1649. list.concat(taicpu.op_ref_reg(A_MOVZX, S_BW, tmpref, reg))
  1650. else
  1651. begin
  1652. reg := makeregsize(list, reg, OS_8);
  1653. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, reg));
  1654. setsubreg(reg, R_SUBH);
  1655. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg));
  1656. makeregsize(list, reg, OS_16);
  1657. end;
  1658. end;
  1659. OS_S8:
  1660. begin
  1661. if current_settings.cputype>=cpu_386 then
  1662. list.concat(taicpu.op_ref_reg(A_MOVSX, S_BW, tmpref, reg))
  1663. else
  1664. begin
  1665. getcpuregister(list, NR_AX);
  1666. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, NR_AL));
  1667. list.concat(taicpu.op_none(A_CBW));
  1668. ungetcpuregister(list, NR_AX);
  1669. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg));
  1670. end;
  1671. end;
  1672. OS_16,OS_S16:
  1673. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, reg));
  1674. else
  1675. internalerror(2013030212);
  1676. end;
  1677. OS_32,OS_S32:
  1678. case fromsize of
  1679. OS_8:
  1680. begin
  1681. list.concat(taicpu.op_const_reg(A_MOV,S_W,0,GetNextReg(reg)));
  1682. if current_settings.cputype>=cpu_386 then
  1683. list.concat(taicpu.op_ref_reg(A_MOVZX, S_BW, tmpref, reg))
  1684. else
  1685. begin
  1686. reg := makeregsize(list, reg, OS_8);
  1687. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, reg));
  1688. setsubreg(reg, R_SUBH);
  1689. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg));
  1690. makeregsize(list, reg, OS_16);
  1691. end;
  1692. end;
  1693. OS_S8:
  1694. begin
  1695. getcpuregister(list, NR_AX);
  1696. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, NR_AL));
  1697. getcpuregister(list, NR_DX);
  1698. list.concat(taicpu.op_none(A_CBW));
  1699. list.concat(taicpu.op_none(A_CWD));
  1700. ungetcpuregister(list, NR_AX);
  1701. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg));
  1702. ungetcpuregister(list, NR_DX);
  1703. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg)));
  1704. end;
  1705. OS_16:
  1706. begin
  1707. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, reg));
  1708. list.concat(taicpu.op_const_reg(A_MOV,S_W,0,GetNextReg(reg)));
  1709. end;
  1710. OS_S16:
  1711. begin
  1712. getcpuregister(list, NR_AX);
  1713. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, NR_AX));
  1714. getcpuregister(list, NR_DX);
  1715. list.concat(taicpu.op_none(A_CWD));
  1716. ungetcpuregister(list, NR_AX);
  1717. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg));
  1718. ungetcpuregister(list, NR_DX);
  1719. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg)));
  1720. end;
  1721. OS_32,OS_S32:
  1722. begin
  1723. { Preload the ref base to a new register to reduce spilling
  1724. Also preload if the first target reg is used as base or index
  1725. to prevent overwriting }
  1726. if ((tmpref.base<>NR_NO) and
  1727. (tmpref.index<>NR_NO) and
  1728. (getsupreg(tmpref.base)>=first_int_imreg)) or
  1729. (tmpref.base=reg) or
  1730. (tmpref.index=reg) then
  1731. begin
  1732. tmpreg:=getaddressregister(list);
  1733. a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
  1734. tmpref.base:=tmpreg;
  1735. if tmpref.index=reg then
  1736. begin
  1737. list.concat(taicpu.op_ref_reg(A_LEA, S_W, tmpref, tmpref.base));
  1738. tmpref.index:=NR_NO;
  1739. tmpref.offset:=0;
  1740. tmpref.scalefactor:=0;
  1741. end;
  1742. end;
  1743. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, reg));
  1744. inc(tmpref.offset, 2);
  1745. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, GetNextReg(reg)));
  1746. end;
  1747. else
  1748. internalerror(2013030213);
  1749. end;
  1750. else
  1751. internalerror(2013030211);
  1752. end;
  1753. end;
  1754. procedure tcg8086.a_load_reg_reg(list : TAsmList;fromsize,tosize: tcgsize;reg1,reg2 : tregister);
  1755. procedure add_mov(instr: Taicpu);
  1756. begin
  1757. { Notify the register allocator that we have written a move instruction so
  1758. it can try to eliminate it. }
  1759. if (instr.oper[0]^.reg<>current_procinfo.framepointer) and (instr.oper[0]^.reg<>NR_STACK_POINTER_REG) then
  1760. add_move_instruction(instr);
  1761. list.concat(instr);
  1762. end;
  1763. begin
  1764. check_register_size(fromsize,reg1);
  1765. check_register_size(tosize,reg2);
  1766. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1767. begin
  1768. if tosize in [OS_32, OS_S32] then
  1769. internalerror(2013031801);
  1770. reg1:=makeregsize(list,reg1,tosize);
  1771. fromsize:=tosize;
  1772. end;
  1773. if (reg1<>reg2) or (fromsize<>tosize) then
  1774. begin
  1775. case tosize of
  1776. OS_8,OS_S8:
  1777. if fromsize in [OS_8,OS_S8] then
  1778. begin
  1779. if reg1<>reg2 then
  1780. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, reg2));
  1781. end
  1782. else
  1783. internalerror(2013030203);
  1784. OS_16,OS_S16:
  1785. case fromsize of
  1786. OS_8:
  1787. begin
  1788. if current_settings.cputype>=cpu_386 then
  1789. add_mov(taicpu.op_reg_reg(A_MOVZX, S_BW, reg1, reg2))
  1790. else
  1791. begin
  1792. reg2 := makeregsize(list, reg2, OS_8);
  1793. if reg1<>reg2 then
  1794. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, reg2));
  1795. setsubreg(reg2,R_SUBH);
  1796. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg2));
  1797. makeregsize(list, reg2, OS_16);
  1798. end;
  1799. end;
  1800. OS_S8:
  1801. begin
  1802. if current_settings.cputype>=cpu_386 then
  1803. add_mov(taicpu.op_reg_reg(A_MOVSX, S_BW, reg1, reg2))
  1804. else
  1805. begin
  1806. getcpuregister(list, NR_AX);
  1807. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, NR_AL));
  1808. list.concat(taicpu.op_none(A_CBW));
  1809. ungetcpuregister(list, NR_AX);
  1810. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg2));
  1811. end;
  1812. end;
  1813. OS_16,OS_S16:
  1814. begin
  1815. if reg1<>reg2 then
  1816. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, reg2));
  1817. end
  1818. else
  1819. internalerror(2013030205);
  1820. end;
  1821. OS_32,OS_S32:
  1822. case fromsize of
  1823. OS_8:
  1824. begin
  1825. list.concat(taicpu.op_const_reg(A_MOV, S_W, 0, GetNextReg(reg2)));
  1826. if current_settings.cputype>=cpu_386 then
  1827. add_mov(taicpu.op_reg_reg(A_MOVZX, S_BW, reg1, reg2))
  1828. else
  1829. begin
  1830. reg2 := makeregsize(list, reg2, OS_8);
  1831. if reg1<>reg2 then
  1832. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, reg2));
  1833. setsubreg(reg2,R_SUBH);
  1834. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg2));
  1835. makeregsize(list, reg2, OS_16);
  1836. end;
  1837. end;
  1838. OS_S8:
  1839. begin
  1840. getcpuregister(list, NR_AX);
  1841. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, NR_AL));
  1842. getcpuregister(list, NR_DX);
  1843. list.concat(taicpu.op_none(A_CBW));
  1844. list.concat(taicpu.op_none(A_CWD));
  1845. ungetcpuregister(list, NR_AX);
  1846. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg2));
  1847. ungetcpuregister(list, NR_DX);
  1848. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg2)));
  1849. end;
  1850. OS_16:
  1851. begin
  1852. if reg1<>reg2 then
  1853. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, reg2));
  1854. list.concat(taicpu.op_const_reg(A_MOV,S_W,0,GetNextReg(reg2)));
  1855. end;
  1856. OS_S16:
  1857. begin
  1858. getcpuregister(list, NR_AX);
  1859. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, NR_AX));
  1860. getcpuregister(list, NR_DX);
  1861. list.concat(taicpu.op_none(A_CWD));
  1862. ungetcpuregister(list, NR_AX);
  1863. if reg1<>reg2 then
  1864. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg2));
  1865. ungetcpuregister(list, NR_DX);
  1866. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg2)));
  1867. end;
  1868. OS_32,OS_S32:
  1869. begin
  1870. if reg1<>reg2 then
  1871. begin
  1872. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, reg2));
  1873. add_mov(taicpu.op_reg_reg(A_MOV, S_W, GetNextReg(reg1), GetNextReg(reg2)));
  1874. end;
  1875. end;
  1876. else
  1877. internalerror(2013030206);
  1878. end;
  1879. else
  1880. internalerror(2013030204);
  1881. end;
  1882. end;
  1883. end;
  1884. procedure tcg8086.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
  1885. var
  1886. hl_skip: TAsmLabel;
  1887. begin
  1888. if size in [OS_32, OS_S32] then
  1889. begin
  1890. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1891. if (longint(a shr 16) = 0) then
  1892. list.concat(taicpu.op_reg_reg(A_TEST,S_W,GetNextReg(reg),GetNextReg(reg)))
  1893. else
  1894. list.concat(taicpu.op_const_reg(A_CMP,S_W,longint(a shr 16),GetNextReg(reg)));
  1895. current_asmdata.getjumplabel(hl_skip);
  1896. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1897. if (longint(a and $ffff) = 0) then
  1898. list.concat(taicpu.op_reg_reg(A_TEST,S_W,reg,reg))
  1899. else
  1900. list.concat(taicpu.op_const_reg(A_CMP,S_W,longint(a and $ffff),reg));
  1901. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1902. a_label(list,hl_skip);
  1903. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1904. end
  1905. else
  1906. inherited a_cmp_const_reg_label(list, size, cmp_op, a, reg, l);
  1907. end;
  1908. procedure tcg8086.a_cmp_const_ref_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; const ref: treference; l: tasmlabel);
  1909. var
  1910. tmpref: treference;
  1911. hl_skip: TAsmLabel;
  1912. begin
  1913. if size in [OS_32, OS_S32] then
  1914. begin
  1915. tmpref:=ref;
  1916. make_simple_ref(list,tmpref);
  1917. inc(tmpref.offset,2);
  1918. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1919. list.concat(taicpu.op_const_ref(A_CMP,S_W,longint(a shr 16),tmpref));
  1920. current_asmdata.getjumplabel(hl_skip);
  1921. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1922. dec(tmpref.offset,2);
  1923. list.concat(taicpu.op_const_ref(A_CMP,S_W,longint(a and $ffff),tmpref));
  1924. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1925. a_label(list,hl_skip);
  1926. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1927. end
  1928. else
  1929. inherited a_cmp_const_ref_label(list, size, cmp_op, a, ref, l);
  1930. end;
  1931. procedure tcg8086.a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  1932. var
  1933. hl_skip: TAsmLabel;
  1934. begin
  1935. if size in [OS_32, OS_S32] then
  1936. begin
  1937. check_register_size(size,reg1);
  1938. check_register_size(size,reg2);
  1939. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1940. list.concat(taicpu.op_reg_reg(A_CMP,S_W,GetNextReg(reg1),GetNextReg(reg2)));
  1941. current_asmdata.getjumplabel(hl_skip);
  1942. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1943. list.concat(taicpu.op_reg_reg(A_CMP,S_W,reg1,reg2));
  1944. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1945. a_label(list,hl_skip);
  1946. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1947. end
  1948. else
  1949. inherited a_cmp_reg_reg_label(list, size, cmp_op, reg1, reg2, l);
  1950. end;
  1951. procedure tcg8086.a_cmp_ref_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel);
  1952. var
  1953. tmpref: treference;
  1954. hl_skip: TAsmLabel;
  1955. begin
  1956. if size in [OS_32, OS_S32] then
  1957. begin
  1958. tmpref:=ref;
  1959. make_simple_ref(list,tmpref);
  1960. check_register_size(size,reg);
  1961. inc(tmpref.offset,2);
  1962. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1963. list.concat(taicpu.op_ref_reg(A_CMP,S_W,tmpref,GetNextReg(reg)));
  1964. current_asmdata.getjumplabel(hl_skip);
  1965. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1966. dec(tmpref.offset,2);
  1967. list.concat(taicpu.op_ref_reg(A_CMP,S_W,tmpref,reg));
  1968. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1969. a_label(list,hl_skip);
  1970. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1971. end
  1972. else
  1973. inherited a_cmp_ref_reg_label(list, size, cmp_op, ref, reg, l);
  1974. end;
  1975. procedure tcg8086.a_cmp_reg_ref_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel);
  1976. var
  1977. tmpref: treference;
  1978. hl_skip: TAsmLabel;
  1979. begin
  1980. if size in [OS_32, OS_S32] then
  1981. begin
  1982. tmpref:=ref;
  1983. make_simple_ref(list,tmpref);
  1984. check_register_size(size,reg);
  1985. inc(tmpref.offset,2);
  1986. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1987. list.concat(taicpu.op_reg_ref(A_CMP,S_W,GetNextReg(reg),tmpref));
  1988. current_asmdata.getjumplabel(hl_skip);
  1989. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1990. dec(tmpref.offset,2);
  1991. list.concat(taicpu.op_reg_ref(A_CMP,S_W,reg,tmpref));
  1992. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1993. a_label(list,hl_skip);
  1994. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1995. end
  1996. else
  1997. inherited a_cmp_reg_ref_label(list, size, cmp_op, reg, ref, l);
  1998. end;
  1999. procedure tcg8086.gen_cmp32_jmp1(list: TAsmList; cmp_op: topcmp; l_skip, l_target: TAsmLabel);
  2000. begin
  2001. case cmp_op of
  2002. OC_EQ:
  2003. a_jmp_cond(list, OC_NE, l_skip);
  2004. OC_NE:
  2005. a_jmp_cond(list, OC_NE, l_target);
  2006. OC_GT,OC_GTE:
  2007. begin
  2008. a_jmp_cond(list, OC_GT, l_target);
  2009. a_jmp_cond(list, OC_LT, l_skip);
  2010. end;
  2011. OC_LT,OC_LTE:
  2012. begin
  2013. a_jmp_cond(list, OC_LT, l_target);
  2014. a_jmp_cond(list, OC_GT, l_skip);
  2015. end;
  2016. OC_B,OC_BE:
  2017. begin
  2018. a_jmp_cond(list, OC_B, l_target);
  2019. a_jmp_cond(list, OC_A, l_skip);
  2020. end;
  2021. OC_A,OC_AE:
  2022. begin
  2023. a_jmp_cond(list, OC_A, l_target);
  2024. a_jmp_cond(list, OC_B, l_skip);
  2025. end;
  2026. else
  2027. internalerror(2014010321);
  2028. end;
  2029. end;
  2030. procedure tcg8086.gen_cmp32_jmp2(list: TAsmList; cmp_op: topcmp; l_skip, l_target: TAsmLabel);
  2031. begin
  2032. case cmp_op of
  2033. OC_EQ:
  2034. a_jmp_cond(list, OC_EQ, l_target);
  2035. OC_GT:
  2036. a_jmp_cond(list, OC_A, l_target);
  2037. OC_LT:
  2038. a_jmp_cond(list, OC_B, l_target);
  2039. OC_GTE:
  2040. a_jmp_cond(list, OC_AE, l_target);
  2041. OC_LTE:
  2042. a_jmp_cond(list, OC_BE, l_target);
  2043. OC_NE:
  2044. a_jmp_cond(list, OC_NE, l_target);
  2045. OC_BE:
  2046. a_jmp_cond(list, OC_BE, l_target);
  2047. OC_B:
  2048. a_jmp_cond(list, OC_B, l_target);
  2049. OC_AE:
  2050. a_jmp_cond(list, OC_AE, l_target);
  2051. OC_A:
  2052. a_jmp_cond(list, OC_A, l_target);
  2053. else
  2054. internalerror(2014010322);
  2055. end;
  2056. end;
  2057. procedure tcg8086.g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);
  2058. var
  2059. ai : taicpu;
  2060. hreg16 : tregister;
  2061. hl_skip: TAsmLabel;
  2062. invf: TResFlags;
  2063. tmpsize: TCgSize;
  2064. tmpopsize: topsize;
  2065. begin
  2066. { optimized case for the carry flag, using ADC/RCL }
  2067. if f in [F_C,F_B,F_FB] then
  2068. begin
  2069. case size of
  2070. OS_8,OS_S8:
  2071. begin
  2072. tmpsize:=OS_8;
  2073. tmpopsize:=S_B;
  2074. end;
  2075. OS_16,OS_S16,OS_32,OS_S32:
  2076. begin
  2077. tmpsize:=OS_16;
  2078. tmpopsize:=S_W;
  2079. end;
  2080. else
  2081. internalerror(2013123101);
  2082. end;
  2083. list.concat(Taicpu.op_const_reg(A_MOV, tmpopsize, 0, reg));
  2084. hl_skip:=nil;
  2085. if f=F_FB then
  2086. begin
  2087. current_asmdata.getjumplabel(hl_skip);
  2088. ai:=Taicpu.op_sym(A_Jcc,S_NO,hl_skip);
  2089. ai.SetCondition(C_P);
  2090. ai.is_jmp:=true;
  2091. list.concat(ai);
  2092. end;
  2093. { RCL is faster than ADC on 8086/8088. On the 80286, it is
  2094. equally fast and it also has the same size. In these cases,
  2095. we still prefer it over ADC, because it's a better choice in
  2096. case the register is spilled. }
  2097. if (cs_opt_size in current_settings.optimizerswitches) or
  2098. (current_settings.optimizecputype<=cpu_286) then
  2099. list.concat(Taicpu.op_const_reg(A_RCL, tmpopsize, 1, reg))
  2100. else
  2101. { ADC is much faster on the 386. }
  2102. list.concat(Taicpu.op_reg_reg(A_ADC, tmpopsize, reg, reg));
  2103. if f=F_FB then
  2104. a_label(list,hl_skip);
  2105. a_load_reg_reg(list,tmpsize,size,reg,reg);
  2106. end
  2107. { optimized case for the inverted carry flag, using SBB }
  2108. else if f in [F_NC,F_AE,F_FAE] then
  2109. begin
  2110. case size of
  2111. OS_8,OS_S8:
  2112. begin
  2113. tmpsize:=OS_8;
  2114. list.concat(Taicpu.op_const_reg(A_MOV, S_B, 1, reg));
  2115. list.concat(Taicpu.op_const_reg(A_SBB, S_B, 0, reg));
  2116. end;
  2117. OS_16,OS_S16,OS_32,OS_S32:
  2118. begin
  2119. tmpsize:=OS_16;
  2120. list.concat(Taicpu.op_const_reg(A_MOV, S_W, 1, reg));
  2121. list.concat(Taicpu.op_const_reg(A_SBB, S_W, 0, reg));
  2122. end;
  2123. else
  2124. internalerror(2013123102);
  2125. end;
  2126. a_load_reg_reg(list,tmpsize,size,reg,reg);
  2127. end
  2128. else
  2129. begin
  2130. invf := f;
  2131. inverse_flags(invf);
  2132. case size of
  2133. OS_8,OS_S8:
  2134. begin
  2135. tmpsize:=OS_8;
  2136. list.concat(Taicpu.op_const_reg(A_MOV, S_B, 0, reg));
  2137. end;
  2138. OS_16,OS_S16,OS_32,OS_S32:
  2139. begin
  2140. tmpsize:=OS_16;
  2141. list.concat(Taicpu.op_const_reg(A_MOV, S_W, 0, reg));
  2142. end;
  2143. else
  2144. internalerror(2013123103);
  2145. end;
  2146. current_asmdata.getjumplabel(hl_skip);
  2147. { we can't just forward invf to a_jmp_flags for FA,FAE,FB and FBE, because
  2148. in the case of NaNs:
  2149. not(F_FA )<>F_FBE
  2150. not(F_FAE)<>F_FB
  2151. not(F_FB )<>F_FAE
  2152. not(F_FBE)<>F_FA
  2153. }
  2154. case f of
  2155. F_FA:
  2156. invf:=FPUFlags2Flags[invf];
  2157. F_FAE,F_FB:
  2158. { F_FAE and F_FB are handled above, using ADC/RCL/SBB }
  2159. internalerror(2015102101);
  2160. F_FBE:
  2161. begin
  2162. ai:=Taicpu.op_sym(A_Jcc,S_NO,hl_skip);
  2163. ai.SetCondition(C_P);
  2164. ai.is_jmp:=true;
  2165. list.concat(ai);
  2166. invf:=FPUFlags2Flags[invf];
  2167. end;
  2168. else
  2169. ;
  2170. end;
  2171. a_jmp_flags(list,invf,hl_skip);
  2172. { 16-bit INC is shorter than 8-bit }
  2173. hreg16:=makeregsize(list,reg,OS_16);
  2174. list.concat(Taicpu.op_reg(A_INC, S_W, hreg16));
  2175. makeregsize(list,hreg16,tmpsize);
  2176. a_label(list,hl_skip);
  2177. a_load_reg_reg(list,tmpsize,size,reg,reg);
  2178. end;
  2179. end;
  2180. procedure tcg8086.g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref: TReference);
  2181. var
  2182. tmpreg : tregister;
  2183. tmpregsize: TCgSize;
  2184. tmpref: treference;
  2185. begin
  2186. if size in [OS_8,OS_S8,OS_16,OS_S16] then
  2187. tmpregsize:=size
  2188. else
  2189. tmpregsize:=OS_16;
  2190. tmpreg:=getintregister(list,tmpregsize);
  2191. g_flags2reg(list,tmpregsize,f,tmpreg);
  2192. tmpref:=ref;
  2193. make_simple_ref(list,tmpref);
  2194. if size in [OS_64,OS_S64] then
  2195. begin
  2196. a_load_reg_ref(list,tmpregsize,OS_32,tmpreg,tmpref);
  2197. inc(tmpref.offset,4);
  2198. a_load_const_ref(list,OS_32,0,tmpref);
  2199. end
  2200. else
  2201. a_load_reg_ref(list,tmpregsize,size,tmpreg,tmpref);
  2202. end;
  2203. procedure tcg8086.g_stackpointer_alloc(list : TAsmList;localsize: longint);
  2204. begin
  2205. if cs_check_stack in current_settings.localswitches then
  2206. begin
  2207. cg.getcpuregister(list,NR_AX);
  2208. cg.a_load_const_reg(list,OS_16, localsize,NR_AX);
  2209. cg.a_call_name(list,'FPC_STACKCHECK_I8086',false);
  2210. cg.ungetcpuregister(list, NR_AX);
  2211. end;
  2212. if localsize>0 then
  2213. list.concat(Taicpu.Op_const_reg(A_SUB,S_W,localsize,NR_STACK_POINTER_REG));
  2214. end;
  2215. procedure tcg8086.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
  2216. var
  2217. stacksize : longint;
  2218. ret_instr: TAsmOp;
  2219. sp_moved : boolean;
  2220. procedure maybe_move_sp;
  2221. var
  2222. ref : treference;
  2223. begin
  2224. if sp_moved then
  2225. exit;
  2226. if not(pi_has_open_array_parameter in current_procinfo.flags) then
  2227. exit;
  2228. { Restore SP position before SP change }
  2229. if current_settings.x86memorymodel=mm_huge then
  2230. stacksize:=stacksize + 2;
  2231. reference_reset_base(ref,NR_BP,-stacksize,ctempposinvalid,2,[]);
  2232. list.concat(Taicpu.op_ref_reg(A_LEA,S_W,ref,NR_SP));
  2233. sp_moved:=true;
  2234. end;
  2235. begin
  2236. if is_proc_far(current_procinfo.procdef) then
  2237. ret_instr:=A_RETF
  2238. else
  2239. ret_instr:=A_RET;
  2240. { MMX needs to call EMMS }
  2241. if assigned(rg[R_MMXREGISTER]) and
  2242. (rg[R_MMXREGISTER].uses_registers) then
  2243. list.concat(Taicpu.op_none(A_EMMS,S_NO));
  2244. sp_moved:=false;
  2245. { remove stackframe }
  2246. if not nostackframe then
  2247. begin
  2248. stacksize:=current_procinfo.calc_stackframe_size;
  2249. if (target_info.stackalign>4) and
  2250. ((stacksize <> 0) or
  2251. (pi_do_call in current_procinfo.flags) or
  2252. { can't detect if a call in this case -> use nostackframe }
  2253. { if you (think you) know what you are doing }
  2254. (po_assembler in current_procinfo.procdef.procoptions)) then
  2255. stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint);
  2256. if (po_exports in current_procinfo.procdef.procoptions) and
  2257. (target_info.system=system_i8086_win16) then
  2258. begin
  2259. maybe_move_sp;
  2260. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DI));
  2261. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_SI));
  2262. end;
  2263. if ((current_settings.x86memorymodel=mm_huge) and
  2264. not (po_interrupt in current_procinfo.procdef.procoptions)) or
  2265. ((po_exports in current_procinfo.procdef.procoptions) and
  2266. (target_info.system=system_i8086_win16)) then
  2267. begin
  2268. maybe_move_sp;
  2269. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
  2270. end;
  2271. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  2272. begin
  2273. if (stacksize<>0) then
  2274. cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
  2275. end
  2276. else
  2277. begin
  2278. generate_leave(list);
  2279. if ((ts_x86_far_procs_push_odd_bp in current_settings.targetswitches) or
  2280. ((po_exports in current_procinfo.procdef.procoptions) and
  2281. (target_info.system=system_i8086_win16))) and
  2282. is_proc_far(current_procinfo.procdef) then
  2283. cg.a_op_const_reg(list,OP_SUB,OS_ADDR,1,current_procinfo.framepointer);
  2284. end;
  2285. list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
  2286. end;
  2287. { return from interrupt }
  2288. if po_interrupt in current_procinfo.procdef.procoptions then
  2289. begin
  2290. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_ES));
  2291. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
  2292. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DI));
  2293. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_SI));
  2294. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DX));
  2295. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_CX));
  2296. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_BX));
  2297. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_AX));
  2298. list.concat(Taicpu.Op_none(A_IRET,S_NO));
  2299. end
  2300. { Routines with the poclearstack flag set use only a ret }
  2301. else if (current_procinfo.procdef.proccalloption in clearstack_pocalls) and
  2302. (not paramanager.use_fixed_stack) then
  2303. begin
  2304. { complex return values are removed from stack in C code PM }
  2305. { but not on win32 }
  2306. { and not for safecall with hidden exceptions, because the result }
  2307. { wich contains the exception is passed in EAX }
  2308. if (target_info.system <> system_i386_win32) and
  2309. not ((current_procinfo.procdef.proccalloption = pocall_safecall) and
  2310. (tf_safecall_exceptions in target_info.flags)) and
  2311. paramanager.ret_in_param(current_procinfo.procdef.returndef,
  2312. current_procinfo.procdef) then
  2313. list.concat(Taicpu.Op_const(ret_instr,S_W,sizeof(aint)))
  2314. else
  2315. list.concat(Taicpu.Op_none(ret_instr,S_NO));
  2316. end
  2317. { ... also routines with parasize=0 }
  2318. else if (parasize=0) then
  2319. list.concat(Taicpu.Op_none(ret_instr,S_NO))
  2320. else
  2321. begin
  2322. { parameters are limited to 65535 bytes because ret allows only imm16 }
  2323. if (parasize>65535) then
  2324. CGMessage(cg_e_parasize_too_big);
  2325. list.concat(Taicpu.Op_const(ret_instr,S_W,parasize));
  2326. end;
  2327. end;
  2328. procedure tcg8086.g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);
  2329. var
  2330. power : longint;
  2331. opsize : topsize;
  2332. saved_ds: Boolean;
  2333. begin
  2334. { get stack space }
  2335. getcpuregister(list,NR_DI);
  2336. a_load_loc_reg(list,OS_INT,lenloc,NR_DI);
  2337. list.concat(Taicpu.op_reg(A_INC,S_W,NR_DI));
  2338. { Now DI contains (high+1). }
  2339. include(current_procinfo.flags, pi_has_open_array_parameter);
  2340. { special case handling for elesize=2:
  2341. set CX = (high+1) instead of CX = (high+1)*elesize.
  2342. This allows us to avoid the SHR later. }
  2343. if elesize=2 then
  2344. begin
  2345. { Now DI contains (high+1). Copy it to CX for later use. }
  2346. getcpuregister(list,NR_CX);
  2347. list.concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_DI,NR_CX));
  2348. end;
  2349. { DI := DI * elesize }
  2350. if (elesize<>1) then
  2351. begin
  2352. if ispowerof2(elesize, power) then
  2353. a_op_const_reg(list,OP_SHL,OS_16,power,NR_DI)
  2354. else
  2355. a_op_const_reg(list,OP_IMUL,OS_16,elesize,NR_DI);
  2356. end;
  2357. if elesize<>2 then
  2358. begin
  2359. { Now DI contains (high+1)*elesize. Copy it to CX for later use. }
  2360. getcpuregister(list,NR_CX);
  2361. list.concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_DI,NR_CX));
  2362. end;
  2363. { If we were probing pages, EDI=(size mod pagesize) and ESP is decremented
  2364. by (size div pagesize)*pagesize, otherwise EDI=size.
  2365. Either way, subtracting EDI from ESP will set ESP to desired final value. }
  2366. list.concat(Taicpu.op_reg_reg(A_SUB,S_W,NR_DI,NR_SP));
  2367. { align stack on 2 bytes }
  2368. list.concat(Taicpu.op_const_reg(A_AND,S_W,aint($fffe),NR_SP));
  2369. { load destination, don't use a_load_reg_reg, that will add a move instruction
  2370. that can confuse the reg allocator }
  2371. list.concat(Taicpu.Op_reg_reg(A_MOV,S_W,NR_SP,NR_DI));
  2372. {$ifdef volatile_es}
  2373. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_SS));
  2374. list.concat(taicpu.op_reg(A_POP,S_W,NR_ES));
  2375. {$endif volatile_es}
  2376. { Allocate SI and load it with source }
  2377. getcpuregister(list,NR_SI);
  2378. if ((ref.segment=NR_NO) and (segment_regs_equal(NR_SS,NR_DS) or (ref.base<>NR_BP))) or
  2379. (is_segment_reg(ref.segment) and segment_regs_equal(ref.segment,NR_DS)) then
  2380. begin
  2381. hlcg.a_loadaddr_ref_reg(list,voidnearpointertype,voidnearpointertype,ref,NR_SI);
  2382. saved_ds:=false;
  2383. end
  2384. else
  2385. begin
  2386. hlcg.a_loadaddr_ref_reg(list,voidnearpointertype,voidnearpointertype,ref,NR_SI);
  2387. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DS));
  2388. saved_ds:=true;
  2389. if ref.segment<>NR_NO then
  2390. list.concat(taicpu.op_reg(A_PUSH,S_W,ref.segment))
  2391. else if ref.base=NR_BP then
  2392. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_SS))
  2393. else
  2394. internalerror(2014040403);
  2395. list.concat(taicpu.op_reg(A_POP,S_W,NR_DS));
  2396. end;
  2397. { calculate size }
  2398. opsize:=S_B;
  2399. if elesize=2 then
  2400. begin
  2401. opsize:=S_W;
  2402. { CX is already number of words, so no need to SHL/SHR }
  2403. end
  2404. else if (elesize and 1)=0 then
  2405. begin
  2406. opsize:=S_W;
  2407. { CX is number of bytes, convert to words }
  2408. list.concat(Taicpu.op_const_reg(A_SHR,S_W,1,NR_CX))
  2409. end;
  2410. if ts_cld in current_settings.targetswitches then
  2411. list.concat(Taicpu.op_none(A_CLD,S_NO));
  2412. if (opsize=S_B) and not (cs_opt_size in current_settings.optimizerswitches) then
  2413. begin
  2414. { SHR CX,1 moves the lowest (odd/even) bit to the carry flag }
  2415. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2416. list.concat(Taicpu.op_const_reg(A_SHR,S_W,1,NR_CX));
  2417. list.concat(Taicpu.op_none(A_REP,S_NO));
  2418. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  2419. { ADC CX,CX will set CX to 1 if the number of bytes was odd }
  2420. list.concat(Taicpu.op_reg_reg(A_ADC,S_W,NR_CX,NR_CX));
  2421. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2422. list.concat(Taicpu.op_none(A_REP,S_NO));
  2423. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  2424. end
  2425. else
  2426. begin
  2427. list.concat(Taicpu.op_none(A_REP,S_NO));
  2428. case opsize of
  2429. S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  2430. S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
  2431. else
  2432. internalerror(2019051019);
  2433. end;
  2434. end;
  2435. ungetcpuregister(list,NR_DI);
  2436. ungetcpuregister(list,NR_CX);
  2437. ungetcpuregister(list,NR_SI);
  2438. if saved_ds then
  2439. list.concat(taicpu.op_reg(A_POP,S_W,NR_DS));
  2440. { patch the new address, but don't use a_load_reg_reg, that will add a move instruction
  2441. that can confuse the reg allocator }
  2442. list.concat(Taicpu.Op_reg_reg(A_MOV,S_W,NR_SP,destreg));
  2443. if current_settings.x86memorymodel in x86_far_data_models then
  2444. list.concat(Taicpu.Op_reg_reg(A_MOV,S_W,NR_SS,GetNextReg(destreg)));
  2445. end;
  2446. procedure tcg8086.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
  2447. begin
  2448. { Nothing to do }
  2449. end;
  2450. procedure tcg8086.get_32bit_ops(op: TOpCG; out op1, op2: TAsmOp);
  2451. begin
  2452. case op of
  2453. OP_ADD :
  2454. begin
  2455. op1:=A_ADD;
  2456. op2:=A_ADC;
  2457. end;
  2458. OP_SUB :
  2459. begin
  2460. op1:=A_SUB;
  2461. op2:=A_SBB;
  2462. end;
  2463. OP_XOR :
  2464. begin
  2465. op1:=A_XOR;
  2466. op2:=A_XOR;
  2467. end;
  2468. OP_OR :
  2469. begin
  2470. op1:=A_OR;
  2471. op2:=A_OR;
  2472. end;
  2473. OP_AND :
  2474. begin
  2475. op1:=A_AND;
  2476. op2:=A_AND;
  2477. end;
  2478. else
  2479. internalerror(200203241);
  2480. end;
  2481. end;
  2482. procedure tcg8086.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
  2483. var
  2484. hsym : tsym;
  2485. href : treference;
  2486. paraloc : Pcgparalocation;
  2487. return_address_size: Integer;
  2488. begin
  2489. if current_settings.x86memorymodel in x86_far_code_models then
  2490. return_address_size:=4
  2491. else
  2492. return_address_size:=2;
  2493. { calculate the parameter info for the procdef }
  2494. procdef.init_paraloc_info(callerside);
  2495. hsym:=tsym(procdef.parast.Find('self'));
  2496. if not(assigned(hsym) and
  2497. (hsym.typ=paravarsym)) then
  2498. internalerror(2003052502);
  2499. paraloc:=tparavarsym(hsym).paraloc[callerside].location;
  2500. with paraloc^ do
  2501. begin
  2502. case loc of
  2503. LOC_REGISTER:
  2504. a_op_const_reg(list,OP_SUB,size,ioffset,register);
  2505. LOC_REFERENCE:
  2506. begin
  2507. { offset in the wrapper needs to be adjusted for the stored
  2508. return address }
  2509. if (reference.index<>NR_BP) and (reference.index<>NR_BX) and (reference.index<>NR_DI)
  2510. and (reference.index<>NR_SI) then
  2511. begin
  2512. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DI));
  2513. list.concat(taicpu.op_reg_reg(A_MOV,S_W,reference.index,NR_DI));
  2514. if reference.index=NR_SP then
  2515. reference_reset_base(href,NR_DI,reference.offset+return_address_size+2,ctempposinvalid,sizeof(pint),[])
  2516. else
  2517. reference_reset_base(href,NR_DI,reference.offset+return_address_size,ctempposinvalid,sizeof(pint),[]);
  2518. href.segment:=NR_SS;
  2519. a_op_const_ref(list,OP_SUB,size,ioffset,href);
  2520. list.concat(taicpu.op_reg(A_POP,S_W,NR_DI));
  2521. end
  2522. else
  2523. begin
  2524. reference_reset_base(href,reference.index,reference.offset+return_address_size,ctempposinvalid,sizeof(pint),[]);
  2525. href.segment:=NR_SS;
  2526. a_op_const_ref(list,OP_SUB,size,ioffset,href);
  2527. end;
  2528. end
  2529. else
  2530. internalerror(2003091802);
  2531. end;
  2532. paraloc:=next;
  2533. end;
  2534. end;
  2535. { ************* 64bit operations ************ }
  2536. procedure tcg64f8086.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  2537. begin
  2538. case op of
  2539. OP_ADD :
  2540. begin
  2541. op1:=A_ADD;
  2542. op2:=A_ADC;
  2543. end;
  2544. OP_SUB :
  2545. begin
  2546. op1:=A_SUB;
  2547. op2:=A_SBB;
  2548. end;
  2549. OP_XOR :
  2550. begin
  2551. op1:=A_XOR;
  2552. op2:=A_XOR;
  2553. end;
  2554. OP_OR :
  2555. begin
  2556. op1:=A_OR;
  2557. op2:=A_OR;
  2558. end;
  2559. OP_AND :
  2560. begin
  2561. op1:=A_AND;
  2562. op2:=A_AND;
  2563. end;
  2564. else
  2565. internalerror(2002032403);
  2566. end;
  2567. end;
  2568. procedure tcg64f8086.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
  2569. var
  2570. op1,op2 : TAsmOp;
  2571. tempref : treference;
  2572. begin
  2573. if not(op in [OP_NEG,OP_NOT]) then
  2574. begin
  2575. get_64bit_ops(op,op1,op2);
  2576. tempref:=ref;
  2577. tcgx86(cg).make_simple_ref(list,tempref);
  2578. if op in [OP_ADD,OP_SUB] then
  2579. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2580. list.concat(taicpu.op_ref_reg(op1,S_W,tempref,reg.reglo));
  2581. inc(tempref.offset,2);
  2582. list.concat(taicpu.op_ref_reg(op2,S_W,tempref,cg.GetNextReg(reg.reglo)));
  2583. inc(tempref.offset,2);
  2584. list.concat(taicpu.op_ref_reg(op2,S_W,tempref,reg.reghi));
  2585. inc(tempref.offset,2);
  2586. list.concat(taicpu.op_ref_reg(op2,S_W,tempref,cg.GetNextReg(reg.reghi)));
  2587. if op in [OP_ADD,OP_SUB] then
  2588. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2589. end
  2590. else
  2591. begin
  2592. a_load64_ref_reg(list,ref,reg);
  2593. a_op64_reg_reg(list,op,size,reg,reg);
  2594. end;
  2595. end;
  2596. procedure tcg64f8086.a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
  2597. var
  2598. op1,op2 : TAsmOp;
  2599. tempref : treference;
  2600. begin
  2601. case op of
  2602. OP_NOT,OP_NEG:
  2603. inherited;
  2604. else
  2605. begin
  2606. get_64bit_ops(op,op1,op2);
  2607. tempref:=ref;
  2608. tcgx86(cg).make_simple_ref(list,tempref);
  2609. if op in [OP_ADD,OP_SUB] then
  2610. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2611. list.concat(taicpu.op_reg_ref(op1,S_W,reg.reglo,tempref));
  2612. inc(tempref.offset,2);
  2613. list.concat(taicpu.op_reg_ref(op2,S_W,cg.GetNextReg(reg.reglo),tempref));
  2614. inc(tempref.offset,2);
  2615. list.concat(taicpu.op_reg_ref(op2,S_W,reg.reghi,tempref));
  2616. inc(tempref.offset,2);
  2617. list.concat(taicpu.op_reg_ref(op2,S_W,cg.GetNextReg(reg.reghi),tempref));
  2618. if op in [OP_ADD,OP_SUB] then
  2619. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2620. end;
  2621. end;
  2622. end;
  2623. procedure tcg64f8086.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2624. var
  2625. op1,op2 : TAsmOp;
  2626. l2, l3: TAsmLabel;
  2627. ai: taicpu;
  2628. begin
  2629. case op of
  2630. OP_NEG :
  2631. begin
  2632. if (regsrc.reglo<>regdst.reglo) then
  2633. a_load64_reg_reg(list,regsrc,regdst);
  2634. cg.a_op_reg_reg(list,OP_NOT,OS_32,regdst.reghi,regdst.reghi);
  2635. list.concat(taicpu.op_reg(A_NOT,S_W,cg.GetNextReg(regdst.reglo)));
  2636. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2637. list.concat(taicpu.op_reg(A_NEG,S_W,regdst.reglo));
  2638. list.concat(taicpu.op_const_reg(A_SBB,S_W,-1,cg.GetNextReg(regdst.reglo)));
  2639. list.concat(taicpu.op_const_reg(A_SBB,S_W,-1,regdst.reghi));
  2640. list.concat(taicpu.op_const_reg(A_SBB,S_W,-1,cg.GetNextReg(regdst.reghi)));
  2641. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2642. exit;
  2643. end;
  2644. OP_NOT :
  2645. begin
  2646. if (regsrc.reglo<>regdst.reglo) then
  2647. a_load64_reg_reg(list,regsrc,regdst);
  2648. cg.a_op_reg_reg(list,OP_NOT,OS_32,regdst.reglo,regdst.reglo);
  2649. cg.a_op_reg_reg(list,OP_NOT,OS_32,regdst.reghi,regdst.reghi);
  2650. exit;
  2651. end;
  2652. OP_SHR,OP_SHL,OP_SAR:
  2653. begin
  2654. { load right operators in a register }
  2655. cg.getcpuregister(list,NR_CX);
  2656. cg.a_load_reg_reg(list,OS_16,OS_16,regsrc.reglo,NR_CX);
  2657. current_asmdata.getjumplabel(l2);
  2658. current_asmdata.getjumplabel(l3);
  2659. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2660. list.concat(taicpu.op_const_reg(A_AND,S_W,63,NR_CX));
  2661. cg.a_jmp_flags(list,F_E,l3);
  2662. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2663. cg.a_label(list,l2);
  2664. case op of
  2665. OP_SHL:
  2666. begin
  2667. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2668. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,regdst.reglo));
  2669. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(regdst.reglo)));
  2670. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,regdst.reghi));
  2671. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(regdst.reghi)));
  2672. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2673. end;
  2674. OP_SHR,OP_SAR:
  2675. begin
  2676. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2677. cg.a_op_const_reg(list,op,OS_16,1,cg.GetNextReg(regdst.reghi));
  2678. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,regdst.reghi));
  2679. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(regdst.reglo)));
  2680. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,regdst.reglo));
  2681. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2682. end;
  2683. else
  2684. internalerror(2019051018);
  2685. end;
  2686. ai:=Taicpu.Op_Sym(A_LOOP,S_W,l2);
  2687. ai.is_jmp := True;
  2688. list.Concat(ai);
  2689. cg.a_label(list,l3);
  2690. cg.ungetcpuregister(list,NR_CX);
  2691. exit;
  2692. end;
  2693. else
  2694. ;
  2695. end;
  2696. get_64bit_ops(op,op1,op2);
  2697. if op in [OP_ADD,OP_SUB] then
  2698. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2699. list.concat(taicpu.op_reg_reg(op1,S_W,regsrc.reglo,regdst.reglo));
  2700. list.concat(taicpu.op_reg_reg(op2,S_W,cg.GetNextReg(regsrc.reglo),cg.GetNextReg(regdst.reglo)));
  2701. list.concat(taicpu.op_reg_reg(op2,S_W,regsrc.reghi,regdst.reghi));
  2702. list.concat(taicpu.op_reg_reg(op2,S_W,cg.GetNextReg(regsrc.reghi),cg.GetNextReg(regdst.reghi)));
  2703. if op in [OP_ADD,OP_SUB] then
  2704. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2705. end;
  2706. procedure tcg64f8086.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2707. var
  2708. op1,op2 : TAsmOp;
  2709. loop_start: TAsmLabel;
  2710. ai: taicpu;
  2711. begin
  2712. case op of
  2713. OP_AND,OP_OR,OP_XOR:
  2714. begin
  2715. cg.a_op_const_reg(list,op,OS_32,tcgint(lo(value)),reg.reglo);
  2716. cg.a_op_const_reg(list,op,OS_32,tcgint(hi(value)),reg.reghi);
  2717. end;
  2718. OP_ADD, OP_SUB:
  2719. begin
  2720. get_64bit_ops(op,op1,op2);
  2721. if (value and $ffffffffffff) = 0 then
  2722. begin
  2723. { use a_op_const_reg to allow the use of inc/dec }
  2724. cg.a_op_const_reg(list,op,OS_16,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi));
  2725. end
  2726. // can't use a_op_const_ref because this may use dec/inc
  2727. else if (value and $ffffffff) = 0 then
  2728. begin
  2729. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2730. list.concat(taicpu.op_const_reg(op1,S_W,aint((value shr 32) and $ffff),reg.reghi));
  2731. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi)));
  2732. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2733. end
  2734. else if (value and $ffff) = 0 then
  2735. begin
  2736. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2737. list.concat(taicpu.op_const_reg(op1,S_W,aint((value shr 16) and $ffff),cg.GetNextReg(reg.reglo)));
  2738. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 32) and $ffff),reg.reghi));
  2739. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi)));
  2740. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2741. end
  2742. else
  2743. begin
  2744. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2745. list.concat(taicpu.op_const_reg(op1,S_W,aint(value and $ffff),reg.reglo));
  2746. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 16) and $ffff),cg.GetNextReg(reg.reglo)));
  2747. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 32) and $ffff),reg.reghi));
  2748. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi)));
  2749. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2750. end;
  2751. end;
  2752. OP_SHR,OP_SHL,OP_SAR:
  2753. begin
  2754. value:=value and 63;
  2755. case value of
  2756. 0:
  2757. { ultra hyper fast shift by 0 };
  2758. 1:
  2759. case op of
  2760. OP_SHL:
  2761. begin
  2762. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2763. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,reg.reglo));
  2764. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reglo)));
  2765. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,reg.reghi));
  2766. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reghi)));
  2767. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2768. end;
  2769. OP_SHR,OP_SAR:
  2770. begin
  2771. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2772. cg.a_op_const_reg(list,op,OS_16,1,cg.GetNextReg(reg.reghi));
  2773. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reghi));
  2774. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2775. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2776. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2777. end;
  2778. else
  2779. internalerror(2019051017);
  2780. end;
  2781. 2..15:
  2782. begin
  2783. cg.getcpuregister(list,NR_CX);
  2784. cg.a_load_const_reg(list,OS_16,value,NR_CX);
  2785. current_asmdata.getjumplabel(loop_start);
  2786. cg.a_label(list,loop_start);
  2787. case op of
  2788. OP_SHL:
  2789. begin
  2790. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2791. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,reg.reglo));
  2792. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reglo)));
  2793. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,reg.reghi));
  2794. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reghi)));
  2795. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2796. end;
  2797. OP_SHR,OP_SAR:
  2798. begin
  2799. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2800. cg.a_op_const_reg(list,op,OS_16,1,cg.GetNextReg(reg.reghi));
  2801. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reghi));
  2802. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2803. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2804. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2805. end;
  2806. else
  2807. internalerror(2019051010);
  2808. end;
  2809. ai:=Taicpu.Op_Sym(A_LOOP,S_W,loop_start);
  2810. ai.is_jmp := True;
  2811. list.Concat(ai);
  2812. cg.ungetcpuregister(list,NR_CX);
  2813. end;
  2814. 16,17:
  2815. begin
  2816. case op of
  2817. OP_SHL:
  2818. begin
  2819. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reghi));
  2820. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reghi);
  2821. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reglo,cg.GetNextReg(reg.reglo));
  2822. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2823. end;
  2824. OP_SHR:
  2825. begin
  2826. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2827. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2828. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2829. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  2830. end;
  2831. OP_SAR:
  2832. begin
  2833. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2834. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2835. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2836. cg.a_op_const_reg(list,OP_SAR,OS_16,15,cg.GetNextReg(reg.reghi));
  2837. end;
  2838. else
  2839. internalerror(2019051011);
  2840. end;
  2841. if value=17 then
  2842. case op of
  2843. OP_SHL:
  2844. begin
  2845. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2846. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,cg.GetNextReg(reg.reglo)));
  2847. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,reg.reghi));
  2848. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reghi)));
  2849. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2850. end;
  2851. OP_SHR,OP_SAR:
  2852. begin
  2853. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2854. cg.a_op_const_reg(list,op,OS_16,1,reg.reghi);
  2855. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2856. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2857. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2858. end;
  2859. else
  2860. internalerror(2019051012);
  2861. end;
  2862. end;
  2863. 18..31:
  2864. begin
  2865. case op of
  2866. OP_SHL:
  2867. begin
  2868. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reghi));
  2869. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reghi);
  2870. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reglo,cg.GetNextReg(reg.reglo));
  2871. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2872. end;
  2873. OP_SHR:
  2874. begin
  2875. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2876. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2877. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2878. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  2879. end;
  2880. OP_SAR:
  2881. begin
  2882. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2883. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2884. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2885. cg.a_op_const_reg(list,OP_SAR,OS_16,15,cg.GetNextReg(reg.reghi));
  2886. end;
  2887. else
  2888. internalerror(2019051013);
  2889. end;
  2890. cg.getcpuregister(list,NR_CX);
  2891. cg.a_load_const_reg(list,OS_16,value-16,NR_CX);
  2892. current_asmdata.getjumplabel(loop_start);
  2893. cg.a_label(list,loop_start);
  2894. case op of
  2895. OP_SHL:
  2896. begin
  2897. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2898. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,cg.GetNextReg(reg.reglo)));
  2899. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,reg.reghi));
  2900. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reghi)));
  2901. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2902. end;
  2903. OP_SHR,OP_SAR:
  2904. begin
  2905. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2906. cg.a_op_const_reg(list,op,OS_16,1,reg.reghi);
  2907. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2908. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2909. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2910. end;
  2911. else
  2912. internalerror(2019051014);
  2913. end;
  2914. ai:=Taicpu.Op_Sym(A_LOOP,S_W,loop_start);
  2915. ai.is_jmp := True;
  2916. list.Concat(ai);
  2917. cg.ungetcpuregister(list,NR_CX);
  2918. end;
  2919. 32..47:
  2920. case op of
  2921. OP_SHL:
  2922. begin
  2923. cg.a_op_const_reg_reg(list,OP_SHL,OS_32,value-32,reg.reglo,reg.reghi);
  2924. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2925. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reglo));
  2926. end;
  2927. OP_SHR:
  2928. begin
  2929. cg.a_op_const_reg_reg(list,OP_SHR,OS_32,value-32,reg.reghi,reg.reglo);
  2930. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reghi,reg.reghi);
  2931. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  2932. end;
  2933. OP_SAR:
  2934. begin
  2935. cg.a_op_const_reg_reg(list,OP_SAR,OS_32,value-32,reg.reghi,reg.reglo);
  2936. cg.a_op_const_reg_reg(list,OP_SAR,OS_16,15-(value-32),cg.GetNextReg(reg.reglo),reg.reghi);
  2937. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reghi));
  2938. end;
  2939. else
  2940. internalerror(2019051015);
  2941. end;
  2942. 48..63:
  2943. case op of
  2944. OP_SHL:
  2945. begin
  2946. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reglo,cg.GetNextReg(reg.reghi));
  2947. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2948. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reglo));
  2949. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reghi,reg.reghi);
  2950. cg.a_op_const_reg(list,OP_SHL,OS_16,value-48,cg.GetNextReg(reg.reghi));
  2951. end;
  2952. OP_SHR:
  2953. begin
  2954. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reglo);
  2955. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  2956. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reghi,reg.reghi);
  2957. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reglo));
  2958. cg.a_op_const_reg(list,OP_SHR,OS_16,value-48,reg.reglo);
  2959. end;
  2960. OP_SAR:
  2961. if value=63 then
  2962. begin
  2963. cg.a_op_const_reg(list,OP_SAR,OS_16,15,cg.GetNextReg(reg.reghi));
  2964. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2965. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reglo));
  2966. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reglo);
  2967. end
  2968. else
  2969. begin
  2970. cg.a_op_const_reg_reg(list,OP_SAR,OS_16,value-48,cg.GetNextReg(reg.reghi),reg.reglo);
  2971. cg.a_op_const_reg_reg(list,OP_SAR,OS_16,15-(value-48),reg.reglo,cg.GetNextReg(reg.reglo));
  2972. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reghi);
  2973. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reghi));
  2974. end;
  2975. else
  2976. internalerror(2019051016);
  2977. end;
  2978. end;
  2979. end;
  2980. else
  2981. internalerror(200204021);
  2982. end;
  2983. end;
  2984. procedure tcg64f8086.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
  2985. var
  2986. op1,op2 : TAsmOp;
  2987. tempref : treference;
  2988. begin
  2989. tempref:=ref;
  2990. tcgx86(cg).make_simple_ref(list,tempref);
  2991. case op of
  2992. OP_AND,OP_OR,OP_XOR:
  2993. begin
  2994. cg.a_op_const_ref(list,op,OS_32,tcgint(lo(value)),tempref);
  2995. inc(tempref.offset,4);
  2996. cg.a_op_const_ref(list,op,OS_32,tcgint(hi(value)),tempref);
  2997. end;
  2998. OP_ADD, OP_SUB:
  2999. begin
  3000. get_64bit_ops(op,op1,op2);
  3001. if (value and $ffffffffffff) = 0 then
  3002. begin
  3003. inc(tempref.offset,6);
  3004. { use a_op_const_ref to allow the use of inc/dec }
  3005. cg.a_op_const_ref(list,op,OS_16,aint((value shr 48) and $ffff),tempref);
  3006. end
  3007. // can't use a_op_const_ref because this may use dec/inc
  3008. else if (value and $ffffffff) = 0 then
  3009. begin
  3010. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  3011. inc(tempref.offset,4);
  3012. list.concat(taicpu.op_const_ref(op1,S_W,aint((value shr 32) and $ffff),tempref));
  3013. inc(tempref.offset,2);
  3014. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 48) and $ffff),tempref));
  3015. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  3016. end
  3017. else if (value and $ffff) = 0 then
  3018. begin
  3019. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  3020. inc(tempref.offset,2);
  3021. list.concat(taicpu.op_const_ref(op1,S_W,aint((value shr 16) and $ffff),tempref));
  3022. inc(tempref.offset,2);
  3023. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 32) and $ffff),tempref));
  3024. inc(tempref.offset,2);
  3025. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 48) and $ffff),tempref));
  3026. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  3027. end
  3028. else
  3029. begin
  3030. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  3031. list.concat(taicpu.op_const_ref(op1,S_W,aint(value and $ffff),tempref));
  3032. inc(tempref.offset,2);
  3033. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 16) and $ffff),tempref));
  3034. inc(tempref.offset,2);
  3035. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 32) and $ffff),tempref));
  3036. inc(tempref.offset,2);
  3037. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 48) and $ffff),tempref));
  3038. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  3039. end;
  3040. end;
  3041. else
  3042. internalerror(200204022);
  3043. end;
  3044. end;
  3045. procedure tcg64f8086.a_op64_ref(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference);
  3046. var
  3047. tempref: treference;
  3048. begin
  3049. tempref:=ref;
  3050. tcgx86(cg).make_simple_ref(list,tempref);
  3051. case op of
  3052. OP_NOT:
  3053. begin
  3054. cg.a_op_ref(list,op,OS_32,tempref);
  3055. inc(tempref.offset,4);
  3056. cg.a_op_ref(list,op,OS_32,tempref);
  3057. end;
  3058. OP_NEG :
  3059. begin
  3060. inc(tempref.offset,6);
  3061. cg.a_op_ref(list,OP_NOT,OS_16,tempref);
  3062. dec(tempref.offset,2);
  3063. cg.a_op_ref(list,OP_NOT,OS_16,tempref);
  3064. dec(tempref.offset,2);
  3065. cg.a_op_ref(list,OP_NOT,OS_16,tempref);
  3066. dec(tempref.offset,2);
  3067. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  3068. list.concat(taicpu.op_ref(A_NEG,S_W,tempref));
  3069. inc(tempref.offset,2);
  3070. list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
  3071. inc(tempref.offset,2);
  3072. list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
  3073. inc(tempref.offset,2);
  3074. list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
  3075. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  3076. end;
  3077. else
  3078. inherited;
  3079. end;
  3080. end;
  3081. procedure create_codegen;
  3082. begin
  3083. cg := tcg8086.create;
  3084. cg64 := tcg64f8086.create;
  3085. end;
  3086. end.