cgcpu.pas 139 KB

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