cgcpu.pas 139 KB

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