cgcpu.pas 139 KB

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