cgcpu.pas 137 KB

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