cgcpu.pas 139 KB

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