aasmcpu.pas 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583
  1. {
  2. Copyright (c) 2003-2012 by Florian Klaempfl and others
  3. Contains the assembler object for Aarch64
  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 aasmcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,globtype,globals,verbose,
  22. aasmbase,aasmtai,aasmdata,aasmsym,
  23. ogbase,
  24. symtype,
  25. cpubase,cpuinfo,cgbase,cgutils;
  26. const
  27. { "mov reg,reg" source operand number }
  28. O_MOV_SOURCE = 1;
  29. { "mov reg,reg" source operand number }
  30. O_MOV_DEST = 0;
  31. { Operand types }
  32. OT_NONE = $00000000;
  33. OT_BITS8 = $00000001; { size, and other attributes, of the operand }
  34. OT_BITS16 = $00000002;
  35. OT_BITS32 = $00000004;
  36. OT_BITS64 = $00000008; { FPU only }
  37. OT_BITS80 = $00000010;
  38. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  39. OT_NEAR = $00000040;
  40. OT_SHORT = $00000080;
  41. OT_BITSTINY = $00000100; { fpu constant }
  42. OT_BITSSHIFTER =
  43. $00000200;
  44. OT_SIZE_MASK = $000003FF; { all the size attributes }
  45. OT_NON_SIZE = longint(not OT_SIZE_MASK);
  46. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  47. OT_TO = $00000200; { operand is followed by a colon }
  48. { reverse effect in FADD, FSUB &c }
  49. OT_COLON = $00000400;
  50. OT_SHIFTEROP = $00000800;
  51. OT_REGISTER = $00001000;
  52. OT_IMMEDIATE = $00002000;
  53. OT_REGLIST = $00008000;
  54. OT_IMM8 = $00002001;
  55. OT_IMM24 = $00002002;
  56. OT_IMM32 = $00002004;
  57. OT_IMM64 = $00002008;
  58. OT_IMM80 = $00002010;
  59. OT_IMMTINY = $00002100;
  60. OT_IMMSHIFTER= $00002200;
  61. OT_IMMEDIATE24 = OT_IMM24;
  62. OT_SHIFTIMM = OT_SHIFTEROP or OT_IMMSHIFTER;
  63. OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
  64. OT_IMMEDIATESHIFTER = OT_IMMSHIFTER;
  65. OT_IMMEDIATEFPU = OT_IMMTINY;
  66. OT_REGMEM = $00200000; { for r/m, ie EA, operands }
  67. OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
  68. OT_REG8 = $00201001;
  69. OT_REG16 = $00201002;
  70. OT_REG32 = $00201004;
  71. OT_REG64 = $00201008;
  72. OT_VREG = $00201010; { vector register }
  73. OT_REGF = $00201020; { coproc register }
  74. OT_MEMORY = $00204000; { register number in 'basereg' }
  75. OT_MEM8 = $00204001;
  76. OT_MEM16 = $00204002;
  77. OT_MEM32 = $00204004;
  78. OT_MEM64 = $00204008;
  79. OT_MEM80 = $00204010;
  80. { word/byte load/store }
  81. OT_AM2 = $00010000;
  82. { misc ld/st operations }
  83. OT_AM3 = $00020000;
  84. { multiple ld/st operations }
  85. OT_AM4 = $00040000;
  86. { co proc. ld/st operations }
  87. OT_AM5 = $00080000;
  88. OT_AMMASK = $000f0000;
  89. { IT instruction }
  90. OT_CONDITION = $00100000;
  91. OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
  92. OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
  93. OT_MEMORYAM4 = OT_MEMORY or OT_AM4;
  94. OT_MEMORYAM5 = OT_MEMORY or OT_AM5;
  95. OT_FPUREG = $01000000; { floating point stack registers }
  96. OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
  97. { a mask for the following }
  98. OT_MEM_OFFS = $00604000; { special type of EA }
  99. { simple [address] offset }
  100. OT_ONENESS = $00800000; { special type of immediate operand }
  101. { so UNITY == IMMEDIATE | ONENESS }
  102. OT_UNITY = $00802000; { for shift/rotate instructions }
  103. instabentries = {$i a64nop.inc}
  104. maxinfolen = 5;
  105. IF_NONE = $00000000;
  106. IF_ARMMASK = $000F0000;
  107. IF_ARM7 = $00070000;
  108. IF_FPMASK = $00F00000;
  109. IF_FPA = $00100000;
  110. { if the instruction can change in a second pass }
  111. IF_PASS2 = longint($80000000);
  112. type
  113. TInsTabCache=array[TasmOp] of longint;
  114. PInsTabCache=^TInsTabCache;
  115. tinsentry = record
  116. opcode : tasmop;
  117. ops : byte;
  118. optypes : array[0..3] of longint;
  119. code : array[0..maxinfolen] of char;
  120. flags : longint;
  121. end;
  122. pinsentry=^tinsentry;
  123. var
  124. InsTabCache : PInsTabCache;
  125. type
  126. taicpu = class(tai_cpu_abstract_sym)
  127. oppostfix : TOpPostfix;
  128. procedure loadshifterop(opidx:longint;const so:tshifterop);
  129. procedure loadconditioncode(opidx: longint; const c: tasmcond);
  130. constructor op_none(op : tasmop);
  131. constructor op_reg(op : tasmop;_op1 : tregister);
  132. constructor op_ref(op : tasmop;const _op1 : treference);
  133. constructor op_const(op : tasmop;_op1 : longint);
  134. constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  135. constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  136. constructor op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
  137. constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  138. constructor op_reg_const_shifterop(op : tasmop;_op1: tregister; _op2: aint;_op3 : tshifterop);
  139. constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  140. constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  141. constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  142. constructor op_reg_reg_const_const(op : tasmop;_op1,_op2 : tregister; _op3, _op4: aint);
  143. constructor op_reg_reg_const_shifterop(op : tasmop;_op1,_op2 : tregister; _op3: aint; const _op4 : tshifterop);
  144. constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  145. constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  146. constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  147. constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
  148. constructor op_reg_reg_reg_cond(op : tasmop;_op1,_op2,_op3 : tregister; const _op4: tasmcond);
  149. { this is for Jmp instructions }
  150. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  151. constructor op_sym(op : tasmop;_op1 : tasmsymbol);
  152. constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  153. constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  154. constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  155. function is_same_reg_move(regtype: Tregistertype):boolean; override;
  156. function spilling_get_operation_type(opnr: longint): topertype;override;
  157. function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
  158. { assembler }
  159. public
  160. { the next will reset all instructions that can change in pass 2 }
  161. procedure ResetPass1;override;
  162. procedure ResetPass2;override;
  163. function CheckIfValid:boolean;
  164. function GetString:string;
  165. function Pass1(objdata:TObjData):longint;override;
  166. procedure Pass2(objdata:TObjData);override;
  167. protected
  168. procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
  169. procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
  170. procedure ppubuildderefimploper(var o:toper);override;
  171. procedure ppuderefoper(var o:toper);override;
  172. private
  173. { next fields are filled in pass1, so pass2 is faster }
  174. inssize : shortint;
  175. LastInsOffset : longint; { need to be public to be reset }
  176. insentry : PInsEntry;
  177. function InsEnd:longint;
  178. procedure create_ot(objdata:TObjData);
  179. function Matches(p:PInsEntry):longint;
  180. function calcsize(p:PInsEntry):shortint;
  181. procedure gencode(objdata:TObjData);
  182. function NeedAddrPrefix(opidx:byte):boolean;
  183. procedure Swapoperands;
  184. function FindInsentry(objdata:TObjData):boolean;
  185. end;
  186. tai_align = class(tai_align_abstract)
  187. { nothing to add }
  188. end;
  189. type
  190. tsimplereftype =
  191. { valid reference }
  192. (sr_simple,
  193. { invalid reference, should not be generated by the code generator (but
  194. can be encountered via inline assembly, where it must be rejected) }
  195. sr_internal_illegal,
  196. { invalid reference, may be generated by the code generator and then
  197. must be simplified (also rejected in inline assembly) }
  198. sr_complex);
  199. function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
  200. function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
  201. function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
  202. function spilling_create_load(const ref: treference; r: tregister): taicpu;
  203. function spilling_create_store(r: tregister; const ref: treference): taicpu;
  204. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  205. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  206. { inserts pc relative symbols at places where they are reachable
  207. and transforms special instructions to valid instruction encodings }
  208. procedure finalizearmcode(list,listtoinsert : TAsmList);
  209. { inserts .pdata section and dummy function prolog needed for arm-wince exception handling }
  210. procedure InsertPData;
  211. procedure InitAsm;
  212. procedure DoneAsm;
  213. implementation
  214. uses
  215. cutils,rgobj,itcpugas,aoptcpu;
  216. procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
  217. begin
  218. allocate_oper(opidx+1);
  219. with oper[opidx]^ do
  220. begin
  221. if typ<>top_shifterop then
  222. begin
  223. clearop(opidx);
  224. new(shifterop);
  225. end;
  226. shifterop^:=so;
  227. typ:=top_shifterop;
  228. end;
  229. end;
  230. procedure taicpu.loadconditioncode(opidx: longint; const c: tasmcond);
  231. begin
  232. allocate_oper(opidx+1);
  233. with oper[opidx]^ do
  234. begin
  235. if typ<>top_conditioncode then
  236. begin
  237. clearop(opidx);
  238. end;
  239. cc:=c;
  240. typ:=top_conditioncode;
  241. end;
  242. end;
  243. {*****************************************************************************
  244. taicpu Constructors
  245. *****************************************************************************}
  246. constructor taicpu.op_none(op : tasmop);
  247. begin
  248. inherited create(op);
  249. end;
  250. { for pld }
  251. constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
  252. begin
  253. inherited create(op);
  254. ops:=1;
  255. loadref(0,_op1);
  256. end;
  257. constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
  258. begin
  259. inherited create(op);
  260. ops:=1;
  261. loadreg(0,_op1);
  262. end;
  263. constructor taicpu.op_const(op : tasmop;_op1 : longint);
  264. begin
  265. inherited create(op);
  266. ops:=1;
  267. loadconst(0,aint(_op1));
  268. end;
  269. constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  270. begin
  271. inherited create(op);
  272. ops:=2;
  273. loadreg(0,_op1);
  274. loadreg(1,_op2);
  275. end;
  276. constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  277. begin
  278. inherited create(op);
  279. ops:=2;
  280. loadreg(0,_op1);
  281. loadconst(1,aint(_op2));
  282. end;
  283. constructor taicpu.op_reg_const_shifterop(op: tasmop; _op1: tregister; _op2: aint; _op3: tshifterop);
  284. begin
  285. inherited create(op);
  286. ops:=3;
  287. loadreg(0,_op1);
  288. loadconst(1,_op2);
  289. loadshifterop(2,_op3);
  290. end;
  291. constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  292. begin
  293. inherited create(op);
  294. ops:=2;
  295. loadreg(0,_op1);
  296. loadref(1,_op2);
  297. end;
  298. constructor taicpu.op_reg_cond(op: tasmop; _op1: tregister; _op2: tasmcond);
  299. begin
  300. inherited create(op);
  301. ops:=2;
  302. loadreg(0,_op1);
  303. loadconditioncode(1,_op2);
  304. end;
  305. constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  306. begin
  307. inherited create(op);
  308. ops:=3;
  309. loadreg(0,_op1);
  310. loadreg(1,_op2);
  311. loadreg(2,_op3);
  312. end;
  313. constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  314. begin
  315. inherited create(op);
  316. ops:=4;
  317. loadreg(0,_op1);
  318. loadreg(1,_op2);
  319. loadreg(2,_op3);
  320. loadreg(3,_op4);
  321. end;
  322. constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  323. begin
  324. inherited create(op);
  325. ops:=3;
  326. loadreg(0,_op1);
  327. loadreg(1,_op2);
  328. loadconst(2,aint(_op3));
  329. end;
  330. constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
  331. begin
  332. inherited create(op);
  333. ops:=4;
  334. loadreg(0,_op1);
  335. loadreg(1,_op2);
  336. loadconst(2,aint(_op3));
  337. loadconst(3,aint(_op4));
  338. end;
  339. constructor taicpu.op_reg_reg_const_shifterop(op: tasmop; _op1, _op2: tregister; _op3: aint; const _op4: tshifterop);
  340. begin
  341. inherited create(op);
  342. ops:=4;
  343. loadreg(0,_op1);
  344. loadreg(1,_op2);
  345. loadconst(2,aint(_op3));
  346. loadshifterop(3,_op4);
  347. end;
  348. constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  349. begin
  350. inherited create(op);
  351. ops:=3;
  352. loadreg(0,_op1);
  353. loadreg(1,_op2);
  354. loadsymbol(0,_op3,_op3ofs);
  355. end;
  356. constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  357. begin
  358. inherited create(op);
  359. ops:=3;
  360. loadreg(0,_op1);
  361. loadreg(1,_op2);
  362. loadref(2,_op3);
  363. end;
  364. constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  365. begin
  366. inherited create(op);
  367. ops:=3;
  368. loadreg(0,_op1);
  369. loadreg(1,_op2);
  370. loadshifterop(2,_op3);
  371. end;
  372. constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister; const _op4 : tshifterop);
  373. begin
  374. inherited create(op);
  375. ops:=4;
  376. loadreg(0,_op1);
  377. loadreg(1,_op2);
  378. loadreg(2,_op3);
  379. loadshifterop(3,_op4);
  380. end;
  381. constructor taicpu.op_reg_reg_reg_cond(op: tasmop; _op1, _op2, _op3: tregister; const _op4: tasmcond);
  382. begin
  383. inherited create(op);
  384. ops:=4;
  385. loadreg(0,_op1);
  386. loadreg(1,_op2);
  387. loadreg(2,_op3);
  388. loadconditioncode(3,_op4);
  389. end;
  390. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  391. begin
  392. inherited create(op);
  393. condition:=cond;
  394. ops:=1;
  395. loadsymbol(0,_op1,0);
  396. end;
  397. constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
  398. begin
  399. inherited create(op);
  400. ops:=1;
  401. loadsymbol(0,_op1,0);
  402. end;
  403. constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  404. begin
  405. inherited create(op);
  406. ops:=1;
  407. loadsymbol(0,_op1,_op1ofs);
  408. end;
  409. constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  410. begin
  411. inherited create(op);
  412. ops:=2;
  413. loadreg(0,_op1);
  414. loadsymbol(1,_op2,_op2ofs);
  415. end;
  416. constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  417. begin
  418. inherited create(op);
  419. ops:=2;
  420. loadsymbol(0,_op1,_op1ofs);
  421. loadref(1,_op2);
  422. end;
  423. function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
  424. begin
  425. { allow the register allocator to remove unnecessary moves }
  426. result:=(
  427. ((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
  428. ((opcode=A_FMOV) and (regtype = R_MMREGISTER))
  429. ) and
  430. (oppostfix in [PF_None]) and
  431. (condition=C_None) and
  432. (ops=2) and
  433. (oper[0]^.typ=top_reg) and
  434. (oper[1]^.typ=top_reg) and
  435. (oper[0]^.reg=oper[1]^.reg);
  436. end;
  437. function spilling_create_op(op: tasmop; const ref: treference; r: tregister): taicpu;
  438. const
  439. { invalid sizes for aarch64 are 0 }
  440. subreg2bytesize: array[TSubRegister] of byte =
  441. (0,0,0,0,4,8,0,0,0,4,8,0,0,0);
  442. var
  443. scalefactor: byte;
  444. begin
  445. scalefactor:=subreg2bytesize[getsubreg(r)];
  446. if scalefactor=0 then
  447. internalerror(2014120301);
  448. if (ref.offset>4095*scalefactor) or
  449. ((ref.offset>255) and
  450. ((ref.offset mod scalefactor)<>0)) or
  451. (ref.offset<-256) then
  452. internalerror(2014120302);
  453. case getregtype(r) of
  454. R_INTREGISTER,
  455. R_MMREGISTER:
  456. result:=taicpu.op_reg_ref(op,r,ref);
  457. else
  458. internalerror(200401041);
  459. end;
  460. end;
  461. function is_valid_load_symbol(op: tasmop; oppostfix: toppostfix; const ref: treference): tsimplereftype;
  462. begin
  463. result:=sr_complex;
  464. if not assigned(ref.symboldata) and
  465. not(ref.refaddr in [addr_gotpageoffset,addr_gotpage,addr_pageoffset,addr_page]) then
  466. exit;
  467. { can't use pre-/post-indexed mode here (makes no sense either) }
  468. if ref.addressmode<>AM_OFFSET then
  469. exit;
  470. { "ldr literal" must be a 32/64 bit LDR and have a symbol }
  471. if assigned(ref.symboldata) and
  472. ((op<>A_LDR) or
  473. not(oppostfix in [PF_NONE,PF_W,PF_SW]) or
  474. not assigned(ref.symbol)) then
  475. exit;
  476. { if this is a (got) page offset load, we must have a base register and a
  477. symbol }
  478. if (ref.refaddr in [addr_gotpageoffset,addr_pageoffset]) and
  479. (not assigned(ref.symbol) or
  480. (ref.base=NR_NO) or
  481. (ref.index<>NR_NO) or
  482. (ref.offset<>0)) then
  483. begin
  484. result:=sr_internal_illegal;
  485. exit;
  486. end;
  487. { cannot have base or index register (we generate these kind of
  488. references internally, they should never end up here with an
  489. extra base or offset) }
  490. if (ref.refaddr in [addr_gotpage,addr_page]) and
  491. (ref.base<>NR_NO) or
  492. (ref.index<>NR_NO) then
  493. begin
  494. result:=sr_internal_illegal;
  495. exit;
  496. end;
  497. result:=sr_simple;
  498. end;
  499. function simple_ref_type(op: tasmop; size:tcgsize; oppostfix: toppostfix; const ref: treference): tsimplereftype;
  500. var
  501. maxoffs: asizeint;
  502. accesssize: longint;
  503. begin
  504. result:=sr_internal_illegal;
  505. { post-indexed is only allowed for vector and immediate loads/stores }
  506. if (ref.addressmode=AM_POSTINDEXED) and
  507. not(op in [A_LD1,A_LD2,A_LD3,A_LD4,A_ST1,A_ST2,A_ST3,A_ST4]) and
  508. (not(op in [A_LDR,A_STR,A_LDP,A_STP]) or
  509. (ref.base=NR_NO) or
  510. (ref.index<>NR_NO)) then
  511. exit;
  512. { can only have a shift mode if we have an index }
  513. if (ref.index=NR_NO) and
  514. (ref.shiftmode<>SM_None) then
  515. exit;
  516. { the index can never be the stack pointer }
  517. if ref.index=NR_SP then
  518. exit;
  519. { no instruction supports an index without a base }
  520. if (ref.base=NR_NO) and
  521. (ref.index<>NR_NO) then
  522. begin
  523. result:=sr_complex;
  524. exit;
  525. end;
  526. { LDR literal or GOT entry: 32 or 64 bit, label }
  527. if assigned(ref.symboldata) or
  528. assigned(ref.symbol) then
  529. begin
  530. { we generate these kind of references internally; at least for now,
  531. they should never end up here with an extra base or offset or so }
  532. result:=is_valid_load_symbol(op,oppostfix,ref);
  533. exit;
  534. end;
  535. { any other reference cannot be gotpage/gotpageoffset/pic }
  536. if ref.refaddr in [addr_gotpage,addr_gotpageoffset,addr_page,addr_pageoffset,addr_pic] then
  537. exit;
  538. { base & index:
  539. * index cannot be the stack pointer
  540. * offset must be 0
  541. * can scale with the size of the access
  542. * can zero/sign extend 32 bit index register, and/or multiple by
  543. access size
  544. * no pre/post-indexing
  545. }
  546. if (ref.base<>NR_NO) and
  547. (ref.index<>NR_NO) then
  548. begin
  549. if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
  550. exit;
  551. case op of
  552. { this holds for both integer and fpu/vector loads }
  553. A_LDR,A_STR:
  554. if (ref.offset=0) and
  555. (((ref.shiftmode=SM_None) and
  556. (ref.shiftimm=0)) or
  557. ((ref.shiftmode in [SM_LSL,SM_UXTW,SM_SXTW]) and
  558. (ref.shiftimm=tcgsizep2size[size]))) then
  559. result:=sr_simple
  560. else
  561. result:=sr_complex;
  562. { todo }
  563. A_LD1,A_LD2,A_LD3,A_LD4,
  564. A_ST1,A_ST2,A_ST3,A_ST4:
  565. internalerror(2014110704);
  566. { these don't support base+index }
  567. A_LDUR,A_STUR,
  568. A_LDP,A_STP:
  569. result:=sr_complex;
  570. else
  571. { nothing: result is already sr_internal_illegal };
  572. end;
  573. exit;
  574. end;
  575. { base + immediate offset. Variants:
  576. * LDR*/STR*:
  577. - pre- or post-indexed with signed 9 bit immediate
  578. - regular with unsiged scaled immediate (multiple of access
  579. size), in the range 0 to (12 bit * access_size)-1
  580. * LDP/STP
  581. - pre- or post-indexed with signed 9 bit immediate
  582. - regular with signed 9 bit immediate
  583. * LDUR*/STUR*:
  584. - regular with signed 9 bit immediate
  585. }
  586. if ref.base<>NR_NO then
  587. begin
  588. accesssize:=1 shl tcgsizep2size[size];
  589. case op of
  590. A_LDR,A_STR:
  591. begin
  592. if (ref.addressmode=AM_OFFSET) and
  593. (ref.offset>=0) and
  594. (ref.offset<(((1 shl 12)-1)*accesssize)) and
  595. ((ref.offset mod accesssize)=0) then
  596. result:=sr_simple
  597. else if (ref.offset>=-256) and
  598. (ref.offset<=255) then
  599. begin
  600. { non pre-/post-indexed regular loads/stores can only be
  601. performed using LDUR/STUR }
  602. if ref.addressmode in [AM_PREINDEXED,AM_POSTINDEXED] then
  603. result:=sr_simple
  604. else
  605. result:=sr_complex
  606. end
  607. else
  608. result:=sr_complex;
  609. end;
  610. A_LDP,A_LDNP,
  611. A_STP,A_STNP:
  612. begin
  613. { only supported for 32/64 bit }
  614. if not(oppostfix in [PF_W,PF_SW,PF_None]) then
  615. exit;
  616. { offset must be a multple of the access size }
  617. if (ref.offset mod accesssize)<>0 then
  618. exit;
  619. { offset must fit in a signed 7 bit offset }
  620. if (ref.offset>=-(1 shl (6+tcgsizep2size[size]))) and
  621. (ref.offset<=(1 shl (6+tcgsizep2size[size]))-1) then
  622. result:=sr_simple
  623. else
  624. result:=sr_complex;
  625. end;
  626. A_LDUR,A_STUR:
  627. begin
  628. if (ref.addressmode=AM_OFFSET) and
  629. (ref.offset>=-256) and
  630. (ref.offset<=255) then
  631. result:=sr_simple
  632. else
  633. result:=sr_complex;
  634. end;
  635. { todo }
  636. A_LD1,A_LD2,A_LD3,A_LD4,
  637. A_ST1,A_ST2,A_ST3,A_ST4:
  638. internalerror(2014110907);
  639. A_LDAR,
  640. A_LDAXR,
  641. A_LDXR,
  642. A_LDXP,
  643. A_STLR,
  644. A_STLXR,
  645. A_STLXP,
  646. A_STXP,
  647. A_STXR:
  648. begin
  649. if (ref.addressmode=AM_OFFSET) and
  650. (ref.offset=0) then
  651. result:=sr_simple;
  652. end
  653. else
  654. { nothing: result is already sr_internal_illegal };
  655. end;
  656. exit;
  657. end;
  658. { absolute addresses are not supported, have to load them first into
  659. a register }
  660. result:=sr_complex;
  661. end;
  662. function can_be_shifter_operand(opc: tasmop; opnr: longint): boolean;
  663. begin
  664. case opc of
  665. A_ADD,
  666. A_AND,
  667. A_EON,
  668. A_EOR,
  669. A_ORN,
  670. A_ORR,
  671. A_SUB:
  672. result:=opnr=3;
  673. A_BIC,
  674. A_CMN,
  675. A_CMP,
  676. A_MOVK,
  677. A_MOVZ,
  678. A_MOVN,
  679. A_MVN,
  680. A_NEG,
  681. A_TST:
  682. result:=opnr=2;
  683. else
  684. result:=false;
  685. end;
  686. end;
  687. function valid_shifter_operand(opc: tasmop; useszr, usessp, is64bit: boolean; sm: tshiftmode; shiftimm: longint): boolean;
  688. begin
  689. case opc of
  690. A_ADD,
  691. A_SUB,
  692. A_NEG,
  693. A_AND,
  694. A_TST,
  695. A_CMN,
  696. A_CMP:
  697. begin
  698. result:=false;
  699. if not useszr then
  700. result:=
  701. (sm in shiftedregmodes) and
  702. ((shiftimm in [0..31]) or
  703. (is64bit and
  704. (shiftimm in [32..63])));
  705. if not usessp then
  706. result:=
  707. result or
  708. ((sm in extendedregmodes) and
  709. (shiftimm in [0..4]));
  710. end;
  711. A_BIC,
  712. A_EON,
  713. A_EOR,
  714. A_MVN,
  715. A_ORN,
  716. A_ORR:
  717. result:=
  718. (sm in shiftedregmodes) and
  719. (shiftimm in [0..31*(ord(is64bit)+1)+ord(is64bit)]);
  720. A_MOVK,
  721. A_MOVZ,
  722. A_MOVN:
  723. result:=
  724. (sm=SM_LSL) and
  725. ((shiftimm in [0,16]) or
  726. (is64bit and
  727. (shiftimm in [32,48])));
  728. else
  729. result:=false;
  730. end;
  731. end;
  732. function spilling_create_load(const ref: treference; r: tregister): taicpu;
  733. var
  734. op: tasmop;
  735. begin
  736. if (ref.index<>NR_NO) or
  737. (ref.offset<-256) or
  738. (ref.offset>255) then
  739. op:=A_LDR
  740. else
  741. op:=A_LDUR;
  742. result:=spilling_create_op(op,ref,r);
  743. end;
  744. function spilling_create_store(r: tregister; const ref: treference): taicpu;
  745. var
  746. op: tasmop;
  747. begin
  748. if (ref.index<>NR_NO) or
  749. (ref.offset<-256) or
  750. (ref.offset>255) then
  751. op:=A_STR
  752. else
  753. op:=A_STUR;
  754. result:=spilling_create_op(op,ref,r);
  755. end;
  756. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  757. begin
  758. case opcode of
  759. A_B,A_BL,
  760. A_CMN,A_CMP,
  761. A_CCMN,A_CCMP,
  762. A_TST:
  763. result:=operand_read;
  764. A_STR,A_STUR:
  765. if opnr=0 then
  766. result:=operand_read
  767. else
  768. { check for pre/post indexed in spilling_get_operation_type_ref }
  769. result:=operand_read;
  770. A_STLXP,
  771. A_STLXR,
  772. A_STXP,
  773. A_STXR:
  774. if opnr=0 then
  775. result:=operand_write
  776. else
  777. result:=operand_read;
  778. A_STP:
  779. begin
  780. if opnr in [0,1] then
  781. result:=operand_read
  782. else
  783. { check for pre/post indexed in spilling_get_operation_type_ref }
  784. result:=operand_read;
  785. end;
  786. A_LDP,
  787. A_LDXP:
  788. begin
  789. if opnr in [0,1] then
  790. result:=operand_write
  791. else
  792. { check for pre/post indexed in spilling_get_operation_type_ref }
  793. result:=operand_read;
  794. end;
  795. else
  796. if opnr=0 then
  797. result:=operand_write
  798. else
  799. result:=operand_read;
  800. end;
  801. end;
  802. function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
  803. begin
  804. result:=operand_read;
  805. if (oper[opnr]^.ref^.base = reg) and
  806. (oper[opnr]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
  807. result:=operand_readwrite;
  808. end;
  809. procedure BuildInsTabCache;
  810. var
  811. i : longint;
  812. begin
  813. (* new(instabcache);
  814. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  815. i:=0;
  816. while (i<InsTabEntries) do
  817. begin
  818. if InsTabCache^[InsTab[i].Opcode]=-1 then
  819. InsTabCache^[InsTab[i].Opcode]:=i;
  820. inc(i);
  821. end; *)
  822. end;
  823. procedure InitAsm;
  824. begin
  825. if not assigned(instabcache) then
  826. BuildInsTabCache;
  827. end;
  828. procedure DoneAsm;
  829. begin
  830. if assigned(instabcache) then
  831. begin
  832. dispose(instabcache);
  833. instabcache:=nil;
  834. end;
  835. end;
  836. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  837. begin
  838. i.oppostfix:=pf;
  839. result:=i;
  840. end;
  841. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  842. begin
  843. i.condition:=c;
  844. result:=i;
  845. end;
  846. Function SimpleGetNextInstruction(Current: tai; Var Next: tai): Boolean;
  847. Begin
  848. Current:=tai(Current.Next);
  849. While Assigned(Current) And (Current.typ In SkipInstr) Do
  850. Current:=tai(Current.Next);
  851. Next:=Current;
  852. If Assigned(Next) And Not(Next.typ In SkipInstr) Then
  853. Result:=True
  854. Else
  855. Begin
  856. Next:=Nil;
  857. Result:=False;
  858. End;
  859. End;
  860. (*
  861. function armconstequal(hp1,hp2: tai): boolean;
  862. begin
  863. result:=false;
  864. if hp1.typ<>hp2.typ then
  865. exit;
  866. case hp1.typ of
  867. tai_const:
  868. result:=
  869. (tai_const(hp2).sym=tai_const(hp).sym) and
  870. (tai_const(hp2).value=tai_const(hp).value) and
  871. (tai(hp2.previous).typ=ait_label);
  872. tai_const:
  873. result:=
  874. (tai_const(hp2).sym=tai_const(hp).sym) and
  875. (tai_const(hp2).value=tai_const(hp).value) and
  876. (tai(hp2.previous).typ=ait_label);
  877. end;
  878. end;
  879. *)
  880. procedure insertpcrelativedata(list,listtoinsert : TAsmList);
  881. var
  882. curinspos,
  883. penalty,
  884. lastinspos,
  885. { increased for every data element > 4 bytes inserted }
  886. currentsize,
  887. extradataoffset,
  888. limit: longint;
  889. curop : longint;
  890. curtai : tai;
  891. curdatatai,hp,hp2 : tai;
  892. curdata : TAsmList;
  893. l : tasmlabel;
  894. doinsert,
  895. removeref : boolean;
  896. begin
  897. (*
  898. curdata:=TAsmList.create;
  899. lastinspos:=-1;
  900. curinspos:=0;
  901. extradataoffset:=0;
  902. limit:=1016;
  903. curtai:=tai(list.first);
  904. doinsert:=false;
  905. while assigned(curtai) do
  906. begin
  907. { instruction? }
  908. case curtai.typ of
  909. ait_instruction:
  910. begin
  911. { walk through all operand of the instruction }
  912. for curop:=0 to taicpu(curtai).ops-1 do
  913. begin
  914. { reference? }
  915. if (taicpu(curtai).oper[curop]^.typ=top_ref) then
  916. begin
  917. { pc relative symbol? }
  918. curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
  919. if assigned(curdatatai) and
  920. { move only if we're at the first reference of a label }
  921. not(tai_label(curdatatai).moved) then
  922. begin
  923. tai_label(curdatatai).moved:=true;
  924. { check if symbol already used. }
  925. { if yes, reuse the symbol }
  926. hp:=tai(curdatatai.next);
  927. removeref:=false;
  928. if assigned(hp) then
  929. begin
  930. case hp.typ of
  931. ait_const:
  932. begin
  933. if (tai_const(hp).consttype=aitconst_64bit) then
  934. inc(extradataoffset);
  935. end;
  936. ait_comp_64bit,
  937. ait_real_64bit:
  938. begin
  939. inc(extradataoffset);
  940. end;
  941. ait_real_80bit:
  942. begin
  943. inc(extradataoffset,2);
  944. end;
  945. end;
  946. if (hp.typ=ait_const) then
  947. begin
  948. hp2:=tai(curdata.first);
  949. while assigned(hp2) do
  950. begin
  951. { if armconstequal(hp2,hp) then }
  952. if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
  953. and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label)
  954. then
  955. begin
  956. with taicpu(curtai).oper[curop]^.ref^ do
  957. begin
  958. symboldata:=hp2.previous;
  959. symbol:=tai_label(hp2.previous).labsym;
  960. end;
  961. removeref:=true;
  962. break;
  963. end;
  964. hp2:=tai(hp2.next);
  965. end;
  966. end;
  967. end;
  968. { move or remove symbol reference }
  969. repeat
  970. hp:=tai(curdatatai.next);
  971. listtoinsert.remove(curdatatai);
  972. if removeref then
  973. curdatatai.free
  974. else
  975. curdata.concat(curdatatai);
  976. curdatatai:=hp;
  977. until (curdatatai=nil) or (curdatatai.typ=ait_label);
  978. if lastinspos=-1 then
  979. lastinspos:=curinspos;
  980. end;
  981. end;
  982. end;
  983. inc(curinspos);
  984. end;
  985. ait_align:
  986. begin
  987. { code is always 4 byte aligned, so we don't have to take care of .align 2 which would
  988. requires also incrementing curinspos by 1 }
  989. inc(curinspos,(tai_align(curtai).aligntype div 4));
  990. end;
  991. ait_const:
  992. begin
  993. inc(curinspos);
  994. if (tai_const(curtai).consttype=aitconst_64bit) then
  995. inc(curinspos);
  996. end;
  997. ait_real_32bit:
  998. begin
  999. inc(curinspos);
  1000. end;
  1001. ait_comp_64bit,
  1002. ait_real_64bit:
  1003. begin
  1004. inc(curinspos,2);
  1005. end;
  1006. ait_real_80bit:
  1007. begin
  1008. inc(curinspos,3);
  1009. end;
  1010. end;
  1011. { special case for case jump tables }
  1012. if SimpleGetNextInstruction(curtai,hp) and
  1013. (tai(hp).typ=ait_instruction) and
  1014. (taicpu(hp).opcode=A_LDR) and
  1015. (taicpu(hp).oper[0]^.typ=top_reg) and
  1016. (taicpu(hp).oper[0]^.reg=NR_PC) then
  1017. begin
  1018. penalty:=1;
  1019. hp:=tai(hp.next);
  1020. { skip register allocations and comments inserted by the optimizer }
  1021. while assigned(hp) and (hp.typ in [ait_comment,ait_regalloc]) do
  1022. hp:=tai(hp.next);
  1023. while assigned(hp) and (hp.typ=ait_const) do
  1024. begin
  1025. inc(penalty);
  1026. hp:=tai(hp.next);
  1027. end;
  1028. end
  1029. else
  1030. penalty:=0;
  1031. { FLD/FST VFP instructions have a limit of +/- 1024, not 4096 }
  1032. if SimpleGetNextInstruction(curtai,hp) and
  1033. (tai(hp).typ=ait_instruction) and
  1034. ((taicpu(hp).opcode=A_FLDS) or
  1035. (taicpu(hp).opcode=A_FLDD)) then
  1036. limit:=254;
  1037. { don't miss an insert }
  1038. doinsert:=doinsert or
  1039. (not(curdata.empty) and
  1040. (curinspos-lastinspos+penalty+extradataoffset>limit));
  1041. { split only at real instructions else the test below fails }
  1042. if doinsert and (curtai.typ=ait_instruction) and
  1043. (
  1044. { don't split loads of pc to lr and the following move }
  1045. not(
  1046. (taicpu(curtai).opcode=A_MOV) and
  1047. (taicpu(curtai).oper[0]^.typ=top_reg) and
  1048. (taicpu(curtai).oper[0]^.reg=NR_R14) and
  1049. (taicpu(curtai).oper[1]^.typ=top_reg) and
  1050. (taicpu(curtai).oper[1]^.reg=NR_PC)
  1051. )
  1052. ) then
  1053. begin
  1054. lastinspos:=-1;
  1055. extradataoffset:=0;
  1056. limit:=1016;
  1057. doinsert:=false;
  1058. hp:=tai(curtai.next);
  1059. current_asmdata.getjumplabel(l);
  1060. curdata.insert(taicpu.op_sym(A_B,l));
  1061. curdata.concat(tai_label.create(l));
  1062. list.insertlistafter(curtai,curdata);
  1063. curtai:=hp;
  1064. end
  1065. else
  1066. curtai:=tai(curtai.next);
  1067. end;
  1068. list.concatlist(curdata);
  1069. curdata.free;
  1070. *)
  1071. end;
  1072. procedure finalizearmcode(list, listtoinsert: TAsmList);
  1073. begin
  1074. insertpcrelativedata(list, listtoinsert);
  1075. end;
  1076. procedure InsertPData;
  1077. var
  1078. prolog: TAsmList;
  1079. begin
  1080. prolog:=TAsmList.create;
  1081. new_section(prolog,sec_code,'FPC_EH_PROLOG',sizeof(pint),secorder_begin);
  1082. prolog.concat(Tai_const.Createname('_ARM_ExceptionHandler', 0));
  1083. prolog.concat(Tai_const.Create_32bit(0));
  1084. prolog.concat(Tai_symbol.Createname_global('FPC_EH_CODE_START',AT_DATA,0));
  1085. { dummy function }
  1086. prolog.concat(taicpu.op_reg(A_BR,NR_X29));
  1087. current_asmdata.asmlists[al_start].insertList(prolog);
  1088. prolog.Free;
  1089. new_section(current_asmdata.asmlists[al_end],sec_pdata,'',sizeof(pint));
  1090. current_asmdata.asmlists[al_end].concat(Tai_const.Createname('FPC_EH_CODE_START', 0));
  1091. current_asmdata.asmlists[al_end].concat(Tai_const.Create_32bit(longint($ffffff01)));
  1092. end;
  1093. (*
  1094. Floating point instruction format information, taken from the linux kernel
  1095. ARM Floating Point Instruction Classes
  1096. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1097. |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
  1098. |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
  1099. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1100. |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
  1101. |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
  1102. |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
  1103. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1104. CPDT data transfer instructions
  1105. LDF, STF, LFM (copro 2), SFM (copro 2)
  1106. CPDO dyadic arithmetic instructions
  1107. ADF, MUF, SUF, RSF, DVF, RDF,
  1108. POW, RPW, RMF, FML, FDV, FRD, POL
  1109. CPDO monadic arithmetic instructions
  1110. MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
  1111. SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
  1112. CPRT joint arithmetic/data transfer instructions
  1113. FIX (arithmetic followed by load/store)
  1114. FLT (load/store followed by arithmetic)
  1115. CMF, CNF CMFE, CNFE (comparisons)
  1116. WFS, RFS (write/read floating point status register)
  1117. WFC, RFC (write/read floating point control register)
  1118. cond condition codes
  1119. P pre/post index bit: 0 = postindex, 1 = preindex
  1120. U up/down bit: 0 = stack grows down, 1 = stack grows up
  1121. W write back bit: 1 = update base register (Rn)
  1122. L load/store bit: 0 = store, 1 = load
  1123. Rn base register
  1124. Rd destination/source register
  1125. Fd floating point destination register
  1126. Fn floating point source register
  1127. Fm floating point source register or floating point constant
  1128. uv transfer length (TABLE 1)
  1129. wx register count (TABLE 2)
  1130. abcd arithmetic opcode (TABLES 3 & 4)
  1131. ef destination size (rounding precision) (TABLE 5)
  1132. gh rounding mode (TABLE 6)
  1133. j dyadic/monadic bit: 0 = dyadic, 1 = monadic
  1134. i constant bit: 1 = constant (TABLE 6)
  1135. */
  1136. /*
  1137. TABLE 1
  1138. +-------------------------+---+---+---------+---------+
  1139. | Precision | u | v | FPSR.EP | length |
  1140. +-------------------------+---+---+---------+---------+
  1141. | Single | 0 | 0 | x | 1 words |
  1142. | Double | 1 | 1 | x | 2 words |
  1143. | Extended | 1 | 1 | x | 3 words |
  1144. | Packed decimal | 1 | 1 | 0 | 3 words |
  1145. | Expanded packed decimal | 1 | 1 | 1 | 4 words |
  1146. +-------------------------+---+---+---------+---------+
  1147. Note: x = don't care
  1148. */
  1149. /*
  1150. TABLE 2
  1151. +---+---+---------------------------------+
  1152. | w | x | Number of registers to transfer |
  1153. +---+---+---------------------------------+
  1154. | 0 | 1 | 1 |
  1155. | 1 | 0 | 2 |
  1156. | 1 | 1 | 3 |
  1157. | 0 | 0 | 4 |
  1158. +---+---+---------------------------------+
  1159. */
  1160. /*
  1161. TABLE 3: Dyadic Floating Point Opcodes
  1162. +---+---+---+---+----------+-----------------------+-----------------------+
  1163. | a | b | c | d | Mnemonic | Description | Operation |
  1164. +---+---+---+---+----------+-----------------------+-----------------------+
  1165. | 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
  1166. | 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
  1167. | 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
  1168. | 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
  1169. | 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
  1170. | 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
  1171. | 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
  1172. | 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
  1173. | 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
  1174. | 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
  1175. | 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
  1176. | 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
  1177. | 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
  1178. | 1 | 1 | 0 | 1 | | undefined instruction | trap |
  1179. | 1 | 1 | 1 | 0 | | undefined instruction | trap |
  1180. | 1 | 1 | 1 | 1 | | undefined instruction | trap |
  1181. +---+---+---+---+----------+-----------------------+-----------------------+
  1182. Note: POW, RPW, POL are deprecated, and are available for backwards
  1183. compatibility only.
  1184. */
  1185. /*
  1186. TABLE 4: Monadic Floating Point Opcodes
  1187. +---+---+---+---+----------+-----------------------+-----------------------+
  1188. | a | b | c | d | Mnemonic | Description | Operation |
  1189. +---+---+---+---+----------+-----------------------+-----------------------+
  1190. | 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
  1191. | 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
  1192. | 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
  1193. | 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
  1194. | 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
  1195. | 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
  1196. | 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
  1197. | 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
  1198. | 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
  1199. | 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
  1200. | 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
  1201. | 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
  1202. | 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
  1203. | 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
  1204. | 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
  1205. | 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
  1206. +---+---+---+---+----------+-----------------------+-----------------------+
  1207. Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
  1208. available for backwards compatibility only.
  1209. */
  1210. /*
  1211. TABLE 5
  1212. +-------------------------+---+---+
  1213. | Rounding Precision | e | f |
  1214. +-------------------------+---+---+
  1215. | IEEE Single precision | 0 | 0 |
  1216. | IEEE Double precision | 0 | 1 |
  1217. | IEEE Extended precision | 1 | 0 |
  1218. | undefined (trap) | 1 | 1 |
  1219. +-------------------------+---+---+
  1220. */
  1221. /*
  1222. TABLE 5
  1223. +---------------------------------+---+---+
  1224. | Rounding Mode | g | h |
  1225. +---------------------------------+---+---+
  1226. | Round to nearest (default) | 0 | 0 |
  1227. | Round toward plus infinity | 0 | 1 |
  1228. | Round toward negative infinity | 1 | 0 |
  1229. | Round toward zero | 1 | 1 |
  1230. +---------------------------------+---+---+
  1231. *)
  1232. function taicpu.GetString:string;
  1233. var
  1234. i : longint;
  1235. s : string;
  1236. addsize : boolean;
  1237. begin
  1238. s:='['+gas_op2str[opcode];
  1239. for i:=0 to ops-1 do
  1240. begin
  1241. with oper[i]^ do
  1242. begin
  1243. if i=0 then
  1244. s:=s+' '
  1245. else
  1246. s:=s+',';
  1247. { type }
  1248. addsize:=false;
  1249. if (ot and OT_VREG)=OT_VREG then
  1250. s:=s+'vreg'
  1251. else
  1252. if (ot and OT_FPUREG)=OT_FPUREG then
  1253. s:=s+'fpureg'
  1254. else
  1255. if (ot and OT_REGISTER)=OT_REGISTER then
  1256. begin
  1257. s:=s+'reg';
  1258. addsize:=true;
  1259. end
  1260. else
  1261. if (ot and OT_REGLIST)=OT_REGLIST then
  1262. begin
  1263. s:=s+'reglist';
  1264. addsize:=false;
  1265. end
  1266. else
  1267. if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  1268. begin
  1269. s:=s+'imm';
  1270. addsize:=true;
  1271. end
  1272. else
  1273. if (ot and OT_MEMORY)=OT_MEMORY then
  1274. begin
  1275. s:=s+'mem';
  1276. addsize:=true;
  1277. if (ot and OT_AM2)<>0 then
  1278. s:=s+' am2 ';
  1279. end
  1280. else
  1281. s:=s+'???';
  1282. { size }
  1283. if addsize then
  1284. begin
  1285. if (ot and OT_BITS8)<>0 then
  1286. s:=s+'8'
  1287. else
  1288. if (ot and OT_BITS16)<>0 then
  1289. s:=s+'24'
  1290. else
  1291. if (ot and OT_BITS32)<>0 then
  1292. s:=s+'32'
  1293. else
  1294. if (ot and OT_BITSSHIFTER)<>0 then
  1295. s:=s+'shifter'
  1296. else
  1297. s:=s+'??';
  1298. { signed }
  1299. if (ot and OT_SIGNED)<>0 then
  1300. s:=s+'s';
  1301. end;
  1302. end;
  1303. end;
  1304. GetString:=s+']';
  1305. end;
  1306. procedure taicpu.ResetPass1;
  1307. begin
  1308. { we need to reset everything here, because the choosen insentry
  1309. can be invalid for a new situation where the previously optimized
  1310. insentry is not correct }
  1311. InsEntry:=nil;
  1312. InsSize:=0;
  1313. LastInsOffset:=-1;
  1314. end;
  1315. procedure taicpu.ResetPass2;
  1316. begin
  1317. { we are here in a second pass, check if the instruction can be optimized }
  1318. if assigned(InsEntry) and
  1319. ((InsEntry^.flags and IF_PASS2)<>0) then
  1320. begin
  1321. InsEntry:=nil;
  1322. InsSize:=0;
  1323. end;
  1324. LastInsOffset:=-1;
  1325. end;
  1326. function taicpu.CheckIfValid:boolean;
  1327. begin
  1328. Result:=False; { unimplemented }
  1329. end;
  1330. function taicpu.Pass1(objdata:TObjData):longint;
  1331. begin
  1332. Pass1:=0;
  1333. LastInsOffset:=-1;
  1334. end;
  1335. procedure taicpu.Pass2(objdata:TObjData);
  1336. begin
  1337. { error in pass1 ? }
  1338. if insentry=nil then
  1339. exit;
  1340. current_filepos:=fileinfo;
  1341. { Generate the instruction }
  1342. GenCode(objdata);
  1343. end;
  1344. procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
  1345. begin
  1346. end;
  1347. procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
  1348. begin
  1349. end;
  1350. procedure taicpu.ppubuildderefimploper(var o:toper);
  1351. begin
  1352. end;
  1353. procedure taicpu.ppuderefoper(var o:toper);
  1354. begin
  1355. end;
  1356. function taicpu.InsEnd:longint;
  1357. begin
  1358. Result:=0; { unimplemented }
  1359. end;
  1360. procedure taicpu.create_ot(objdata:TObjData);
  1361. begin
  1362. end;
  1363. function taicpu.Matches(p:PInsEntry):longint;
  1364. begin
  1365. result:=0; { unimplemented }
  1366. end;
  1367. function taicpu.calcsize(p:PInsEntry):shortint;
  1368. begin
  1369. result:=4;
  1370. end;
  1371. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  1372. begin
  1373. Result:=False; { unimplemented }
  1374. end;
  1375. procedure taicpu.Swapoperands;
  1376. begin
  1377. end;
  1378. function taicpu.FindInsentry(objdata:TObjData):boolean;
  1379. begin
  1380. result:=false;
  1381. end;
  1382. procedure taicpu.gencode(objdata:TObjData);
  1383. var
  1384. bytes : dword;
  1385. i_field : byte;
  1386. procedure setshifterop(op : byte);
  1387. begin
  1388. case oper[op]^.typ of
  1389. top_const:
  1390. begin
  1391. i_field:=1;
  1392. bytes:=bytes or dword(oper[op]^.val and $fff);
  1393. end;
  1394. top_reg:
  1395. begin
  1396. i_field:=0;
  1397. bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
  1398. { does a real shifter op follow? }
  1399. if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
  1400. begin
  1401. end;
  1402. end;
  1403. else
  1404. internalerror(2005091103);
  1405. end;
  1406. end;
  1407. begin
  1408. bytes:=$0;
  1409. { evaluate and set condition code }
  1410. { condition code allowed? }
  1411. { setup rest of the instruction }
  1412. case insentry^.code[0] of
  1413. #$08:
  1414. begin
  1415. { set instruction code }
  1416. bytes:=bytes or (ord(insentry^.code[1]) shl 26);
  1417. bytes:=bytes or (ord(insentry^.code[2]) shl 21);
  1418. { set destination }
  1419. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  1420. { create shifter op }
  1421. setshifterop(1);
  1422. { set i field }
  1423. bytes:=bytes or (i_field shl 25);
  1424. { set s if necessary }
  1425. if oppostfix=PF_S then
  1426. bytes:=bytes or (1 shl 20);
  1427. end;
  1428. #$ff:
  1429. internalerror(2005091101);
  1430. else
  1431. internalerror(2005091102);
  1432. end;
  1433. { we're finished, write code }
  1434. objdata.writebytes(bytes,sizeof(bytes));
  1435. end;
  1436. {$ifdef dummy}
  1437. (*
  1438. static void gencode (long segment, long offset, int bits,
  1439. insn *ins, char *codes, long insn_end)
  1440. {
  1441. int has_S_code; /* S - setflag */
  1442. int has_B_code; /* B - setflag */
  1443. int has_T_code; /* T - setflag */
  1444. int has_W_code; /* ! => W flag */
  1445. int has_F_code; /* ^ => S flag */
  1446. int keep;
  1447. unsigned char c;
  1448. unsigned char bytes[4];
  1449. long data, size;
  1450. static int cc_code[] = /* bit pattern of cc */
  1451. { /* order as enum in */
  1452. 0x0E, 0x03, 0x02, 0x00, /* nasm.h */
  1453. 0x0A, 0x0C, 0x08, 0x0D,
  1454. 0x09, 0x0B, 0x04, 0x01,
  1455. 0x05, 0x07, 0x06,
  1456. };
  1457. #ifdef DEBUG
  1458. static char *CC[] =
  1459. { /* condition code names */
  1460. "AL", "CC", "CS", "EQ",
  1461. "GE", "GT", "HI", "LE",
  1462. "LS", "LT", "MI", "NE",
  1463. "PL", "VC", "VS", "",
  1464. "S"
  1465. };
  1466. has_S_code = (ins->condition & C_SSETFLAG);
  1467. has_B_code = (ins->condition & C_BSETFLAG);
  1468. has_T_code = (ins->condition & C_TSETFLAG);
  1469. has_W_code = (ins->condition & C_EXSETFLAG);
  1470. has_F_code = (ins->condition & C_FSETFLAG);
  1471. ins->condition = (ins->condition & 0x0F);
  1472. if (rt_debug)
  1473. {
  1474. printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
  1475. CC[ins->condition & 0x0F]);
  1476. if (has_S_code)
  1477. printf ("S");
  1478. if (has_B_code)
  1479. printf ("B");
  1480. if (has_T_code)
  1481. printf ("T");
  1482. if (has_W_code)
  1483. printf ("!");
  1484. if (has_F_code)
  1485. printf ("^");
  1486. printf ("\n");
  1487. c = *codes;
  1488. printf (" (%d) decode - '0x%02X'\n", ins->operands, c);
  1489. bytes[0] = 0xB;
  1490. bytes[1] = 0xE;
  1491. bytes[2] = 0xE;
  1492. bytes[3] = 0xF;
  1493. }
  1494. // First condition code in upper nibble
  1495. if (ins->condition < C_NONE)
  1496. {
  1497. c = cc_code[ins->condition] << 4;
  1498. }
  1499. else
  1500. {
  1501. c = cc_code[C_AL] << 4; // is often ALWAYS but not always
  1502. }
  1503. switch (keep = *codes)
  1504. {
  1505. case 1:
  1506. // B, BL
  1507. ++codes;
  1508. c |= *codes++;
  1509. bytes[0] = c;
  1510. if (ins->oprs[0].segment != segment)
  1511. {
  1512. // fais une relocation
  1513. c = 1;
  1514. data = 0; // Let the linker locate ??
  1515. }
  1516. else
  1517. {
  1518. c = 0;
  1519. data = ins->oprs[0].offset - (offset + 8);
  1520. if (data % 4)
  1521. {
  1522. errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
  1523. }
  1524. }
  1525. if (data >= 0x1000)
  1526. {
  1527. errfunc (ERR_NONFATAL, "too long offset");
  1528. }
  1529. data = data >> 2;
  1530. bytes[1] = (data >> 16) & 0xFF;
  1531. bytes[2] = (data >> 8) & 0xFF;
  1532. bytes[3] = (data ) & 0xFF;
  1533. if (c == 1)
  1534. {
  1535. // out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
  1536. out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
  1537. }
  1538. else
  1539. {
  1540. out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1541. }
  1542. return;
  1543. case 2:
  1544. // SWI
  1545. ++codes;
  1546. c |= *codes++;
  1547. bytes[0] = c;
  1548. data = ins->oprs[0].offset;
  1549. bytes[1] = (data >> 16) & 0xFF;
  1550. bytes[2] = (data >> 8) & 0xFF;
  1551. bytes[3] = (data) & 0xFF;
  1552. out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1553. return;
  1554. case 3:
  1555. // BX
  1556. ++codes;
  1557. c |= *codes++;
  1558. bytes[0] = c;
  1559. bytes[1] = *codes++;
  1560. bytes[2] = *codes++;
  1561. bytes[3] = *codes++;
  1562. c = regval (&ins->oprs[0],1);
  1563. if (c == 15) // PC
  1564. {
  1565. errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
  1566. }
  1567. else if (c > 15)
  1568. {
  1569. errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
  1570. }
  1571. bytes[3] |= (c & 0x0F);
  1572. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1573. return;
  1574. case 4: // AND Rd,Rn,Rm
  1575. case 5: // AND Rd,Rn,Rm,<shift>Rs
  1576. case 6: // AND Rd,Rn,Rm,<shift>imm
  1577. case 7: // AND Rd,Rn,<shift>imm
  1578. ++codes;
  1579. #ifdef DEBUG
  1580. if (rt_debug)
  1581. {
  1582. printf (" decode - '0x%02X'\n", keep);
  1583. printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
  1584. }
  1585. #endif
  1586. bytes[0] = c | *codes;
  1587. ++codes;
  1588. bytes[1] = *codes;
  1589. if (has_S_code)
  1590. bytes[1] |= 0x10;
  1591. c = regval (&ins->oprs[1],1);
  1592. // Rn in low nibble
  1593. bytes[1] |= c;
  1594. // Rd in high nibble
  1595. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1596. if (keep != 7)
  1597. {
  1598. // Rm in low nibble
  1599. bytes[3] = regval (&ins->oprs[2],1);
  1600. }
  1601. // Shifts if any
  1602. if (keep == 5 || keep == 6)
  1603. {
  1604. // Shift in bytes 2 and 3
  1605. if (keep == 5)
  1606. {
  1607. // Rs
  1608. c = regval (&ins->oprs[3],1);
  1609. bytes[2] |= c;
  1610. c = 0x10; // Set bit 4 in byte[3]
  1611. }
  1612. if (keep == 6)
  1613. {
  1614. c = (ins->oprs[3].offset) & 0x1F;
  1615. // #imm
  1616. bytes[2] |= c >> 1;
  1617. if (c & 0x01)
  1618. {
  1619. bytes[3] |= 0x80;
  1620. }
  1621. c = 0; // Clr bit 4 in byte[3]
  1622. }
  1623. // <shift>
  1624. c |= shiftval (&ins->oprs[3]) << 5;
  1625. bytes[3] |= c;
  1626. }
  1627. // reg,reg,imm
  1628. if (keep == 7)
  1629. {
  1630. int shimm;
  1631. shimm = imm_shift (ins->oprs[2].offset);
  1632. if (shimm == -1)
  1633. {
  1634. errfunc (ERR_NONFATAL, "cannot create that constant");
  1635. }
  1636. bytes[3] = shimm & 0xFF;
  1637. bytes[2] |= (shimm & 0xF00) >> 8;
  1638. }
  1639. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1640. return;
  1641. case 8: // MOV Rd,Rm
  1642. case 9: // MOV Rd,Rm,<shift>Rs
  1643. case 0xA: // MOV Rd,Rm,<shift>imm
  1644. case 0xB: // MOV Rd,<shift>imm
  1645. ++codes;
  1646. #ifdef DEBUG
  1647. if (rt_debug)
  1648. {
  1649. printf (" decode - '0x%02X'\n", keep);
  1650. printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
  1651. }
  1652. #endif
  1653. bytes[0] = c | *codes;
  1654. ++codes;
  1655. bytes[1] = *codes;
  1656. if (has_S_code)
  1657. bytes[1] |= 0x10;
  1658. // Rd in high nibble
  1659. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1660. if (keep != 0x0B)
  1661. {
  1662. // Rm in low nibble
  1663. bytes[3] = regval (&ins->oprs[1],1);
  1664. }
  1665. // Shifts if any
  1666. if (keep == 0x09 || keep == 0x0A)
  1667. {
  1668. // Shift in bytes 2 and 3
  1669. if (keep == 0x09)
  1670. {
  1671. // Rs
  1672. c = regval (&ins->oprs[2],1);
  1673. bytes[2] |= c;
  1674. c = 0x10; // Set bit 4 in byte[3]
  1675. }
  1676. if (keep == 0x0A)
  1677. {
  1678. c = (ins->oprs[2].offset) & 0x1F;
  1679. // #imm
  1680. bytes[2] |= c >> 1;
  1681. if (c & 0x01)
  1682. {
  1683. bytes[3] |= 0x80;
  1684. }
  1685. c = 0; // Clr bit 4 in byte[3]
  1686. }
  1687. // <shift>
  1688. c |= shiftval (&ins->oprs[2]) << 5;
  1689. bytes[3] |= c;
  1690. }
  1691. // reg,imm
  1692. if (keep == 0x0B)
  1693. {
  1694. int shimm;
  1695. shimm = imm_shift (ins->oprs[1].offset);
  1696. if (shimm == -1)
  1697. {
  1698. errfunc (ERR_NONFATAL, "cannot create that constant");
  1699. }
  1700. bytes[3] = shimm & 0xFF;
  1701. bytes[2] |= (shimm & 0xF00) >> 8;
  1702. }
  1703. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1704. return;
  1705. case 0xC: // CMP Rn,Rm
  1706. case 0xD: // CMP Rn,Rm,<shift>Rs
  1707. case 0xE: // CMP Rn,Rm,<shift>imm
  1708. case 0xF: // CMP Rn,<shift>imm
  1709. ++codes;
  1710. bytes[0] = c | *codes++;
  1711. bytes[1] = *codes;
  1712. // Implicit S code
  1713. bytes[1] |= 0x10;
  1714. c = regval (&ins->oprs[0],1);
  1715. // Rn in low nibble
  1716. bytes[1] |= c;
  1717. // No destination
  1718. bytes[2] = 0;
  1719. if (keep != 0x0B)
  1720. {
  1721. // Rm in low nibble
  1722. bytes[3] = regval (&ins->oprs[1],1);
  1723. }
  1724. // Shifts if any
  1725. if (keep == 0x0D || keep == 0x0E)
  1726. {
  1727. // Shift in bytes 2 and 3
  1728. if (keep == 0x0D)
  1729. {
  1730. // Rs
  1731. c = regval (&ins->oprs[2],1);
  1732. bytes[2] |= c;
  1733. c = 0x10; // Set bit 4 in byte[3]
  1734. }
  1735. if (keep == 0x0E)
  1736. {
  1737. c = (ins->oprs[2].offset) & 0x1F;
  1738. // #imm
  1739. bytes[2] |= c >> 1;
  1740. if (c & 0x01)
  1741. {
  1742. bytes[3] |= 0x80;
  1743. }
  1744. c = 0; // Clr bit 4 in byte[3]
  1745. }
  1746. // <shift>
  1747. c |= shiftval (&ins->oprs[2]) << 5;
  1748. bytes[3] |= c;
  1749. }
  1750. // reg,imm
  1751. if (keep == 0x0F)
  1752. {
  1753. int shimm;
  1754. shimm = imm_shift (ins->oprs[1].offset);
  1755. if (shimm == -1)
  1756. {
  1757. errfunc (ERR_NONFATAL, "cannot create that constant");
  1758. }
  1759. bytes[3] = shimm & 0xFF;
  1760. bytes[2] |= (shimm & 0xF00) >> 8;
  1761. }
  1762. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1763. return;
  1764. case 0x10: // MRS Rd,<psr>
  1765. ++codes;
  1766. bytes[0] = c | *codes++;
  1767. bytes[1] = *codes++;
  1768. // Rd
  1769. c = regval (&ins->oprs[0],1);
  1770. bytes[2] = c << 4;
  1771. bytes[3] = 0;
  1772. c = ins->oprs[1].basereg;
  1773. if (c == R_CPSR || c == R_SPSR)
  1774. {
  1775. if (c == R_SPSR)
  1776. {
  1777. bytes[1] |= 0x40;
  1778. }
  1779. }
  1780. else
  1781. {
  1782. errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
  1783. }
  1784. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1785. return;
  1786. case 0x11: // MSR <psr>,Rm
  1787. case 0x12: // MSR <psrf>,Rm
  1788. case 0x13: // MSR <psrf>,#expression
  1789. ++codes;
  1790. bytes[0] = c | *codes++;
  1791. bytes[1] = *codes++;
  1792. bytes[2] = *codes;
  1793. if (keep == 0x11 || keep == 0x12)
  1794. {
  1795. // Rm
  1796. c = regval (&ins->oprs[1],1);
  1797. bytes[3] = c;
  1798. }
  1799. else
  1800. {
  1801. int shimm;
  1802. shimm = imm_shift (ins->oprs[1].offset);
  1803. if (shimm == -1)
  1804. {
  1805. errfunc (ERR_NONFATAL, "cannot create that constant");
  1806. }
  1807. bytes[3] = shimm & 0xFF;
  1808. bytes[2] |= (shimm & 0xF00) >> 8;
  1809. }
  1810. c = ins->oprs[0].basereg;
  1811. if ( keep == 0x11)
  1812. {
  1813. if ( c == R_CPSR || c == R_SPSR)
  1814. {
  1815. if ( c== R_SPSR)
  1816. {
  1817. bytes[1] |= 0x40;
  1818. }
  1819. }
  1820. else
  1821. {
  1822. errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
  1823. }
  1824. }
  1825. else
  1826. {
  1827. if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
  1828. {
  1829. if ( c== R_SPSR_FLG)
  1830. {
  1831. bytes[1] |= 0x40;
  1832. }
  1833. }
  1834. else
  1835. {
  1836. errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
  1837. }
  1838. }
  1839. break;
  1840. case 0x14: // MUL Rd,Rm,Rs
  1841. case 0x15: // MULA Rd,Rm,Rs,Rn
  1842. ++codes;
  1843. bytes[0] = c | *codes++;
  1844. bytes[1] = *codes++;
  1845. bytes[3] = *codes;
  1846. // Rd
  1847. bytes[1] |= regval (&ins->oprs[0],1);
  1848. if (has_S_code)
  1849. bytes[1] |= 0x10;
  1850. // Rm
  1851. bytes[3] |= regval (&ins->oprs[1],1);
  1852. // Rs
  1853. bytes[2] = regval (&ins->oprs[2],1);
  1854. if (keep == 0x15)
  1855. {
  1856. bytes[2] |= regval (&ins->oprs[3],1) << 4;
  1857. }
  1858. break;
  1859. case 0x16: // SMLAL RdHi,RdLo,Rm,Rs
  1860. ++codes;
  1861. bytes[0] = c | *codes++;
  1862. bytes[1] = *codes++;
  1863. bytes[3] = *codes;
  1864. // RdHi
  1865. bytes[1] |= regval (&ins->oprs[1],1);
  1866. if (has_S_code)
  1867. bytes[1] |= 0x10;
  1868. // RdLo
  1869. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1870. // Rm
  1871. bytes[3] |= regval (&ins->oprs[2],1);
  1872. // Rs
  1873. bytes[2] |= regval (&ins->oprs[3],1);
  1874. break;
  1875. case 0x17: // LDR Rd, expression
  1876. ++codes;
  1877. bytes[0] = c | *codes++;
  1878. bytes[1] = *codes++;
  1879. // Rd
  1880. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1881. if (has_B_code)
  1882. bytes[1] |= 0x40;
  1883. if (has_T_code)
  1884. {
  1885. errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
  1886. }
  1887. if (has_W_code)
  1888. {
  1889. errfunc (ERR_NONFATAL, "'!' not allowed");
  1890. }
  1891. // Rn - implicit R15
  1892. bytes[1] |= 0xF;
  1893. if (ins->oprs[1].segment != segment)
  1894. {
  1895. errfunc (ERR_NONFATAL, "label not in same segment");
  1896. }
  1897. data = ins->oprs[1].offset - (offset + 8);
  1898. if (data < 0)
  1899. {
  1900. data = -data;
  1901. }
  1902. else
  1903. {
  1904. bytes[1] |= 0x80;
  1905. }
  1906. if (data >= 0x1000)
  1907. {
  1908. errfunc (ERR_NONFATAL, "too long offset");
  1909. }
  1910. bytes[2] |= ((data & 0xF00) >> 8);
  1911. bytes[3] = data & 0xFF;
  1912. break;
  1913. case 0x18: // LDR Rd, [Rn]
  1914. ++codes;
  1915. bytes[0] = c | *codes++;
  1916. bytes[1] = *codes++;
  1917. // Rd
  1918. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1919. if (has_B_code)
  1920. bytes[1] |= 0x40;
  1921. if (has_T_code)
  1922. {
  1923. bytes[1] |= 0x20; // write-back
  1924. }
  1925. else
  1926. {
  1927. bytes[0] |= 0x01; // implicit pre-index mode
  1928. }
  1929. if (has_W_code)
  1930. {
  1931. bytes[1] |= 0x20; // write-back
  1932. }
  1933. // Rn
  1934. c = regval (&ins->oprs[1],1);
  1935. bytes[1] |= c;
  1936. if (c == 0x15) // R15
  1937. data = -8;
  1938. else
  1939. data = 0;
  1940. if (data < 0)
  1941. {
  1942. data = -data;
  1943. }
  1944. else
  1945. {
  1946. bytes[1] |= 0x80;
  1947. }
  1948. bytes[2] |= ((data & 0xF00) >> 8);
  1949. bytes[3] = data & 0xFF;
  1950. break;
  1951. case 0x19: // LDR Rd, [Rn,#expression]
  1952. case 0x20: // LDR Rd, [Rn,Rm]
  1953. case 0x21: // LDR Rd, [Rn,Rm,shift]
  1954. ++codes;
  1955. bytes[0] = c | *codes++;
  1956. bytes[1] = *codes++;
  1957. // Rd
  1958. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1959. if (has_B_code)
  1960. bytes[1] |= 0x40;
  1961. // Rn
  1962. c = regval (&ins->oprs[1],1);
  1963. bytes[1] |= c;
  1964. if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
  1965. {
  1966. bytes[0] |= 0x01; // pre-index mode
  1967. if (has_W_code)
  1968. {
  1969. bytes[1] |= 0x20;
  1970. }
  1971. if (has_T_code)
  1972. {
  1973. errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
  1974. }
  1975. }
  1976. else
  1977. {
  1978. if (has_T_code) // Forced write-back in post-index mode
  1979. {
  1980. bytes[1] |= 0x20;
  1981. }
  1982. if (has_W_code)
  1983. {
  1984. errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
  1985. }
  1986. }
  1987. if (keep == 0x19)
  1988. {
  1989. data = ins->oprs[2].offset;
  1990. if (data < 0)
  1991. {
  1992. data = -data;
  1993. }
  1994. else
  1995. {
  1996. bytes[1] |= 0x80;
  1997. }
  1998. if (data >= 0x1000)
  1999. {
  2000. errfunc (ERR_NONFATAL, "too long offset");
  2001. }
  2002. bytes[2] |= ((data & 0xF00) >> 8);
  2003. bytes[3] = data & 0xFF;
  2004. }
  2005. else
  2006. {
  2007. if (ins->oprs[2].minus == 0)
  2008. {
  2009. bytes[1] |= 0x80;
  2010. }
  2011. c = regval (&ins->oprs[2],1);
  2012. bytes[3] = c;
  2013. if (keep == 0x21)
  2014. {
  2015. c = ins->oprs[3].offset;
  2016. if (c > 0x1F)
  2017. {
  2018. errfunc (ERR_NONFATAL, "too large shiftvalue");
  2019. c = c & 0x1F;
  2020. }
  2021. bytes[2] |= c >> 1;
  2022. if (c & 0x01)
  2023. {
  2024. bytes[3] |= 0x80;
  2025. }
  2026. bytes[3] |= shiftval (&ins->oprs[3]) << 5;
  2027. }
  2028. }
  2029. break;
  2030. case 0x22: // LDRH Rd, expression
  2031. ++codes;
  2032. bytes[0] = c | 0x01; // Implicit pre-index
  2033. bytes[1] = *codes++;
  2034. // Rd
  2035. bytes[2] = regval (&ins->oprs[0],1) << 4;
  2036. // Rn - implicit R15
  2037. bytes[1] |= 0xF;
  2038. if (ins->oprs[1].segment != segment)
  2039. {
  2040. errfunc (ERR_NONFATAL, "label not in same segment");
  2041. }
  2042. data = ins->oprs[1].offset - (offset + 8);
  2043. if (data < 0)
  2044. {
  2045. data = -data;
  2046. }
  2047. else
  2048. {
  2049. bytes[1] |= 0x80;
  2050. }
  2051. if (data >= 0x100)
  2052. {
  2053. errfunc (ERR_NONFATAL, "too long offset");
  2054. }
  2055. bytes[3] = *codes++;
  2056. bytes[2] |= ((data & 0xF0) >> 4);
  2057. bytes[3] |= data & 0xF;
  2058. break;
  2059. case 0x23: // LDRH Rd, Rn
  2060. ++codes;
  2061. bytes[0] = c | 0x01; // Implicit pre-index
  2062. bytes[1] = *codes++;
  2063. // Rd
  2064. bytes[2] = regval (&ins->oprs[0],1) << 4;
  2065. // Rn
  2066. c = regval (&ins->oprs[1],1);
  2067. bytes[1] |= c;
  2068. if (c == 0x15) // R15
  2069. data = -8;
  2070. else
  2071. data = 0;
  2072. if (data < 0)
  2073. {
  2074. data = -data;
  2075. }
  2076. else
  2077. {
  2078. bytes[1] |= 0x80;
  2079. }
  2080. if (data >= 0x100)
  2081. {
  2082. errfunc (ERR_NONFATAL, "too long offset");
  2083. }
  2084. bytes[3] = *codes++;
  2085. bytes[2] |= ((data & 0xF0) >> 4);
  2086. bytes[3] |= data & 0xF;
  2087. break;
  2088. case 0x24: // LDRH Rd, Rn, expression
  2089. case 0x25: // LDRH Rd, Rn, Rm
  2090. ++codes;
  2091. bytes[0] = c;
  2092. bytes[1] = *codes++;
  2093. // Rd
  2094. bytes[2] = regval (&ins->oprs[0],1) << 4;
  2095. // Rn
  2096. c = regval (&ins->oprs[1],1);
  2097. bytes[1] |= c;
  2098. if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
  2099. {
  2100. bytes[0] |= 0x01; // pre-index mode
  2101. if (has_W_code)
  2102. {
  2103. bytes[1] |= 0x20;
  2104. }
  2105. }
  2106. else
  2107. {
  2108. if (has_W_code)
  2109. {
  2110. errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
  2111. }
  2112. }
  2113. bytes[3] = *codes++;
  2114. if (keep == 0x24)
  2115. {
  2116. data = ins->oprs[2].offset;
  2117. if (data < 0)
  2118. {
  2119. data = -data;
  2120. }
  2121. else
  2122. {
  2123. bytes[1] |= 0x80;
  2124. }
  2125. if (data >= 0x100)
  2126. {
  2127. errfunc (ERR_NONFATAL, "too long offset");
  2128. }
  2129. bytes[2] |= ((data & 0xF0) >> 4);
  2130. bytes[3] |= data & 0xF;
  2131. }
  2132. else
  2133. {
  2134. if (ins->oprs[2].minus == 0)
  2135. {
  2136. bytes[1] |= 0x80;
  2137. }
  2138. c = regval (&ins->oprs[2],1);
  2139. bytes[3] |= c;
  2140. }
  2141. break;
  2142. case 0x26: // LDM/STM Rn, {reg-list}
  2143. ++codes;
  2144. bytes[0] = c;
  2145. bytes[0] |= ( *codes >> 4) & 0xF;
  2146. bytes[1] = ( *codes << 4) & 0xF0;
  2147. ++codes;
  2148. if (has_W_code)
  2149. {
  2150. bytes[1] |= 0x20;
  2151. }
  2152. if (has_F_code)
  2153. {
  2154. bytes[1] |= 0x40;
  2155. }
  2156. // Rn
  2157. bytes[1] |= regval (&ins->oprs[0],1);
  2158. data = ins->oprs[1].basereg;
  2159. bytes[2] = ((data >> 8) & 0xFF);
  2160. bytes[3] = (data & 0xFF);
  2161. break;
  2162. case 0x27: // SWP Rd, Rm, [Rn]
  2163. ++codes;
  2164. bytes[0] = c;
  2165. bytes[0] |= *codes++;
  2166. bytes[1] = regval (&ins->oprs[2],1);
  2167. if (has_B_code)
  2168. {
  2169. bytes[1] |= 0x40;
  2170. }
  2171. bytes[2] = regval (&ins->oprs[0],1) << 4;
  2172. bytes[3] = *codes++;
  2173. bytes[3] |= regval (&ins->oprs[1],1);
  2174. break;
  2175. default:
  2176. errfunc (ERR_FATAL, "unknown decoding of instruction");
  2177. bytes[0] = c;
  2178. // And a fix nibble
  2179. ++codes;
  2180. bytes[0] |= *codes++;
  2181. if ( *codes == 0x01) // An I bit
  2182. {
  2183. }
  2184. if ( *codes == 0x02) // An I bit
  2185. {
  2186. }
  2187. ++codes;
  2188. }
  2189. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  2190. }
  2191. *)
  2192. {$endif dummy}
  2193. begin
  2194. cai_align:=tai_align;
  2195. end.