cgcpu.pas 139 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315
  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. procedure add_move_instruction(instr:Taicpu);override;
  76. protected
  77. procedure a_load_ref_reg_internal(list : TAsmList;fromsize,tosize: tcgsize;const ref : treference;reg : tregister;isdirect:boolean);override;
  78. end;
  79. tcg64f8086 = class(tcg64f32)
  80. procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
  81. procedure a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);override;
  82. procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
  83. procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
  84. procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;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 (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. begin
  1143. var
  1144. tmpref: treference;
  1145. begin
  1146. tmpref:=ref;
  1147. make_simple_ref(list,tmpref);
  1148. if size in [OS_64, OS_S64] then
  1149. internalerror(2013050803);
  1150. if size in [OS_32, OS_S32] then
  1151. begin
  1152. case op of
  1153. OP_NEG:
  1154. begin
  1155. inc(tmpref.offset, 2);
  1156. list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
  1157. dec(tmpref.offset, 2);
  1158. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1159. list.concat(taicpu.op_ref(A_NEG, S_W, tmpref));
  1160. inc(tmpref.offset, 2);
  1161. list.concat(taicpu.op_const_ref(A_SBB, S_W,-1, tmpref));
  1162. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1163. end;
  1164. OP_NOT:
  1165. begin
  1166. list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
  1167. inc(tmpref.offset, 2);
  1168. list.concat(taicpu.op_ref(A_NOT, S_W, tmpref));
  1169. end;
  1170. else
  1171. internalerror(2020050709);
  1172. end;
  1173. end
  1174. else
  1175. inherited a_op_reg_ref(list,Op,size,reg,tmpref);
  1176. end;
  1177. procedure tcg8086.push_const(list: TAsmList; size: tcgsize; a: tcgint);
  1178. var
  1179. tmpreg: TRegister;
  1180. begin
  1181. if not (size in [OS_16,OS_S16]) then
  1182. internalerror(2013043001);
  1183. if current_settings.cputype < cpu_186 then
  1184. begin
  1185. tmpreg:=getintregister(list,size);
  1186. a_load_const_reg(list,size,a,tmpreg);
  1187. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1188. end
  1189. else
  1190. list.concat(taicpu.op_const(A_PUSH,TCGSize2OpSize[size],a));
  1191. end;
  1192. procedure tcg8086.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
  1193. procedure load_para_loc(r : TRegister;paraloc : PCGParaLocation);
  1194. var
  1195. ref : treference;
  1196. begin
  1197. paramanager.allocparaloc(list,paraloc);
  1198. case paraloc^.loc of
  1199. LOC_REGISTER,LOC_CREGISTER:
  1200. a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
  1201. LOC_REFERENCE,LOC_CREFERENCE:
  1202. begin
  1203. reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
  1204. a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
  1205. end;
  1206. else
  1207. internalerror(2002071004);
  1208. end;
  1209. end;
  1210. var
  1211. pushsize,pushsize2 : tcgsize;
  1212. begin
  1213. check_register_size(size,r);
  1214. if use_push(cgpara) then
  1215. begin
  1216. if tcgsize2size[cgpara.Size] > 2 then
  1217. begin
  1218. if tcgsize2size[cgpara.Size] <> 4 then
  1219. internalerror(2013031101);
  1220. if cgpara.location^.Next = nil then
  1221. begin
  1222. if tcgsize2size[cgpara.location^.size] <> 4 then
  1223. internalerror(2013031101);
  1224. end
  1225. else
  1226. begin
  1227. if tcgsize2size[cgpara.location^.size] <> 2 then
  1228. internalerror(2013031101);
  1229. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  1230. internalerror(2013031101);
  1231. if cgpara.location^.Next^.Next <> nil then
  1232. internalerror(2013031101);
  1233. end;
  1234. if tcgsize2size[cgpara.size]>cgpara.alignment then
  1235. pushsize:=cgpara.size
  1236. else
  1237. pushsize:=int_cgsize(cgpara.alignment);
  1238. pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2);
  1239. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2)));
  1240. list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16)));
  1241. end
  1242. else
  1243. begin
  1244. cgpara.check_simple_location;
  1245. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  1246. pushsize:=cgpara.location^.size
  1247. else
  1248. pushsize:=int_cgsize(cgpara.alignment);
  1249. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
  1250. end;
  1251. end
  1252. else
  1253. begin
  1254. if tcgsize2size[cgpara.Size]=4 then
  1255. begin
  1256. if (cgpara.location^.Next=nil) or
  1257. (tcgsize2size[cgpara.location^.size]<>2) or
  1258. (tcgsize2size[cgpara.location^.Next^.size]<>2) or
  1259. (cgpara.location^.Next^.Next<>nil) or
  1260. (cgpara.location^.shiftval<>0) then
  1261. internalerror(2013031102);
  1262. load_para_loc(r,cgpara.Location);
  1263. load_para_loc(GetNextReg(r),cgpara.Location^.Next);
  1264. end
  1265. else
  1266. inherited a_load_reg_cgpara(list,size,r,cgpara);
  1267. end;
  1268. end;
  1269. procedure tcg8086.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);
  1270. var
  1271. pushsize : tcgsize;
  1272. begin
  1273. if use_push(cgpara) then
  1274. begin
  1275. if tcgsize2size[cgpara.Size] > 2 then
  1276. begin
  1277. if tcgsize2size[cgpara.Size] <> 4 then
  1278. internalerror(2013031101);
  1279. if cgpara.location^.Next = nil then
  1280. begin
  1281. if tcgsize2size[cgpara.location^.size] <> 4 then
  1282. internalerror(2013031101);
  1283. end
  1284. else
  1285. begin
  1286. if tcgsize2size[cgpara.location^.size] <> 2 then
  1287. internalerror(2013031101);
  1288. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  1289. internalerror(2013031101);
  1290. if cgpara.location^.Next^.Next <> nil then
  1291. internalerror(2013031101);
  1292. end;
  1293. if (cgpara.alignment <> 4) and (cgpara.alignment <> 2) then
  1294. internalerror(2013031101);
  1295. push_const(list,OS_16,a shr 16);
  1296. push_const(list,OS_16,a and $FFFF);
  1297. end
  1298. else
  1299. begin
  1300. cgpara.check_simple_location;
  1301. if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
  1302. pushsize:=cgpara.location^.size
  1303. else
  1304. pushsize:=int_cgsize(cgpara.alignment);
  1305. push_const(list,pushsize,a);
  1306. end;
  1307. end
  1308. else if (tcgsize2size[cgpara.Size]>2) and
  1309. (cgpara.location^.loc in [LOC_REGISTER,LOC_CREGISTER]) and
  1310. (cgpara.location^.Next<>nil) then
  1311. begin
  1312. if (tcgsize2size[cgpara.Size]<>4) or
  1313. (tcgsize2size[cgpara.location^.Size]<>2) or
  1314. not (cgpara.location^.Next^.Loc in [LOC_REGISTER,LOC_CREGISTER]) or
  1315. (tcgsize2size[cgpara.location^.Next^.Size]<>2) or
  1316. (cgpara.location^.Next^.Next<>nil) then
  1317. internalerror(2018041801);
  1318. a_load_const_reg(list,cgpara.location^.size,a and $FFFF,cgpara.location^.register);
  1319. a_load_const_reg(list,cgpara.location^.Next^.size,a shr 16,cgpara.location^.Next^.register);
  1320. end
  1321. else
  1322. inherited a_load_const_cgpara(list,size,a,cgpara);
  1323. end;
  1324. procedure tcg8086.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);
  1325. procedure pushdata(paraloc:pcgparalocation;ofs:tcgint);
  1326. var
  1327. pushsize : tcgsize;
  1328. opsize : topsize;
  1329. tmpreg : tregister;
  1330. href,tmpref: treference;
  1331. begin
  1332. if not assigned(paraloc) then
  1333. exit;
  1334. if (paraloc^.loc<>LOC_REFERENCE) or
  1335. (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
  1336. (tcgsize2size[paraloc^.size]>4) then
  1337. internalerror(200501162);
  1338. { Pushes are needed in reverse order, add the size of the
  1339. current location to the offset where to load from. This
  1340. prevents wrong calculations for the last location when
  1341. the size is not a power of 2 }
  1342. if assigned(paraloc^.next) then
  1343. pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
  1344. { Push the data starting at ofs }
  1345. href:=r;
  1346. inc(href.offset,ofs);
  1347. if tcgsize2size[paraloc^.size]>cgpara.alignment then
  1348. pushsize:=paraloc^.size
  1349. else
  1350. pushsize:=int_cgsize(cgpara.alignment);
  1351. opsize:=TCgsize2opsize[pushsize];
  1352. { for go32v2 we obtain OS_F32,
  1353. but pushs is not valid, we need pushl }
  1354. if opsize=S_FS then
  1355. opsize:=S_W;
  1356. if tcgsize2size[paraloc^.size]<cgpara.alignment then
  1357. begin
  1358. tmpreg:=getintregister(list,pushsize);
  1359. a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  1360. list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
  1361. end
  1362. else
  1363. begin
  1364. make_simple_ref(list,href);
  1365. if tcgsize2size[pushsize] > 2 then
  1366. begin
  1367. tmpref := href;
  1368. Inc(tmpref.offset, 2);
  1369. list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[int_cgsize(tcgsize2size[pushsize]-2)],tmpref));
  1370. end;
  1371. list.concat(taicpu.op_ref(A_PUSH,opsize,href));
  1372. end;
  1373. end;
  1374. var
  1375. len : tcgint;
  1376. href : treference;
  1377. begin
  1378. { cgpara.size=OS_NO requires a copy on the stack }
  1379. if use_push(cgpara) then
  1380. begin
  1381. { Record copy? }
  1382. if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
  1383. begin
  1384. cgpara.check_simple_location;
  1385. len:=align(cgpara.intsize,cgpara.alignment);
  1386. g_stackpointer_alloc(list,len);
  1387. reference_reset_base(href,NR_STACK_POINTER_REG,0,ctempposinvalid,4,[]);
  1388. g_concatcopy(list,r,href,len);
  1389. end
  1390. else
  1391. begin
  1392. if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
  1393. internalerror(200501161);
  1394. { We need to push the data in reverse order,
  1395. therefor we use a recursive algorithm }
  1396. pushdata(cgpara.location,0);
  1397. end
  1398. end
  1399. else
  1400. inherited a_load_ref_cgpara(list,size,r,cgpara);
  1401. end;
  1402. procedure tcg8086.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);
  1403. var
  1404. tmpreg : tregister;
  1405. tmpref : treference;
  1406. begin
  1407. with r do
  1408. begin
  1409. if use_push(cgpara) then
  1410. begin
  1411. if tcgsize2size[cgpara.Size] > 2 then
  1412. begin
  1413. if tcgsize2size[cgpara.Size] <> 4 then
  1414. internalerror(2014032401);
  1415. if cgpara.location^.Next = nil then
  1416. begin
  1417. if tcgsize2size[cgpara.location^.size] <> 4 then
  1418. internalerror(2014032401);
  1419. end
  1420. else
  1421. begin
  1422. if tcgsize2size[cgpara.location^.size] <> 2 then
  1423. internalerror(2014032401);
  1424. if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
  1425. internalerror(2014032401);
  1426. if cgpara.location^.Next^.Next <> nil then
  1427. internalerror(2014032401);
  1428. end;
  1429. if cgpara.alignment > 4 then
  1430. internalerror(2014032401);
  1431. if segment<>NR_NO then
  1432. begin
  1433. list.concat(Taicpu.op_reg(A_PUSH,S_W,segment));
  1434. tmpref:=r;
  1435. tmpref.segment:=NR_NO;
  1436. tmpreg:=getaddressregister(list);
  1437. a_loadaddr_ref_reg(list,tmpref,tmpreg);
  1438. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1439. end
  1440. else
  1441. begin
  1442. if (base=NR_NO) and (index=NR_NO) then
  1443. begin
  1444. if assigned(symbol) then
  1445. begin
  1446. tmpref:=r;
  1447. tmpref.refaddr:=addr_seg;
  1448. tmpref.offset:=0;
  1449. if current_settings.cputype < cpu_186 then
  1450. begin
  1451. tmpreg:=getaddressregister(list);
  1452. a_load_ref_reg(list,OS_16,OS_16,tmpref,tmpreg);
  1453. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1454. end
  1455. else
  1456. list.concat(Taicpu.Op_ref(A_PUSH,S_W,tmpref));
  1457. if current_settings.cputype < cpu_186 then
  1458. begin
  1459. tmpreg:=getaddressregister(list);
  1460. a_loadaddr_ref_reg(list,r,tmpreg);
  1461. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1462. end
  1463. else
  1464. list.concat(Taicpu.Op_sym_ofs(A_PUSH,S_W,symbol,offset));
  1465. end
  1466. else
  1467. internalerror(2014032402);
  1468. end
  1469. else if assigned(symbol) then
  1470. begin
  1471. reference_reset_symbol(tmpref,r.symbol,0,r.alignment,r.volatility);
  1472. tmpref.refaddr:=addr_seg;
  1473. if current_settings.cputype < cpu_186 then
  1474. begin
  1475. tmpreg:=getaddressregister(list);
  1476. a_load_ref_reg(list,OS_16,OS_16,tmpref,tmpreg);
  1477. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1478. end
  1479. else
  1480. list.concat(Taicpu.Op_ref(A_PUSH,S_W,tmpref));
  1481. tmpreg:=getaddressregister(list);
  1482. a_loadaddr_ref_reg(list,r,tmpreg);
  1483. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1484. end
  1485. else if base=NR_BP then
  1486. begin
  1487. list.concat(Taicpu.op_reg(A_PUSH,S_W,NR_SS));
  1488. tmpreg:=getaddressregister(list);
  1489. a_loadaddr_ref_reg(list,r,tmpreg);
  1490. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1491. end
  1492. else
  1493. internalerror(2014032403);
  1494. end;
  1495. end
  1496. else
  1497. begin
  1498. cgpara.check_simple_location;
  1499. tmpref:=r;
  1500. tmpref.segment:=NR_NO;
  1501. with tmpref do
  1502. begin
  1503. if (base=NR_NO) and (index=NR_NO) then
  1504. begin
  1505. if assigned(symbol) then
  1506. begin
  1507. if current_settings.cputype < cpu_186 then
  1508. begin
  1509. tmpreg:=getaddressregister(list);
  1510. a_loadaddr_ref_reg(list,tmpref,tmpreg);
  1511. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1512. end
  1513. else
  1514. list.concat(Taicpu.Op_sym_ofs(A_PUSH,S_W,symbol,offset));
  1515. end
  1516. else
  1517. push_const(list,OS_16,offset);
  1518. end
  1519. else if (base=NR_NO) and (index<>NR_NO) and
  1520. (offset=0) and (scalefactor=0) and (symbol=nil) then
  1521. list.concat(Taicpu.Op_reg(A_PUSH,S_W,index))
  1522. else if (base<>NR_NO) and (index=NR_NO) and
  1523. (offset=0) and (symbol=nil) then
  1524. list.concat(Taicpu.Op_reg(A_PUSH,S_W,base))
  1525. else
  1526. begin
  1527. tmpreg:=getaddressregister(list);
  1528. a_loadaddr_ref_reg(list,tmpref,tmpreg);
  1529. list.concat(taicpu.op_reg(A_PUSH,S_W,tmpreg));
  1530. end;
  1531. end;
  1532. end;
  1533. end
  1534. else
  1535. inherited a_loadaddr_ref_cgpara(list,r,cgpara);
  1536. end;
  1537. end;
  1538. procedure tcg8086.a_load_const_reg(list : TAsmList; tosize: tcgsize; a : tcgint;reg : tregister);
  1539. begin
  1540. check_register_size(tosize,reg);
  1541. if tosize in [OS_S32,OS_32] then
  1542. begin
  1543. list.concat(taicpu.op_const_reg(A_MOV,S_W,longint(a and $ffff),reg));
  1544. list.concat(taicpu.op_const_reg(A_MOV,S_W,longint(a shr 16),GetNextReg(reg)));
  1545. end
  1546. else
  1547. list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[tosize],a,reg));
  1548. end;
  1549. procedure tcg8086.a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);
  1550. var
  1551. tmpref : treference;
  1552. begin
  1553. tmpref:=ref;
  1554. make_simple_ref(list,tmpref);
  1555. if tosize in [OS_S32,OS_32] then
  1556. begin
  1557. a_load_const_ref(list,OS_16,longint(a and $ffff),tmpref);
  1558. inc(tmpref.offset,2);
  1559. a_load_const_ref(list,OS_16,longint(a shr 16),tmpref);
  1560. end
  1561. else
  1562. list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[tosize],a,tmpref));
  1563. end;
  1564. procedure tcg8086.a_load_reg_ref(list : TAsmList;fromsize,tosize: tcgsize; reg : tregister;const ref : treference);
  1565. var
  1566. tmpreg : tregister;
  1567. tmpref : treference;
  1568. begin
  1569. tmpref:=ref;
  1570. make_simple_ref(list,tmpref);
  1571. check_register_size(fromsize,reg);
  1572. case tosize of
  1573. OS_8,OS_S8:
  1574. if fromsize in [OS_8,OS_S8] then
  1575. list.concat(taicpu.op_reg_ref(A_MOV, S_B, reg, tmpref))
  1576. else
  1577. internalerror(2013030310);
  1578. OS_16,OS_S16:
  1579. case fromsize of
  1580. OS_8,OS_S8:
  1581. begin
  1582. tmpreg:=getintregister(list,tosize);
  1583. a_load_reg_reg(list,fromsize,tosize,reg,tmpreg);
  1584. a_load_reg_ref(list,tosize,tosize,tmpreg,tmpref);
  1585. end;
  1586. OS_16,OS_S16:
  1587. begin
  1588. list.concat(taicpu.op_reg_ref(A_MOV, S_W, reg, tmpref));
  1589. end;
  1590. else
  1591. internalerror(2013030312);
  1592. end;
  1593. OS_32,OS_S32:
  1594. case fromsize of
  1595. OS_8,OS_S8,OS_S16:
  1596. begin
  1597. tmpreg:=getintregister(list,tosize);
  1598. a_load_reg_reg(list,fromsize,tosize,reg,tmpreg);
  1599. a_load_reg_ref(list,tosize,tosize,tmpreg,tmpref);
  1600. end;
  1601. OS_16:
  1602. begin
  1603. list.concat(taicpu.op_reg_ref(A_MOV, S_W, reg, tmpref));
  1604. inc(tmpref.offset, 2);
  1605. list.concat(taicpu.op_const_ref(A_MOV, S_W, 0, tmpref));
  1606. end;
  1607. OS_32,OS_S32:
  1608. begin
  1609. list.concat(taicpu.op_reg_ref(A_MOV, S_W, reg, tmpref));
  1610. inc(tmpref.offset, 2);
  1611. list.concat(taicpu.op_reg_ref(A_MOV, S_W, GetNextReg(reg), tmpref));
  1612. end;
  1613. else
  1614. internalerror(2013030313);
  1615. end;
  1616. else
  1617. internalerror(2013030311);
  1618. end;
  1619. end;
  1620. procedure tcg8086.a_load_ref_reg_internal(list : TAsmList;fromsize,tosize: tcgsize;const ref : treference;reg : tregister;isdirect:boolean);
  1621. procedure add_mov(instr: Taicpu);
  1622. begin
  1623. { Notify the register allocator that we have written a move instruction so
  1624. it can try to eliminate it. }
  1625. if (instr.oper[0]^.reg<>current_procinfo.framepointer) and (instr.oper[0]^.reg<>NR_STACK_POINTER_REG) then
  1626. add_move_instruction(instr);
  1627. list.concat(instr);
  1628. end;
  1629. var
  1630. tmpref : treference;
  1631. begin
  1632. tmpref:=ref;
  1633. make_simple_ref(list,tmpref,isdirect);
  1634. check_register_size(tosize,reg);
  1635. if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
  1636. internalerror(2011021307);
  1637. { if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
  1638. fromsize:=tosize;}
  1639. case tosize of
  1640. OS_8,OS_S8:
  1641. if fromsize in [OS_8,OS_S8] then
  1642. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, reg))
  1643. else
  1644. internalerror(2013030210);
  1645. OS_16,OS_S16:
  1646. case fromsize of
  1647. OS_8:
  1648. begin
  1649. if current_settings.cputype>=cpu_386 then
  1650. list.concat(taicpu.op_ref_reg(A_MOVZX, S_BW, tmpref, reg))
  1651. else
  1652. begin
  1653. reg := makeregsize(list, reg, OS_8);
  1654. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, reg));
  1655. setsubreg(reg, R_SUBH);
  1656. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg));
  1657. makeregsize(list, reg, OS_16);
  1658. end;
  1659. end;
  1660. OS_S8:
  1661. begin
  1662. if current_settings.cputype>=cpu_386 then
  1663. list.concat(taicpu.op_ref_reg(A_MOVSX, S_BW, tmpref, reg))
  1664. else
  1665. begin
  1666. getcpuregister(list, NR_AX);
  1667. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, NR_AL));
  1668. list.concat(taicpu.op_none(A_CBW));
  1669. ungetcpuregister(list, NR_AX);
  1670. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg));
  1671. end;
  1672. end;
  1673. OS_16,OS_S16:
  1674. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, reg));
  1675. else
  1676. internalerror(2013030212);
  1677. end;
  1678. OS_32,OS_S32:
  1679. case fromsize of
  1680. OS_8:
  1681. begin
  1682. list.concat(taicpu.op_const_reg(A_MOV,S_W,0,GetNextReg(reg)));
  1683. if current_settings.cputype>=cpu_386 then
  1684. list.concat(taicpu.op_ref_reg(A_MOVZX, S_BW, tmpref, reg))
  1685. else
  1686. begin
  1687. reg := makeregsize(list, reg, OS_8);
  1688. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, reg));
  1689. setsubreg(reg, R_SUBH);
  1690. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg));
  1691. makeregsize(list, reg, OS_16);
  1692. end;
  1693. end;
  1694. OS_S8:
  1695. begin
  1696. getcpuregister(list, NR_AX);
  1697. list.concat(taicpu.op_ref_reg(A_MOV, S_B, tmpref, NR_AL));
  1698. getcpuregister(list, NR_DX);
  1699. list.concat(taicpu.op_none(A_CBW));
  1700. list.concat(taicpu.op_none(A_CWD));
  1701. ungetcpuregister(list, NR_AX);
  1702. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg));
  1703. ungetcpuregister(list, NR_DX);
  1704. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg)));
  1705. end;
  1706. OS_16:
  1707. begin
  1708. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, reg));
  1709. list.concat(taicpu.op_const_reg(A_MOV,S_W,0,GetNextReg(reg)));
  1710. end;
  1711. OS_S16:
  1712. begin
  1713. getcpuregister(list, NR_AX);
  1714. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, NR_AX));
  1715. getcpuregister(list, NR_DX);
  1716. list.concat(taicpu.op_none(A_CWD));
  1717. ungetcpuregister(list, NR_AX);
  1718. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg));
  1719. ungetcpuregister(list, NR_DX);
  1720. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg)));
  1721. end;
  1722. OS_32,OS_S32:
  1723. begin
  1724. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, reg));
  1725. inc(tmpref.offset, 2);
  1726. list.concat(taicpu.op_ref_reg(A_MOV, S_W, tmpref, GetNextReg(reg)));
  1727. end;
  1728. else
  1729. internalerror(2013030213);
  1730. end;
  1731. else
  1732. internalerror(2013030211);
  1733. end;
  1734. end;
  1735. procedure tcg8086.a_load_reg_reg(list : TAsmList;fromsize,tosize: tcgsize;reg1,reg2 : tregister);
  1736. procedure add_mov(instr: Taicpu);
  1737. begin
  1738. { Notify the register allocator that we have written a move instruction so
  1739. it can try to eliminate it. }
  1740. if (instr.oper[0]^.reg<>current_procinfo.framepointer) and (instr.oper[0]^.reg<>NR_STACK_POINTER_REG) then
  1741. add_move_instruction(instr);
  1742. list.concat(instr);
  1743. end;
  1744. begin
  1745. check_register_size(fromsize,reg1);
  1746. check_register_size(tosize,reg2);
  1747. if tcgsize2size[fromsize]>tcgsize2size[tosize] then
  1748. begin
  1749. if tosize in [OS_32, OS_S32] then
  1750. internalerror(2013031801);
  1751. reg1:=makeregsize(list,reg1,tosize);
  1752. fromsize:=tosize;
  1753. end;
  1754. if (reg1<>reg2) or (fromsize<>tosize) then
  1755. begin
  1756. case tosize of
  1757. OS_8,OS_S8:
  1758. if fromsize in [OS_8,OS_S8] then
  1759. begin
  1760. if reg1<>reg2 then
  1761. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, reg2));
  1762. end
  1763. else
  1764. internalerror(2013030210);
  1765. OS_16,OS_S16:
  1766. case fromsize of
  1767. OS_8:
  1768. begin
  1769. if current_settings.cputype>=cpu_386 then
  1770. add_mov(taicpu.op_reg_reg(A_MOVZX, S_BW, reg1, reg2))
  1771. else
  1772. begin
  1773. reg2 := makeregsize(list, reg2, OS_8);
  1774. if reg1<>reg2 then
  1775. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, reg2));
  1776. setsubreg(reg2,R_SUBH);
  1777. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg2));
  1778. makeregsize(list, reg2, OS_16);
  1779. end;
  1780. end;
  1781. OS_S8:
  1782. begin
  1783. if current_settings.cputype>=cpu_386 then
  1784. add_mov(taicpu.op_reg_reg(A_MOVSX, S_BW, reg1, reg2))
  1785. else
  1786. begin
  1787. getcpuregister(list, NR_AX);
  1788. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, NR_AL));
  1789. list.concat(taicpu.op_none(A_CBW));
  1790. ungetcpuregister(list, NR_AX);
  1791. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg2));
  1792. end;
  1793. end;
  1794. OS_16,OS_S16:
  1795. begin
  1796. if reg1<>reg2 then
  1797. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, reg2));
  1798. end
  1799. else
  1800. internalerror(2013030212);
  1801. end;
  1802. OS_32,OS_S32:
  1803. case fromsize of
  1804. OS_8:
  1805. begin
  1806. list.concat(taicpu.op_const_reg(A_MOV, S_W, 0, GetNextReg(reg2)));
  1807. if current_settings.cputype>=cpu_386 then
  1808. add_mov(taicpu.op_reg_reg(A_MOVZX, S_BW, reg1, reg2))
  1809. else
  1810. begin
  1811. reg2 := makeregsize(list, reg2, OS_8);
  1812. if reg1<>reg2 then
  1813. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, reg2));
  1814. setsubreg(reg2,R_SUBH);
  1815. list.concat(taicpu.op_const_reg(A_MOV, S_B, 0, reg2));
  1816. makeregsize(list, reg2, OS_16);
  1817. end;
  1818. end;
  1819. OS_S8:
  1820. begin
  1821. getcpuregister(list, NR_AX);
  1822. add_mov(taicpu.op_reg_reg(A_MOV, S_B, reg1, NR_AL));
  1823. getcpuregister(list, NR_DX);
  1824. list.concat(taicpu.op_none(A_CBW));
  1825. list.concat(taicpu.op_none(A_CWD));
  1826. ungetcpuregister(list, NR_AX);
  1827. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg2));
  1828. ungetcpuregister(list, NR_DX);
  1829. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg2)));
  1830. end;
  1831. OS_16:
  1832. begin
  1833. if reg1<>reg2 then
  1834. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, reg2));
  1835. list.concat(taicpu.op_const_reg(A_MOV,S_W,0,GetNextReg(reg2)));
  1836. end;
  1837. OS_S16:
  1838. begin
  1839. getcpuregister(list, NR_AX);
  1840. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, NR_AX));
  1841. getcpuregister(list, NR_DX);
  1842. list.concat(taicpu.op_none(A_CWD));
  1843. ungetcpuregister(list, NR_AX);
  1844. if reg1<>reg2 then
  1845. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_AX, reg2));
  1846. ungetcpuregister(list, NR_DX);
  1847. add_mov(taicpu.op_reg_reg(A_MOV, S_W, NR_DX, GetNextReg(reg2)));
  1848. end;
  1849. OS_32,OS_S32:
  1850. begin
  1851. if reg1<>reg2 then
  1852. begin
  1853. add_mov(taicpu.op_reg_reg(A_MOV, S_W, reg1, reg2));
  1854. add_mov(taicpu.op_reg_reg(A_MOV, S_W, GetNextReg(reg1), GetNextReg(reg2)));
  1855. end;
  1856. end;
  1857. else
  1858. internalerror(2013030213);
  1859. end;
  1860. else
  1861. internalerror(2013030211);
  1862. end;
  1863. end;
  1864. end;
  1865. procedure tcg8086.a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
  1866. var
  1867. hl_skip: TAsmLabel;
  1868. begin
  1869. if size in [OS_32, OS_S32] then
  1870. begin
  1871. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1872. if (longint(a shr 16) = 0) then
  1873. list.concat(taicpu.op_reg_reg(A_TEST,S_W,GetNextReg(reg),GetNextReg(reg)))
  1874. else
  1875. list.concat(taicpu.op_const_reg(A_CMP,S_W,longint(a shr 16),GetNextReg(reg)));
  1876. current_asmdata.getjumplabel(hl_skip);
  1877. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1878. if (longint(a and $ffff) = 0) then
  1879. list.concat(taicpu.op_reg_reg(A_TEST,S_W,reg,reg))
  1880. else
  1881. list.concat(taicpu.op_const_reg(A_CMP,S_W,longint(a and $ffff),reg));
  1882. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1883. a_label(list,hl_skip);
  1884. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1885. end
  1886. else
  1887. inherited a_cmp_const_reg_label(list, size, cmp_op, a, reg, l);
  1888. end;
  1889. procedure tcg8086.a_cmp_const_ref_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; a: tcgint; const ref: treference; l: tasmlabel);
  1890. var
  1891. tmpref: treference;
  1892. hl_skip: TAsmLabel;
  1893. begin
  1894. if size in [OS_32, OS_S32] then
  1895. begin
  1896. tmpref:=ref;
  1897. make_simple_ref(list,tmpref);
  1898. inc(tmpref.offset,2);
  1899. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1900. list.concat(taicpu.op_const_ref(A_CMP,S_W,longint(a shr 16),tmpref));
  1901. current_asmdata.getjumplabel(hl_skip);
  1902. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1903. dec(tmpref.offset,2);
  1904. list.concat(taicpu.op_const_ref(A_CMP,S_W,longint(a and $ffff),tmpref));
  1905. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1906. a_label(list,hl_skip);
  1907. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1908. end
  1909. else
  1910. inherited a_cmp_const_ref_label(list, size, cmp_op, a, ref, l);
  1911. end;
  1912. procedure tcg8086.a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  1913. var
  1914. hl_skip: TAsmLabel;
  1915. begin
  1916. if size in [OS_32, OS_S32] then
  1917. begin
  1918. check_register_size(size,reg1);
  1919. check_register_size(size,reg2);
  1920. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1921. list.concat(taicpu.op_reg_reg(A_CMP,S_W,GetNextReg(reg1),GetNextReg(reg2)));
  1922. current_asmdata.getjumplabel(hl_skip);
  1923. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1924. list.concat(taicpu.op_reg_reg(A_CMP,S_W,reg1,reg2));
  1925. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1926. a_label(list,hl_skip);
  1927. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1928. end
  1929. else
  1930. inherited a_cmp_reg_reg_label(list, size, cmp_op, reg1, reg2, l);
  1931. end;
  1932. procedure tcg8086.a_cmp_ref_reg_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel);
  1933. var
  1934. tmpref: treference;
  1935. hl_skip: TAsmLabel;
  1936. begin
  1937. if size in [OS_32, OS_S32] then
  1938. begin
  1939. tmpref:=ref;
  1940. make_simple_ref(list,tmpref);
  1941. check_register_size(size,reg);
  1942. inc(tmpref.offset,2);
  1943. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1944. list.concat(taicpu.op_ref_reg(A_CMP,S_W,tmpref,GetNextReg(reg)));
  1945. current_asmdata.getjumplabel(hl_skip);
  1946. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1947. dec(tmpref.offset,2);
  1948. list.concat(taicpu.op_ref_reg(A_CMP,S_W,tmpref,reg));
  1949. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1950. a_label(list,hl_skip);
  1951. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1952. end
  1953. else
  1954. inherited a_cmp_ref_reg_label(list, size, cmp_op, ref, reg, l);
  1955. end;
  1956. procedure tcg8086.a_cmp_reg_ref_label(list: TAsmList; size: tcgsize; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel);
  1957. var
  1958. tmpref: treference;
  1959. hl_skip: TAsmLabel;
  1960. begin
  1961. if size in [OS_32, OS_S32] then
  1962. begin
  1963. tmpref:=ref;
  1964. make_simple_ref(list,tmpref);
  1965. check_register_size(size,reg);
  1966. inc(tmpref.offset,2);
  1967. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  1968. list.concat(taicpu.op_reg_ref(A_CMP,S_W,GetNextReg(reg),tmpref));
  1969. current_asmdata.getjumplabel(hl_skip);
  1970. gen_cmp32_jmp1(list, cmp_op, hl_skip, l);
  1971. dec(tmpref.offset,2);
  1972. list.concat(taicpu.op_reg_ref(A_CMP,S_W,reg,tmpref));
  1973. gen_cmp32_jmp2(list, cmp_op, hl_skip, l);
  1974. a_label(list,hl_skip);
  1975. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  1976. end
  1977. else
  1978. inherited a_cmp_reg_ref_label(list, size, cmp_op, reg, ref, l);
  1979. end;
  1980. procedure tcg8086.gen_cmp32_jmp1(list: TAsmList; cmp_op: topcmp; l_skip, l_target: TAsmLabel);
  1981. begin
  1982. case cmp_op of
  1983. OC_EQ:
  1984. a_jmp_cond(list, OC_NE, l_skip);
  1985. OC_NE:
  1986. a_jmp_cond(list, OC_NE, l_target);
  1987. OC_GT,OC_GTE:
  1988. begin
  1989. a_jmp_cond(list, OC_GT, l_target);
  1990. a_jmp_cond(list, OC_LT, l_skip);
  1991. end;
  1992. OC_LT,OC_LTE:
  1993. begin
  1994. a_jmp_cond(list, OC_LT, l_target);
  1995. a_jmp_cond(list, OC_GT, l_skip);
  1996. end;
  1997. OC_B,OC_BE:
  1998. begin
  1999. a_jmp_cond(list, OC_B, l_target);
  2000. a_jmp_cond(list, OC_A, l_skip);
  2001. end;
  2002. OC_A,OC_AE:
  2003. begin
  2004. a_jmp_cond(list, OC_A, l_target);
  2005. a_jmp_cond(list, OC_B, l_skip);
  2006. end;
  2007. else
  2008. internalerror(2014010305);
  2009. end;
  2010. end;
  2011. procedure tcg8086.gen_cmp32_jmp2(list: TAsmList; cmp_op: topcmp; l_skip, l_target: TAsmLabel);
  2012. begin
  2013. case cmp_op of
  2014. OC_EQ:
  2015. a_jmp_cond(list, OC_EQ, l_target);
  2016. OC_GT:
  2017. a_jmp_cond(list, OC_A, l_target);
  2018. OC_LT:
  2019. a_jmp_cond(list, OC_B, l_target);
  2020. OC_GTE:
  2021. a_jmp_cond(list, OC_AE, l_target);
  2022. OC_LTE:
  2023. a_jmp_cond(list, OC_BE, l_target);
  2024. OC_NE:
  2025. a_jmp_cond(list, OC_NE, l_target);
  2026. OC_BE:
  2027. a_jmp_cond(list, OC_BE, l_target);
  2028. OC_B:
  2029. a_jmp_cond(list, OC_B, l_target);
  2030. OC_AE:
  2031. a_jmp_cond(list, OC_AE, l_target);
  2032. OC_A:
  2033. a_jmp_cond(list, OC_A, l_target);
  2034. else
  2035. internalerror(2014010306);
  2036. end;
  2037. end;
  2038. procedure tcg8086.g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);
  2039. var
  2040. ai : taicpu;
  2041. hreg16 : tregister;
  2042. hl_skip: TAsmLabel;
  2043. invf: TResFlags;
  2044. tmpsize: TCgSize;
  2045. tmpopsize: topsize;
  2046. begin
  2047. { optimized case for the carry flag, using ADC/RCL }
  2048. if f in [F_C,F_B,F_FB] then
  2049. begin
  2050. case size of
  2051. OS_8,OS_S8:
  2052. begin
  2053. tmpsize:=OS_8;
  2054. tmpopsize:=S_B;
  2055. end;
  2056. OS_16,OS_S16,OS_32,OS_S32:
  2057. begin
  2058. tmpsize:=OS_16;
  2059. tmpopsize:=S_W;
  2060. end;
  2061. else
  2062. internalerror(2013123101);
  2063. end;
  2064. list.concat(Taicpu.op_const_reg(A_MOV, tmpopsize, 0, reg));
  2065. hl_skip:=nil;
  2066. if f=F_FB then
  2067. begin
  2068. current_asmdata.getjumplabel(hl_skip);
  2069. ai:=Taicpu.op_sym(A_Jcc,S_NO,hl_skip);
  2070. ai.SetCondition(C_P);
  2071. ai.is_jmp:=true;
  2072. list.concat(ai);
  2073. end;
  2074. { RCL is faster than ADC on 8086/8088. On the 80286, it is
  2075. equally fast and it also has the same size. In these cases,
  2076. we still prefer it over ADC, because it's a better choice in
  2077. case the register is spilled. }
  2078. if (cs_opt_size in current_settings.optimizerswitches) or
  2079. (current_settings.optimizecputype<=cpu_286) then
  2080. list.concat(Taicpu.op_const_reg(A_RCL, tmpopsize, 1, reg))
  2081. else
  2082. { ADC is much faster on the 386. }
  2083. list.concat(Taicpu.op_reg_reg(A_ADC, tmpopsize, reg, reg));
  2084. if f=F_FB then
  2085. a_label(list,hl_skip);
  2086. a_load_reg_reg(list,tmpsize,size,reg,reg);
  2087. end
  2088. { optimized case for the inverted carry flag, using SBB }
  2089. else if f in [F_NC,F_AE,F_FAE] then
  2090. begin
  2091. case size of
  2092. OS_8,OS_S8:
  2093. begin
  2094. tmpsize:=OS_8;
  2095. list.concat(Taicpu.op_const_reg(A_MOV, S_B, 1, reg));
  2096. list.concat(Taicpu.op_const_reg(A_SBB, S_B, 0, reg));
  2097. end;
  2098. OS_16,OS_S16,OS_32,OS_S32:
  2099. begin
  2100. tmpsize:=OS_16;
  2101. list.concat(Taicpu.op_const_reg(A_MOV, S_W, 1, reg));
  2102. list.concat(Taicpu.op_const_reg(A_SBB, S_W, 0, reg));
  2103. end;
  2104. else
  2105. internalerror(2013123101);
  2106. end;
  2107. a_load_reg_reg(list,tmpsize,size,reg,reg);
  2108. end
  2109. else
  2110. begin
  2111. invf := f;
  2112. inverse_flags(invf);
  2113. case size of
  2114. OS_8,OS_S8:
  2115. begin
  2116. tmpsize:=OS_8;
  2117. list.concat(Taicpu.op_const_reg(A_MOV, S_B, 0, reg));
  2118. end;
  2119. OS_16,OS_S16,OS_32,OS_S32:
  2120. begin
  2121. tmpsize:=OS_16;
  2122. list.concat(Taicpu.op_const_reg(A_MOV, S_W, 0, reg));
  2123. end;
  2124. else
  2125. internalerror(2013123101);
  2126. end;
  2127. current_asmdata.getjumplabel(hl_skip);
  2128. { we can't just forward invf to a_jmp_flags for FA,FAE,FB and FBE, because
  2129. in the case of NaNs:
  2130. not(F_FA )<>F_FBE
  2131. not(F_FAE)<>F_FB
  2132. not(F_FB )<>F_FAE
  2133. not(F_FBE)<>F_FA
  2134. }
  2135. case f of
  2136. F_FA:
  2137. invf:=FPUFlags2Flags[invf];
  2138. F_FAE,F_FB:
  2139. { F_FAE and F_FB are handled above, using ADC/RCL/SBB }
  2140. internalerror(2015102101);
  2141. F_FBE:
  2142. begin
  2143. ai:=Taicpu.op_sym(A_Jcc,S_NO,hl_skip);
  2144. ai.SetCondition(C_P);
  2145. ai.is_jmp:=true;
  2146. list.concat(ai);
  2147. invf:=FPUFlags2Flags[invf];
  2148. end;
  2149. end;
  2150. a_jmp_flags(list,invf,hl_skip);
  2151. { 16-bit INC is shorter than 8-bit }
  2152. hreg16:=makeregsize(list,reg,OS_16);
  2153. list.concat(Taicpu.op_reg(A_INC, S_W, hreg16));
  2154. makeregsize(list,hreg16,tmpsize);
  2155. a_label(list,hl_skip);
  2156. a_load_reg_reg(list,tmpsize,size,reg,reg);
  2157. end;
  2158. end;
  2159. procedure tcg8086.g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref: TReference);
  2160. var
  2161. tmpreg : tregister;
  2162. tmpregsize: TCgSize;
  2163. tmpref: treference;
  2164. begin
  2165. if size in [OS_8,OS_S8,OS_16,OS_S16] then
  2166. tmpregsize:=size
  2167. else
  2168. tmpregsize:=OS_16;
  2169. tmpreg:=getintregister(list,tmpregsize);
  2170. g_flags2reg(list,tmpregsize,f,tmpreg);
  2171. tmpref:=ref;
  2172. make_simple_ref(list,tmpref);
  2173. if size in [OS_64,OS_S64] then
  2174. begin
  2175. a_load_reg_ref(list,tmpregsize,OS_32,tmpreg,tmpref);
  2176. inc(tmpref.offset,4);
  2177. a_load_const_ref(list,OS_32,0,tmpref);
  2178. end
  2179. else
  2180. a_load_reg_ref(list,tmpregsize,size,tmpreg,tmpref);
  2181. end;
  2182. procedure tcg8086.g_stackpointer_alloc(list : TAsmList;localsize: longint);
  2183. begin
  2184. if cs_check_stack in current_settings.localswitches then
  2185. begin
  2186. cg.getcpuregister(list,NR_AX);
  2187. cg.a_load_const_reg(list,OS_16, localsize,NR_AX);
  2188. cg.a_call_name(list,'FPC_STACKCHECK_I8086',false);
  2189. cg.ungetcpuregister(list, NR_AX);
  2190. end;
  2191. if localsize>0 then
  2192. list.concat(Taicpu.Op_const_reg(A_SUB,S_W,localsize,NR_STACK_POINTER_REG));
  2193. end;
  2194. procedure tcg8086.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
  2195. var
  2196. stacksize : longint;
  2197. ret_instr: TAsmOp;
  2198. sp_moved : boolean;
  2199. procedure maybe_move_sp;
  2200. var
  2201. ref : treference;
  2202. begin
  2203. if sp_moved then
  2204. exit;
  2205. if not(pi_has_open_array_parameter in current_procinfo.flags) then
  2206. exit;
  2207. { Restore SP position before SP change }
  2208. if current_settings.x86memorymodel=mm_huge then
  2209. stacksize:=stacksize + 2;
  2210. reference_reset_base(ref,NR_BP,-stacksize,ctempposinvalid,2,[]);
  2211. list.concat(Taicpu.op_ref_reg(A_LEA,S_W,ref,NR_SP));
  2212. sp_moved:=true;
  2213. end;
  2214. begin
  2215. if is_proc_far(current_procinfo.procdef) then
  2216. ret_instr:=A_RETF
  2217. else
  2218. ret_instr:=A_RET;
  2219. { MMX needs to call EMMS }
  2220. if assigned(rg[R_MMXREGISTER]) and
  2221. (rg[R_MMXREGISTER].uses_registers) then
  2222. list.concat(Taicpu.op_none(A_EMMS,S_NO));
  2223. sp_moved:=false;
  2224. { remove stackframe }
  2225. if not nostackframe then
  2226. begin
  2227. stacksize:=current_procinfo.calc_stackframe_size;
  2228. if (target_info.stackalign>4) and
  2229. ((stacksize <> 0) or
  2230. (pi_do_call in current_procinfo.flags) or
  2231. { can't detect if a call in this case -> use nostackframe }
  2232. { if you (think you) know what you are doing }
  2233. (po_assembler in current_procinfo.procdef.procoptions)) then
  2234. stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint);
  2235. if (po_exports in current_procinfo.procdef.procoptions) and
  2236. (target_info.system=system_i8086_win16) then
  2237. begin
  2238. maybe_move_sp;
  2239. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DI));
  2240. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_SI));
  2241. end;
  2242. if ((current_settings.x86memorymodel=mm_huge) and
  2243. not (po_interrupt in current_procinfo.procdef.procoptions)) or
  2244. ((po_exports in current_procinfo.procdef.procoptions) and
  2245. (target_info.system=system_i8086_win16)) then
  2246. begin
  2247. maybe_move_sp;
  2248. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
  2249. end;
  2250. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  2251. begin
  2252. if (stacksize<>0) then
  2253. cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
  2254. end
  2255. else
  2256. begin
  2257. generate_leave(list);
  2258. if ((ts_x86_far_procs_push_odd_bp in current_settings.targetswitches) or
  2259. ((po_exports in current_procinfo.procdef.procoptions) and
  2260. (target_info.system=system_i8086_win16))) and
  2261. is_proc_far(current_procinfo.procdef) then
  2262. cg.a_op_const_reg(list,OP_SUB,OS_ADDR,1,current_procinfo.framepointer);
  2263. end;
  2264. list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
  2265. end;
  2266. { return from interrupt }
  2267. if po_interrupt in current_procinfo.procdef.procoptions then
  2268. begin
  2269. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_ES));
  2270. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
  2271. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DI));
  2272. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_SI));
  2273. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DX));
  2274. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_CX));
  2275. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_BX));
  2276. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_AX));
  2277. list.concat(Taicpu.Op_none(A_IRET,S_NO));
  2278. end
  2279. { Routines with the poclearstack flag set use only a ret }
  2280. else if (current_procinfo.procdef.proccalloption in clearstack_pocalls) and
  2281. (not paramanager.use_fixed_stack) then
  2282. begin
  2283. { complex return values are removed from stack in C code PM }
  2284. { but not on win32 }
  2285. { and not for safecall with hidden exceptions, because the result }
  2286. { wich contains the exception is passed in EAX }
  2287. if (target_info.system <> system_i386_win32) and
  2288. not ((current_procinfo.procdef.proccalloption = pocall_safecall) and
  2289. (tf_safecall_exceptions in target_info.flags)) and
  2290. paramanager.ret_in_param(current_procinfo.procdef.returndef,
  2291. current_procinfo.procdef) then
  2292. list.concat(Taicpu.Op_const(ret_instr,S_W,sizeof(aint)))
  2293. else
  2294. list.concat(Taicpu.Op_none(ret_instr,S_NO));
  2295. end
  2296. { ... also routines with parasize=0 }
  2297. else if (parasize=0) then
  2298. list.concat(Taicpu.Op_none(ret_instr,S_NO))
  2299. else
  2300. begin
  2301. { parameters are limited to 65535 bytes because ret allows only imm16 }
  2302. if (parasize>65535) then
  2303. CGMessage(cg_e_parasize_too_big);
  2304. list.concat(Taicpu.Op_const(ret_instr,S_W,parasize));
  2305. end;
  2306. end;
  2307. procedure tcg8086.g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);
  2308. var
  2309. power : longint;
  2310. opsize : topsize;
  2311. saved_ds: Boolean;
  2312. begin
  2313. { get stack space }
  2314. getcpuregister(list,NR_DI);
  2315. a_load_loc_reg(list,OS_INT,lenloc,NR_DI);
  2316. list.concat(Taicpu.op_reg(A_INC,S_W,NR_DI));
  2317. { Now DI contains (high+1). }
  2318. include(current_procinfo.flags, pi_has_open_array_parameter);
  2319. { special case handling for elesize=2:
  2320. set CX = (high+1) instead of CX = (high+1)*elesize.
  2321. This allows us to avoid the SHR later. }
  2322. if elesize=2 then
  2323. begin
  2324. { Now DI contains (high+1). Copy it to CX for later use. }
  2325. getcpuregister(list,NR_CX);
  2326. list.concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_DI,NR_CX));
  2327. end;
  2328. { DI := DI * elesize }
  2329. if (elesize<>1) then
  2330. begin
  2331. if ispowerof2(elesize, power) then
  2332. a_op_const_reg(list,OP_SHL,OS_16,power,NR_DI)
  2333. else
  2334. a_op_const_reg(list,OP_IMUL,OS_16,elesize,NR_DI);
  2335. end;
  2336. if elesize<>2 then
  2337. begin
  2338. { Now DI contains (high+1)*elesize. Copy it to CX for later use. }
  2339. getcpuregister(list,NR_CX);
  2340. list.concat(Taicpu.op_reg_reg(A_MOV,S_W,NR_DI,NR_CX));
  2341. end;
  2342. { If we were probing pages, EDI=(size mod pagesize) and ESP is decremented
  2343. by (size div pagesize)*pagesize, otherwise EDI=size.
  2344. Either way, subtracting EDI from ESP will set ESP to desired final value. }
  2345. list.concat(Taicpu.op_reg_reg(A_SUB,S_W,NR_DI,NR_SP));
  2346. { align stack on 2 bytes }
  2347. list.concat(Taicpu.op_const_reg(A_AND,S_W,aint($fffe),NR_SP));
  2348. { load destination, don't use a_load_reg_reg, that will add a move instruction
  2349. that can confuse the reg allocator }
  2350. list.concat(Taicpu.Op_reg_reg(A_MOV,S_W,NR_SP,NR_DI));
  2351. {$ifdef volatile_es}
  2352. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_SS));
  2353. list.concat(taicpu.op_reg(A_POP,S_W,NR_ES));
  2354. {$endif volatile_es}
  2355. { Allocate SI and load it with source }
  2356. getcpuregister(list,NR_SI);
  2357. if ((ref.segment=NR_NO) and (segment_regs_equal(NR_SS,NR_DS) or (ref.base<>NR_BP))) or
  2358. (is_segment_reg(ref.segment) and segment_regs_equal(ref.segment,NR_DS)) then
  2359. begin
  2360. hlcg.a_loadaddr_ref_reg(list,voidnearpointertype,voidnearpointertype,ref,NR_SI);
  2361. saved_ds:=false;
  2362. end
  2363. else
  2364. begin
  2365. hlcg.a_loadaddr_ref_reg(list,voidnearpointertype,voidnearpointertype,ref,NR_SI);
  2366. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DS));
  2367. saved_ds:=true;
  2368. if ref.segment<>NR_NO then
  2369. list.concat(taicpu.op_reg(A_PUSH,S_W,ref.segment))
  2370. else if ref.base=NR_BP then
  2371. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_SS))
  2372. else
  2373. internalerror(2014040403);
  2374. list.concat(taicpu.op_reg(A_POP,S_W,NR_DS));
  2375. end;
  2376. { calculate size }
  2377. opsize:=S_B;
  2378. if elesize=2 then
  2379. begin
  2380. opsize:=S_W;
  2381. { CX is already number of words, so no need to SHL/SHR }
  2382. end
  2383. else if (elesize and 1)=0 then
  2384. begin
  2385. opsize:=S_W;
  2386. { CX is number of bytes, convert to words }
  2387. list.concat(Taicpu.op_const_reg(A_SHR,S_W,1,NR_CX))
  2388. end;
  2389. if ts_cld in current_settings.targetswitches then
  2390. list.concat(Taicpu.op_none(A_CLD,S_NO));
  2391. if (opsize=S_B) and not (cs_opt_size in current_settings.optimizerswitches) then
  2392. begin
  2393. { SHR CX,1 moves the lowest (odd/even) bit to the carry flag }
  2394. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2395. list.concat(Taicpu.op_const_reg(A_SHR,S_W,1,NR_CX));
  2396. list.concat(Taicpu.op_none(A_REP,S_NO));
  2397. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  2398. { ADC CX,CX will set CX to 1 if the number of bytes was odd }
  2399. list.concat(Taicpu.op_reg_reg(A_ADC,S_W,NR_CX,NR_CX));
  2400. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2401. list.concat(Taicpu.op_none(A_REP,S_NO));
  2402. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  2403. end
  2404. else
  2405. begin
  2406. list.concat(Taicpu.op_none(A_REP,S_NO));
  2407. case opsize of
  2408. S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  2409. S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
  2410. end;
  2411. end;
  2412. ungetcpuregister(list,NR_DI);
  2413. ungetcpuregister(list,NR_CX);
  2414. ungetcpuregister(list,NR_SI);
  2415. if saved_ds then
  2416. list.concat(taicpu.op_reg(A_POP,S_W,NR_DS));
  2417. { patch the new address, but don't use a_load_reg_reg, that will add a move instruction
  2418. that can confuse the reg allocator }
  2419. list.concat(Taicpu.Op_reg_reg(A_MOV,S_W,NR_SP,destreg));
  2420. if current_settings.x86memorymodel in x86_far_data_models then
  2421. list.concat(Taicpu.Op_reg_reg(A_MOV,S_W,NR_SS,GetNextReg(destreg)));
  2422. end;
  2423. procedure tcg8086.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
  2424. begin
  2425. { Nothing to do }
  2426. end;
  2427. procedure tcg8086.get_32bit_ops(op: TOpCG; out op1, op2: TAsmOp);
  2428. begin
  2429. case op of
  2430. OP_ADD :
  2431. begin
  2432. op1:=A_ADD;
  2433. op2:=A_ADC;
  2434. end;
  2435. OP_SUB :
  2436. begin
  2437. op1:=A_SUB;
  2438. op2:=A_SBB;
  2439. end;
  2440. OP_XOR :
  2441. begin
  2442. op1:=A_XOR;
  2443. op2:=A_XOR;
  2444. end;
  2445. OP_OR :
  2446. begin
  2447. op1:=A_OR;
  2448. op2:=A_OR;
  2449. end;
  2450. OP_AND :
  2451. begin
  2452. op1:=A_AND;
  2453. op2:=A_AND;
  2454. end;
  2455. else
  2456. internalerror(200203241);
  2457. end;
  2458. end;
  2459. procedure tcg8086.add_move_instruction(instr: Taicpu);
  2460. begin
  2461. { HACK: when regvars are on, don't notify the register allocator of any
  2462. direct moves to BX, so it doesn't try to coalesce them. Currently,
  2463. direct moves to BX are only used when returning an int64 value in
  2464. AX:BX:CX:DX. This hack fixes a common issue with functions, returning
  2465. int64, for example:
  2466. function RandomFrom(const AValues: array of Int64): Int64;
  2467. begin
  2468. result:=AValues[random(High(AValues)+1)];
  2469. end;
  2470. push bp
  2471. mov bp,sp
  2472. ; Var AValues located in register ireg20w
  2473. ; Var $highAVALUES located in register ireg21w
  2474. ; Var $result located in register ireg33w:ireg32w:ireg31w:ireg30w
  2475. mov ireg20w,word [bp+6]
  2476. mov ireg21w,word [bp+4]
  2477. ; [3] result:=AValues[random(High(AValues)+1)];
  2478. mov ireg22w,ireg21w
  2479. inc ireg22w
  2480. mov ax,ireg22w
  2481. cwd
  2482. mov ireg23w,ax
  2483. mov ireg24w,dx
  2484. push ireg24w
  2485. push ireg23w
  2486. call SYSTEM_$$_RANDOM$LONGINT$$LONGINT
  2487. mov ireg25w,ax
  2488. mov ireg26w,dx
  2489. mov ireg27w,ireg25w
  2490. mov ireg28w,ireg27w
  2491. mov ireg29w,ireg28w
  2492. mov cl,3
  2493. shl ireg29w,cl
  2494. ; Var $result located in register ireg32w:ireg30w
  2495. mov ireg30w,word [ireg20w+ireg29w]
  2496. mov ireg31w,word [ireg20w+ireg29w+2]
  2497. mov ireg32w,word [ireg20w+ireg29w+4] ; problematic section start
  2498. mov ireg33w,word [ireg20w+ireg29w+6]
  2499. ; [4] end;
  2500. mov bx,ireg32w ; problematic section end
  2501. mov ax,ireg33w
  2502. mov dx,ireg30w
  2503. mov cx,ireg31w
  2504. mov sp,bp
  2505. pop bp
  2506. ret 4
  2507. the problem arises, because the register allocator tries to coalesce
  2508. mov bx,ireg32w
  2509. however, in the references [ireg20w+ireg29w+const], due to the
  2510. constraints of i8086, ireg20w can only be BX (or BP, which isn't available
  2511. to the register allocator, because it's used as a base pointer) }
  2512. if (cs_opt_regvar in current_settings.optimizerswitches) and
  2513. (instr.opcode=A_MOV) and (instr.ops=2) and
  2514. (instr.oper[1]^.typ=top_reg) and (getsupreg(instr.oper[1]^.reg)=RS_BX) then
  2515. exit
  2516. else
  2517. inherited add_move_instruction(instr);
  2518. end;
  2519. procedure tcg8086.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
  2520. var
  2521. hsym : tsym;
  2522. href : treference;
  2523. paraloc : Pcgparalocation;
  2524. return_address_size: Integer;
  2525. begin
  2526. if current_settings.x86memorymodel in x86_far_code_models then
  2527. return_address_size:=4
  2528. else
  2529. return_address_size:=2;
  2530. { calculate the parameter info for the procdef }
  2531. procdef.init_paraloc_info(callerside);
  2532. hsym:=tsym(procdef.parast.Find('self'));
  2533. if not(assigned(hsym) and
  2534. (hsym.typ=paravarsym)) then
  2535. internalerror(200305251);
  2536. paraloc:=tparavarsym(hsym).paraloc[callerside].location;
  2537. with paraloc^ do
  2538. begin
  2539. case loc of
  2540. LOC_REGISTER:
  2541. a_op_const_reg(list,OP_SUB,size,ioffset,register);
  2542. LOC_REFERENCE:
  2543. begin
  2544. { offset in the wrapper needs to be adjusted for the stored
  2545. return address }
  2546. if (reference.index<>NR_BP) and (reference.index<>NR_BX) and (reference.index<>NR_DI)
  2547. and (reference.index<>NR_SI) then
  2548. begin
  2549. list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DI));
  2550. list.concat(taicpu.op_reg_reg(A_MOV,S_W,reference.index,NR_DI));
  2551. if reference.index=NR_SP then
  2552. reference_reset_base(href,NR_DI,reference.offset+return_address_size+2,ctempposinvalid,sizeof(pint),[])
  2553. else
  2554. reference_reset_base(href,NR_DI,reference.offset+return_address_size,ctempposinvalid,sizeof(pint),[]);
  2555. href.segment:=NR_SS;
  2556. a_op_const_ref(list,OP_SUB,size,ioffset,href);
  2557. list.concat(taicpu.op_reg(A_POP,S_W,NR_DI));
  2558. end
  2559. else
  2560. begin
  2561. reference_reset_base(href,reference.index,reference.offset+return_address_size,ctempposinvalid,sizeof(pint),[]);
  2562. href.segment:=NR_SS;
  2563. a_op_const_ref(list,OP_SUB,size,ioffset,href);
  2564. end;
  2565. end
  2566. else
  2567. internalerror(200309189);
  2568. end;
  2569. paraloc:=next;
  2570. end;
  2571. end;
  2572. { ************* 64bit operations ************ }
  2573. procedure tcg64f8086.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  2574. begin
  2575. case op of
  2576. OP_ADD :
  2577. begin
  2578. op1:=A_ADD;
  2579. op2:=A_ADC;
  2580. end;
  2581. OP_SUB :
  2582. begin
  2583. op1:=A_SUB;
  2584. op2:=A_SBB;
  2585. end;
  2586. OP_XOR :
  2587. begin
  2588. op1:=A_XOR;
  2589. op2:=A_XOR;
  2590. end;
  2591. OP_OR :
  2592. begin
  2593. op1:=A_OR;
  2594. op2:=A_OR;
  2595. end;
  2596. OP_AND :
  2597. begin
  2598. op1:=A_AND;
  2599. op2:=A_AND;
  2600. end;
  2601. else
  2602. internalerror(200203241);
  2603. end;
  2604. end;
  2605. procedure tcg64f8086.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
  2606. var
  2607. op1,op2 : TAsmOp;
  2608. tempref : treference;
  2609. begin
  2610. if not(op in [OP_NEG,OP_NOT]) then
  2611. begin
  2612. get_64bit_ops(op,op1,op2);
  2613. tempref:=ref;
  2614. tcgx86(cg).make_simple_ref(list,tempref);
  2615. if op in [OP_ADD,OP_SUB] then
  2616. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2617. list.concat(taicpu.op_ref_reg(op1,S_W,tempref,reg.reglo));
  2618. inc(tempref.offset,2);
  2619. list.concat(taicpu.op_ref_reg(op2,S_W,tempref,cg.GetNextReg(reg.reglo)));
  2620. inc(tempref.offset,2);
  2621. list.concat(taicpu.op_ref_reg(op2,S_W,tempref,reg.reghi));
  2622. inc(tempref.offset,2);
  2623. list.concat(taicpu.op_ref_reg(op2,S_W,tempref,cg.GetNextReg(reg.reghi)));
  2624. if op in [OP_ADD,OP_SUB] then
  2625. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2626. end
  2627. else
  2628. begin
  2629. a_load64_ref_reg(list,ref,reg);
  2630. a_op64_reg_reg(list,op,size,reg,reg);
  2631. end;
  2632. end;
  2633. procedure tcg64f8086.a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
  2634. var
  2635. op1,op2 : TAsmOp;
  2636. tempref : treference;
  2637. begin
  2638. case op of
  2639. OP_NOT:
  2640. begin
  2641. tempref:=ref;
  2642. tcgx86(cg).make_simple_ref(list,tempref);
  2643. list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
  2644. inc(tempref.offset,2);
  2645. list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
  2646. inc(tempref.offset,2);
  2647. list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
  2648. inc(tempref.offset,2);
  2649. list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
  2650. end;
  2651. OP_NEG:
  2652. begin
  2653. tempref:=ref;
  2654. tcgx86(cg).make_simple_ref(list,tempref);
  2655. inc(tempref.offset,6);
  2656. list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
  2657. dec(tempref.offset,2);
  2658. list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
  2659. dec(tempref.offset,2);
  2660. list.concat(taicpu.op_ref(A_NOT,S_W,tempref));
  2661. dec(tempref.offset,2);
  2662. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2663. list.concat(taicpu.op_ref(A_NEG,S_W,tempref));
  2664. inc(tempref.offset,2);
  2665. list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
  2666. inc(tempref.offset,2);
  2667. list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
  2668. inc(tempref.offset,2);
  2669. list.concat(taicpu.op_const_ref(A_SBB,S_W,-1,tempref));
  2670. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2671. end;
  2672. else
  2673. begin
  2674. get_64bit_ops(op,op1,op2);
  2675. tempref:=ref;
  2676. tcgx86(cg).make_simple_ref(list,tempref);
  2677. if op in [OP_ADD,OP_SUB] then
  2678. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2679. list.concat(taicpu.op_reg_ref(op1,S_W,reg.reglo,tempref));
  2680. inc(tempref.offset,2);
  2681. list.concat(taicpu.op_reg_ref(op2,S_W,cg.GetNextReg(reg.reglo),tempref));
  2682. inc(tempref.offset,2);
  2683. list.concat(taicpu.op_reg_ref(op2,S_W,reg.reghi,tempref));
  2684. inc(tempref.offset,2);
  2685. list.concat(taicpu.op_reg_ref(op2,S_W,cg.GetNextReg(reg.reghi),tempref));
  2686. if op in [OP_ADD,OP_SUB] then
  2687. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2688. end;
  2689. end;
  2690. end;
  2691. procedure tcg64f8086.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
  2692. var
  2693. op1,op2 : TAsmOp;
  2694. l2, l3: TAsmLabel;
  2695. ai: taicpu;
  2696. begin
  2697. case op of
  2698. OP_NEG :
  2699. begin
  2700. if (regsrc.reglo<>regdst.reglo) then
  2701. a_load64_reg_reg(list,regsrc,regdst);
  2702. cg.a_op_reg_reg(list,OP_NOT,OS_32,regdst.reghi,regdst.reghi);
  2703. list.concat(taicpu.op_reg(A_NOT,S_W,cg.GetNextReg(regdst.reglo)));
  2704. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2705. list.concat(taicpu.op_reg(A_NEG,S_W,regdst.reglo));
  2706. list.concat(taicpu.op_const_reg(A_SBB,S_W,-1,cg.GetNextReg(regdst.reglo)));
  2707. list.concat(taicpu.op_const_reg(A_SBB,S_W,-1,regdst.reghi));
  2708. list.concat(taicpu.op_const_reg(A_SBB,S_W,-1,cg.GetNextReg(regdst.reghi)));
  2709. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2710. exit;
  2711. end;
  2712. OP_NOT :
  2713. begin
  2714. if (regsrc.reglo<>regdst.reglo) then
  2715. a_load64_reg_reg(list,regsrc,regdst);
  2716. cg.a_op_reg_reg(list,OP_NOT,OS_32,regdst.reglo,regdst.reglo);
  2717. cg.a_op_reg_reg(list,OP_NOT,OS_32,regdst.reghi,regdst.reghi);
  2718. exit;
  2719. end;
  2720. OP_SHR,OP_SHL,OP_SAR:
  2721. begin
  2722. { load right operators in a register }
  2723. cg.getcpuregister(list,NR_CX);
  2724. cg.a_load_reg_reg(list,OS_16,OS_16,regsrc.reglo,NR_CX);
  2725. current_asmdata.getjumplabel(l2);
  2726. current_asmdata.getjumplabel(l3);
  2727. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2728. list.concat(taicpu.op_const_reg(A_AND,S_W,63,NR_CX));
  2729. cg.a_jmp_flags(list,F_E,l3);
  2730. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2731. cg.a_label(list,l2);
  2732. case op of
  2733. OP_SHL:
  2734. begin
  2735. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2736. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,regdst.reglo));
  2737. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(regdst.reglo)));
  2738. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,regdst.reghi));
  2739. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(regdst.reghi)));
  2740. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2741. end;
  2742. OP_SHR,OP_SAR:
  2743. begin
  2744. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2745. cg.a_op_const_reg(list,op,OS_16,1,cg.GetNextReg(regdst.reghi));
  2746. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,regdst.reghi));
  2747. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(regdst.reglo)));
  2748. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,regdst.reglo));
  2749. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2750. end;
  2751. end;
  2752. ai:=Taicpu.Op_Sym(A_LOOP,S_W,l2);
  2753. ai.is_jmp := True;
  2754. list.Concat(ai);
  2755. cg.a_label(list,l3);
  2756. cg.ungetcpuregister(list,NR_CX);
  2757. exit;
  2758. end;
  2759. end;
  2760. get_64bit_ops(op,op1,op2);
  2761. if op in [OP_ADD,OP_SUB] then
  2762. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2763. list.concat(taicpu.op_reg_reg(op1,S_W,regsrc.reglo,regdst.reglo));
  2764. list.concat(taicpu.op_reg_reg(op2,S_W,cg.GetNextReg(regsrc.reglo),cg.GetNextReg(regdst.reglo)));
  2765. list.concat(taicpu.op_reg_reg(op2,S_W,regsrc.reghi,regdst.reghi));
  2766. list.concat(taicpu.op_reg_reg(op2,S_W,cg.GetNextReg(regsrc.reghi),cg.GetNextReg(regdst.reghi)));
  2767. if op in [OP_ADD,OP_SUB] then
  2768. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2769. end;
  2770. procedure tcg64f8086.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
  2771. var
  2772. op1,op2 : TAsmOp;
  2773. loop_start: TAsmLabel;
  2774. ai: taicpu;
  2775. begin
  2776. case op of
  2777. OP_AND,OP_OR,OP_XOR:
  2778. begin
  2779. cg.a_op_const_reg(list,op,OS_32,tcgint(lo(value)),reg.reglo);
  2780. cg.a_op_const_reg(list,op,OS_32,tcgint(hi(value)),reg.reghi);
  2781. end;
  2782. OP_ADD, OP_SUB:
  2783. begin
  2784. get_64bit_ops(op,op1,op2);
  2785. if (value and $ffffffffffff) = 0 then
  2786. begin
  2787. { use a_op_const_reg to allow the use of inc/dec }
  2788. cg.a_op_const_reg(list,op,OS_16,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi));
  2789. end
  2790. // can't use a_op_const_ref because this may use dec/inc
  2791. else if (value and $ffffffff) = 0 then
  2792. begin
  2793. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2794. list.concat(taicpu.op_const_reg(op1,S_W,aint((value shr 32) and $ffff),reg.reghi));
  2795. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi)));
  2796. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2797. end
  2798. else if (value and $ffff) = 0 then
  2799. begin
  2800. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2801. list.concat(taicpu.op_const_reg(op1,S_W,aint((value shr 16) and $ffff),cg.GetNextReg(reg.reglo)));
  2802. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 32) and $ffff),reg.reghi));
  2803. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi)));
  2804. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2805. end
  2806. else
  2807. begin
  2808. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2809. list.concat(taicpu.op_const_reg(op1,S_W,aint(value and $ffff),reg.reglo));
  2810. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 16) and $ffff),cg.GetNextReg(reg.reglo)));
  2811. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 32) and $ffff),reg.reghi));
  2812. list.concat(taicpu.op_const_reg(op2,S_W,aint((value shr 48) and $ffff),cg.GetNextReg(reg.reghi)));
  2813. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2814. end;
  2815. end;
  2816. OP_SHR,OP_SHL,OP_SAR:
  2817. begin
  2818. value:=value and 63;
  2819. case value of
  2820. 0:
  2821. { ultra hyper fast shift by 0 };
  2822. 1:
  2823. case op of
  2824. OP_SHL:
  2825. begin
  2826. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2827. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,reg.reglo));
  2828. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reglo)));
  2829. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,reg.reghi));
  2830. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reghi)));
  2831. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2832. end;
  2833. OP_SHR,OP_SAR:
  2834. begin
  2835. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2836. cg.a_op_const_reg(list,op,OS_16,1,cg.GetNextReg(reg.reghi));
  2837. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reghi));
  2838. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2839. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2840. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2841. end;
  2842. end;
  2843. 2..15:
  2844. begin
  2845. cg.getcpuregister(list,NR_CX);
  2846. cg.a_load_const_reg(list,OS_16,value,NR_CX);
  2847. current_asmdata.getjumplabel(loop_start);
  2848. cg.a_label(list,loop_start);
  2849. case op of
  2850. OP_SHL:
  2851. begin
  2852. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2853. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,reg.reglo));
  2854. list.concat(taicpu.op_const_reg(A_RCL,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,cg.GetNextReg(reg.reghi));
  2863. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reghi));
  2864. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2865. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2866. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2867. end;
  2868. end;
  2869. ai:=Taicpu.Op_Sym(A_LOOP,S_W,loop_start);
  2870. ai.is_jmp := True;
  2871. list.Concat(ai);
  2872. cg.ungetcpuregister(list,NR_CX);
  2873. end;
  2874. 16,17:
  2875. begin
  2876. case op of
  2877. OP_SHL:
  2878. begin
  2879. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reghi));
  2880. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reghi);
  2881. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reglo,cg.GetNextReg(reg.reglo));
  2882. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2883. end;
  2884. OP_SHR:
  2885. begin
  2886. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2887. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2888. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2889. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  2890. end;
  2891. OP_SAR:
  2892. begin
  2893. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2894. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2895. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2896. cg.a_op_const_reg(list,OP_SAR,OS_16,15,cg.GetNextReg(reg.reghi));
  2897. end;
  2898. end;
  2899. if value=17 then
  2900. case op of
  2901. OP_SHL:
  2902. begin
  2903. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2904. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,cg.GetNextReg(reg.reglo)));
  2905. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,reg.reghi));
  2906. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reghi)));
  2907. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2908. end;
  2909. OP_SHR,OP_SAR:
  2910. begin
  2911. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2912. cg.a_op_const_reg(list,op,OS_16,1,reg.reghi);
  2913. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2914. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2915. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2916. end;
  2917. end;
  2918. end;
  2919. 18..31:
  2920. begin
  2921. case op of
  2922. OP_SHL:
  2923. begin
  2924. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reghi));
  2925. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reghi);
  2926. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reglo,cg.GetNextReg(reg.reglo));
  2927. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2928. end;
  2929. OP_SHR:
  2930. begin
  2931. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2932. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2933. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2934. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  2935. end;
  2936. OP_SAR:
  2937. begin
  2938. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reglo);
  2939. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reglo));
  2940. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  2941. cg.a_op_const_reg(list,OP_SAR,OS_16,15,cg.GetNextReg(reg.reghi));
  2942. end;
  2943. end;
  2944. cg.getcpuregister(list,NR_CX);
  2945. cg.a_load_const_reg(list,OS_16,value-16,NR_CX);
  2946. current_asmdata.getjumplabel(loop_start);
  2947. cg.a_label(list,loop_start);
  2948. case op of
  2949. OP_SHL:
  2950. begin
  2951. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2952. list.concat(taicpu.op_const_reg(A_SHL,S_W,1,cg.GetNextReg(reg.reglo)));
  2953. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,reg.reghi));
  2954. list.concat(taicpu.op_const_reg(A_RCL,S_W,1,cg.GetNextReg(reg.reghi)));
  2955. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2956. end;
  2957. OP_SHR,OP_SAR:
  2958. begin
  2959. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  2960. cg.a_op_const_reg(list,op,OS_16,1,reg.reghi);
  2961. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,cg.GetNextReg(reg.reglo)));
  2962. list.concat(taicpu.op_const_reg(A_RCR,S_W,1,reg.reglo));
  2963. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  2964. end;
  2965. end;
  2966. ai:=Taicpu.Op_Sym(A_LOOP,S_W,loop_start);
  2967. ai.is_jmp := True;
  2968. list.Concat(ai);
  2969. cg.ungetcpuregister(list,NR_CX);
  2970. end;
  2971. 32..47:
  2972. case op of
  2973. OP_SHL:
  2974. begin
  2975. cg.a_op_const_reg_reg(list,OP_SHL,OS_32,value-32,reg.reglo,reg.reghi);
  2976. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2977. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reglo));
  2978. end;
  2979. OP_SHR:
  2980. begin
  2981. cg.a_op_const_reg_reg(list,OP_SHR,OS_32,value-32,reg.reghi,reg.reglo);
  2982. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reghi,reg.reghi);
  2983. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  2984. end;
  2985. OP_SAR:
  2986. begin
  2987. cg.a_op_const_reg_reg(list,OP_SAR,OS_32,value-32,reg.reghi,reg.reglo);
  2988. cg.a_op_const_reg_reg(list,OP_SAR,OS_16,15-(value-32),cg.GetNextReg(reg.reglo),reg.reghi);
  2989. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reghi,cg.GetNextReg(reg.reghi));
  2990. end;
  2991. end;
  2992. 48..63:
  2993. case op of
  2994. OP_SHL:
  2995. begin
  2996. cg.a_load_reg_reg(list,OS_16,OS_16,reg.reglo,cg.GetNextReg(reg.reghi));
  2997. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reglo,reg.reglo);
  2998. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reglo));
  2999. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reghi,reg.reghi);
  3000. cg.a_op_const_reg(list,OP_SHL,OS_16,value-48,cg.GetNextReg(reg.reghi));
  3001. end;
  3002. OP_SHR:
  3003. begin
  3004. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reglo);
  3005. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reghi));
  3006. cg.a_op_reg_reg(list,OP_XOR,OS_16,reg.reghi,reg.reghi);
  3007. cg.a_op_reg_reg(list,OP_XOR,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reglo));
  3008. cg.a_op_const_reg(list,OP_SHR,OS_16,value-48,reg.reglo);
  3009. end;
  3010. OP_SAR:
  3011. if value=63 then
  3012. begin
  3013. cg.a_op_const_reg(list,OP_SAR,OS_16,15,cg.GetNextReg(reg.reghi));
  3014. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reghi);
  3015. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),cg.GetNextReg(reg.reglo));
  3016. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reghi),reg.reglo);
  3017. end
  3018. else
  3019. begin
  3020. cg.a_op_const_reg_reg(list,OP_SAR,OS_16,value-48,cg.GetNextReg(reg.reghi),reg.reglo);
  3021. cg.a_op_const_reg_reg(list,OP_SAR,OS_16,15-(value-48),reg.reglo,cg.GetNextReg(reg.reglo));
  3022. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),reg.reghi);
  3023. cg.a_load_reg_reg(list,OS_16,OS_16,cg.GetNextReg(reg.reglo),cg.GetNextReg(reg.reghi));
  3024. end;
  3025. end;
  3026. end;
  3027. end;
  3028. else
  3029. internalerror(200204021);
  3030. end;
  3031. end;
  3032. procedure tcg64f8086.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
  3033. var
  3034. op1,op2 : TAsmOp;
  3035. tempref : treference;
  3036. begin
  3037. tempref:=ref;
  3038. tcgx86(cg).make_simple_ref(list,tempref);
  3039. case op of
  3040. OP_AND,OP_OR,OP_XOR:
  3041. begin
  3042. cg.a_op_const_ref(list,op,OS_32,tcgint(lo(value)),tempref);
  3043. inc(tempref.offset,4);
  3044. cg.a_op_const_ref(list,op,OS_32,tcgint(hi(value)),tempref);
  3045. end;
  3046. OP_ADD, OP_SUB:
  3047. begin
  3048. get_64bit_ops(op,op1,op2);
  3049. if (value and $ffffffffffff) = 0 then
  3050. begin
  3051. inc(tempref.offset,6);
  3052. { use a_op_const_ref to allow the use of inc/dec }
  3053. cg.a_op_const_ref(list,op,OS_16,aint((value shr 48) and $ffff),tempref);
  3054. end
  3055. // can't use a_op_const_ref because this may use dec/inc
  3056. else if (value and $ffffffff) = 0 then
  3057. begin
  3058. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  3059. inc(tempref.offset,4);
  3060. list.concat(taicpu.op_const_ref(op1,S_W,aint((value shr 32) and $ffff),tempref));
  3061. inc(tempref.offset,2);
  3062. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 48) and $ffff),tempref));
  3063. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  3064. end
  3065. else if (value and $ffff) = 0 then
  3066. begin
  3067. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  3068. inc(tempref.offset,2);
  3069. list.concat(taicpu.op_const_ref(op1,S_W,aint((value shr 16) and $ffff),tempref));
  3070. inc(tempref.offset,2);
  3071. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 32) and $ffff),tempref));
  3072. inc(tempref.offset,2);
  3073. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 48) and $ffff),tempref));
  3074. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  3075. end
  3076. else
  3077. begin
  3078. cg.a_reg_alloc(list,NR_DEFAULTFLAGS);
  3079. list.concat(taicpu.op_const_ref(op1,S_W,aint(value and $ffff),tempref));
  3080. inc(tempref.offset,2);
  3081. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 16) and $ffff),tempref));
  3082. inc(tempref.offset,2);
  3083. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 32) and $ffff),tempref));
  3084. inc(tempref.offset,2);
  3085. list.concat(taicpu.op_const_ref(op2,S_W,aint((value shr 48) and $ffff),tempref));
  3086. cg.a_reg_dealloc(list,NR_DEFAULTFLAGS);
  3087. end;
  3088. end;
  3089. else
  3090. internalerror(200204022);
  3091. end;
  3092. end;
  3093. procedure create_codegen;
  3094. begin
  3095. cg := tcg8086.create;
  3096. cg64 := tcg64f8086.create;
  3097. end;
  3098. end.