cgcpu.pas 137 KB

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