aasmcpu.pas 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185
  1. {
  2. Copyright (c) 2003 by Florian Klaempfl
  3. Contains the assembler object for the ARM
  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,
  23. symtype,
  24. cpubase,cpuinfo,cgbase,cgutils;
  25. const
  26. { "mov reg,reg" source operand number }
  27. O_MOV_SOURCE = 1;
  28. { "mov reg,reg" source operand number }
  29. O_MOV_DEST = 0;
  30. { Operand types }
  31. OT_NONE = $00000000;
  32. OT_BITS8 = $00000001; { size, and other attributes, of the operand }
  33. OT_BITS16 = $00000002;
  34. OT_BITS32 = $00000004;
  35. OT_BITS64 = $00000008; { FPU only }
  36. OT_BITS80 = $00000010;
  37. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  38. OT_NEAR = $00000040;
  39. OT_SHORT = $00000080;
  40. OT_BITSTINY = $00000100; { fpu constant }
  41. OT_SIZE_MASK = $000000FF; { all the size attributes }
  42. OT_NON_SIZE = longint(not OT_SIZE_MASK);
  43. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  44. OT_TO = $00000200; { operand is followed by a colon }
  45. { reverse effect in FADD, FSUB &c }
  46. OT_COLON = $00000400;
  47. OT_REGISTER = $00001000;
  48. OT_IMMEDIATE = $00002000;
  49. OT_REGLIST = $00008000;
  50. OT_IMM8 = $00002001;
  51. OT_IMM16 = $00002002;
  52. OT_IMM32 = $00002004;
  53. OT_IMM64 = $00002008;
  54. OT_IMM80 = $00002010;
  55. OT_IMMTINY = $00002100;
  56. OT_IMMEDIATEFPU = OT_IMMTINY;
  57. OT_REGMEM = $00200000; { for r/m, ie EA, operands }
  58. OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
  59. OT_REG8 = $00201001;
  60. OT_REG16 = $00201002;
  61. OT_REG32 = $00201004;
  62. OT_REG64 = $00201008;
  63. OT_VREG = $00201010; { vector register }
  64. OT_MEMORY = $00204000; { register number in 'basereg' }
  65. OT_MEM8 = $00204001;
  66. OT_MEM16 = $00204002;
  67. OT_MEM32 = $00204004;
  68. OT_MEM64 = $00204008;
  69. OT_MEM80 = $00204010;
  70. OT_FPUREG = $01000000; { floating point stack registers }
  71. OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
  72. { a mask for the following }
  73. OT_MEM_OFFS = $00604000; { special type of EA }
  74. { simple [address] offset }
  75. OT_ONENESS = $00800000; { special type of immediate operand }
  76. { so UNITY == IMMEDIATE | ONENESS }
  77. OT_UNITY = $00802000; { for shift/rotate instructions }
  78. instabentries = {$i armnop.inc}
  79. maxinfolen = 5;
  80. IF_NONE = $00000000;
  81. IF_ARMMASK = $000F0000;
  82. IF_ARM7 = $00070000;
  83. IF_FPMASK = $00F00000;
  84. IF_FPA = $00100000;
  85. { if the instruction can change in a second pass }
  86. IF_PASS2 = longint($80000000);
  87. type
  88. TInsTabCache=array[TasmOp] of longint;
  89. PInsTabCache=^TInsTabCache;
  90. tinsentry = record
  91. opcode : tasmop;
  92. ops : byte;
  93. optypes : array[0..3] of longint;
  94. code : array[0..maxinfolen] of char;
  95. flags : longint;
  96. end;
  97. pinsentry=^tinsentry;
  98. const
  99. InsTab : array[0..instabentries-1] of TInsEntry={$i armtab.inc}
  100. var
  101. InsTabCache : PInsTabCache;
  102. type
  103. taicpu = class(tai_cpu_abstract)
  104. oppostfix : TOpPostfix;
  105. roundingmode : troundingmode;
  106. procedure loadshifterop(opidx:longint;const so:tshifterop);
  107. procedure loadregset(opidx:longint;const s:tcpuregisterset);
  108. constructor op_none(op : tasmop);
  109. constructor op_reg(op : tasmop;_op1 : tregister);
  110. constructor op_const(op : tasmop;_op1 : longint);
  111. constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  112. constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  113. constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  114. constructor op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
  115. constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  116. constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  117. constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  118. constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  119. constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  120. { SFM/LFM }
  121. constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
  122. { *M*LL }
  123. constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  124. { this is for Jmp instructions }
  125. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  126. constructor op_sym(op : tasmop;_op1 : tasmsymbol);
  127. constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  128. constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  129. constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  130. function is_same_reg_move(regtype: Tregistertype):boolean; override;
  131. function spilling_get_operation_type(opnr: longint): topertype;override;
  132. { assembler }
  133. public
  134. { the next will reset all instructions that can change in pass 2 }
  135. procedure ResetPass1;
  136. procedure ResetPass2;
  137. function CheckIfValid:boolean;
  138. function GetString:string;
  139. function Pass1(offset:longint):longint;virtual;
  140. procedure Pass2(objdata:TAsmObjectdata);virtual;
  141. protected
  142. procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
  143. procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
  144. procedure ppubuildderefimploper(var o:toper);override;
  145. procedure ppuderefoper(var o:toper);override;
  146. private
  147. { next fields are filled in pass1, so pass2 is faster }
  148. inssize : shortint;
  149. insoffset : longint;
  150. LastInsOffset : longint; { need to be public to be reset }
  151. insentry : PInsEntry;
  152. function InsEnd:longint;
  153. procedure create_ot;
  154. function Matches(p:PInsEntry):longint;
  155. function calcsize(p:PInsEntry):shortint;
  156. procedure gencode(objdata:TAsmObjectData);
  157. function NeedAddrPrefix(opidx:byte):boolean;
  158. procedure Swapoperands;
  159. function FindInsentry:boolean;
  160. end;
  161. tai_align = class(tai_align_abstract)
  162. { nothing to add }
  163. end;
  164. function spilling_create_load(const ref:treference;r:tregister): tai;
  165. function spilling_create_store(r:tregister; const ref:treference): tai;
  166. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  167. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  168. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  169. { inserts pc relative symbols at places where they are reachable }
  170. procedure insertpcrelativedata(list,listtoinsert : taasmoutput);
  171. procedure InitAsm;
  172. procedure DoneAsm;
  173. implementation
  174. uses
  175. cutils,rgobj,itcpugas;
  176. procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
  177. begin
  178. allocate_oper(opidx+1);
  179. with oper[opidx]^ do
  180. begin
  181. if typ<>top_shifterop then
  182. begin
  183. clearop(opidx);
  184. new(shifterop);
  185. end;
  186. shifterop^:=so;
  187. typ:=top_shifterop;
  188. if assigned(add_reg_instruction_hook) then
  189. add_reg_instruction_hook(self,shifterop^.rs);
  190. end;
  191. end;
  192. procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset);
  193. var
  194. i : byte;
  195. begin
  196. allocate_oper(opidx+1);
  197. with oper[opidx]^ do
  198. begin
  199. if typ<>top_regset then
  200. clearop(opidx);
  201. new(regset);
  202. regset^:=s;
  203. typ:=top_regset;
  204. for i:=RS_R0 to RS_R15 do
  205. begin
  206. if assigned(add_reg_instruction_hook) and (i in regset^) then
  207. add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,R_SUBWHOLE));
  208. end;
  209. end;
  210. end;
  211. {*****************************************************************************
  212. taicpu Constructors
  213. *****************************************************************************}
  214. constructor taicpu.op_none(op : tasmop);
  215. begin
  216. inherited create(op);
  217. end;
  218. constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
  219. begin
  220. inherited create(op);
  221. ops:=1;
  222. loadreg(0,_op1);
  223. end;
  224. constructor taicpu.op_const(op : tasmop;_op1 : longint);
  225. begin
  226. inherited create(op);
  227. ops:=1;
  228. loadconst(0,aint(_op1));
  229. end;
  230. constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  231. begin
  232. inherited create(op);
  233. ops:=2;
  234. loadreg(0,_op1);
  235. loadreg(1,_op2);
  236. end;
  237. constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  238. begin
  239. inherited create(op);
  240. ops:=2;
  241. loadreg(0,_op1);
  242. loadconst(1,aint(_op2));
  243. end;
  244. constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; _op2: tcpuregisterset);
  245. begin
  246. inherited create(op);
  247. ops:=2;
  248. loadref(0,_op1);
  249. loadregset(1,_op2);
  250. end;
  251. constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  252. begin
  253. inherited create(op);
  254. ops:=2;
  255. loadreg(0,_op1);
  256. loadref(1,_op2);
  257. end;
  258. constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  259. begin
  260. inherited create(op);
  261. ops:=3;
  262. loadreg(0,_op1);
  263. loadreg(1,_op2);
  264. loadreg(2,_op3);
  265. end;
  266. constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  267. begin
  268. inherited create(op);
  269. ops:=4;
  270. loadreg(0,_op1);
  271. loadreg(1,_op2);
  272. loadreg(2,_op3);
  273. loadreg(3,_op4);
  274. end;
  275. constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  276. begin
  277. inherited create(op);
  278. ops:=3;
  279. loadreg(0,_op1);
  280. loadreg(1,_op2);
  281. loadconst(2,aint(_op3));
  282. end;
  283. constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
  284. begin
  285. inherited create(op);
  286. ops:=3;
  287. loadreg(0,_op1);
  288. loadconst(1,_op2);
  289. loadref(2,_op3);
  290. end;
  291. constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  292. begin
  293. inherited create(op);
  294. ops:=3;
  295. loadreg(0,_op1);
  296. loadreg(1,_op2);
  297. loadsymbol(0,_op3,_op3ofs);
  298. end;
  299. constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  300. begin
  301. inherited create(op);
  302. ops:=3;
  303. loadreg(0,_op1);
  304. loadreg(1,_op2);
  305. loadref(2,_op3);
  306. end;
  307. constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  308. begin
  309. inherited create(op);
  310. ops:=3;
  311. loadreg(0,_op1);
  312. loadreg(1,_op2);
  313. loadshifterop(2,_op3);
  314. end;
  315. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  316. begin
  317. inherited create(op);
  318. condition:=cond;
  319. ops:=1;
  320. loadsymbol(0,_op1,0);
  321. end;
  322. constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
  323. begin
  324. inherited create(op);
  325. ops:=1;
  326. loadsymbol(0,_op1,0);
  327. end;
  328. constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  329. begin
  330. inherited create(op);
  331. ops:=1;
  332. loadsymbol(0,_op1,_op1ofs);
  333. end;
  334. constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  335. begin
  336. inherited create(op);
  337. ops:=2;
  338. loadreg(0,_op1);
  339. loadsymbol(1,_op2,_op2ofs);
  340. end;
  341. constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  342. begin
  343. inherited create(op);
  344. ops:=2;
  345. loadsymbol(0,_op1,_op1ofs);
  346. loadref(1,_op2);
  347. end;
  348. function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
  349. begin
  350. { allow the register allocator to remove unnecessary moves }
  351. result:=(((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
  352. ((opcode=A_MVF) and (regtype = R_FPUREGISTER))
  353. ) and
  354. (condition=C_None) and
  355. (ops=2) and
  356. (oper[0]^.typ=top_reg) and
  357. (oper[1]^.typ=top_reg) and
  358. (oper[0]^.reg=oper[1]^.reg);
  359. end;
  360. function spilling_create_load(const ref:treference;r:tregister): tai;
  361. begin
  362. case getregtype(r) of
  363. R_INTREGISTER :
  364. result:=taicpu.op_reg_ref(A_LDR,r,ref);
  365. R_FPUREGISTER :
  366. { use lfm because we don't know the current internal format
  367. and avoid exceptions
  368. }
  369. result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref);
  370. else
  371. internalerror(200401041);
  372. end;
  373. end;
  374. function spilling_create_store(r:tregister; const ref:treference): tai;
  375. begin
  376. case getregtype(r) of
  377. R_INTREGISTER :
  378. result:=taicpu.op_reg_ref(A_STR,r,ref);
  379. R_FPUREGISTER :
  380. { use sfm because we don't know the current internal format
  381. and avoid exceptions
  382. }
  383. result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref);
  384. else
  385. internalerror(200401041);
  386. end;
  387. end;
  388. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  389. begin
  390. case opcode of
  391. A_ADC,A_ADD,A_AND,
  392. A_EOR,A_CLZ,
  393. A_LDR,A_LDRB,A_LDRBT,A_LDRH,A_LDRSB,
  394. A_LDRSH,A_LDRT,
  395. A_MOV,A_MVN,A_MLA,A_MUL,
  396. A_ORR,A_RSB,A_RSC,A_SBC,A_SUB,
  397. A_SWP,A_SWPB,
  398. A_LDF,A_FLT,A_FIX,
  399. A_ADF,A_DVF,A_FDV,A_FML,
  400. A_RFS,A_RFC,A_RDF,
  401. A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS,
  402. A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN,
  403. A_LFM:
  404. if opnr=0 then
  405. result:=operand_write
  406. else
  407. result:=operand_read;
  408. A_BIC,A_BKPT,A_B,A_BL,A_BLX,A_BX,
  409. A_CMN,A_CMP,A_TEQ,A_TST,
  410. A_CMF,A_CMFE,A_WFS,A_CNF:
  411. result:=operand_read;
  412. A_SMLAL,A_UMLAL:
  413. if opnr in [0,1] then
  414. result:=operand_readwrite
  415. else
  416. result:=operand_read;
  417. A_SMULL,A_UMULL:
  418. if opnr in [0,1] then
  419. result:=operand_write
  420. else
  421. result:=operand_read;
  422. A_STR,A_STRB,A_STRBT,
  423. A_STRH,A_STRT,A_STF,A_SFM:
  424. { important is what happens with the involved registers }
  425. if opnr=0 then
  426. result := operand_read
  427. else
  428. { check for pre/post indexed }
  429. result := operand_read;
  430. else
  431. internalerror(200403151);
  432. end;
  433. end;
  434. procedure BuildInsTabCache;
  435. var
  436. i : longint;
  437. begin
  438. new(instabcache);
  439. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  440. i:=0;
  441. while (i<InsTabEntries) do
  442. begin
  443. if InsTabCache^[InsTab[i].Opcode]=-1 then
  444. InsTabCache^[InsTab[i].Opcode]:=i;
  445. inc(i);
  446. end;
  447. end;
  448. procedure InitAsm;
  449. begin
  450. if not assigned(instabcache) then
  451. BuildInsTabCache;
  452. end;
  453. procedure DoneAsm;
  454. begin
  455. if assigned(instabcache) then
  456. begin
  457. dispose(instabcache);
  458. instabcache:=nil;
  459. end;
  460. end;
  461. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  462. begin
  463. i.oppostfix:=pf;
  464. result:=i;
  465. end;
  466. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  467. begin
  468. i.roundingmode:=rm;
  469. result:=i;
  470. end;
  471. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  472. begin
  473. i.condition:=c;
  474. result:=i;
  475. end;
  476. procedure insertpcrelativedata(list,listtoinsert : taasmoutput);
  477. var
  478. curpos : longint;
  479. lastpos : longint;
  480. curop : longint;
  481. curtai : tai;
  482. curdatatai,hp : tai;
  483. curdata : taasmoutput;
  484. l : tasmlabel;
  485. begin
  486. curdata:=taasmoutput.create;
  487. lastpos:=-1;
  488. curpos:=0;
  489. curtai:=tai(list.first);
  490. while assigned(curtai) do
  491. begin
  492. { instruction? }
  493. if curtai.typ=ait_instruction then
  494. begin
  495. { walk through all operand of the instruction }
  496. for curop:=0 to taicpu(curtai).ops-1 do
  497. begin
  498. { reference? }
  499. if (taicpu(curtai).oper[curop]^.typ=top_ref) then
  500. begin
  501. { pc relative symbol? }
  502. curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
  503. if assigned(curdatatai) then
  504. begin
  505. { if yes, insert till next symbol }
  506. repeat
  507. hp:=tai(curdatatai.next);
  508. listtoinsert.remove(curdatatai);
  509. curdata.concat(curdatatai);
  510. curdatatai:=hp;
  511. until (curdatatai=nil) or (curdatatai.typ=ait_label);
  512. if lastpos=-1 then
  513. lastpos:=curpos;
  514. end;
  515. end;
  516. end;
  517. inc(curpos);
  518. end;
  519. { split only at real instructions else the test below fails }
  520. if ((curpos-lastpos)>1016) and (curtai.typ=ait_instruction) and
  521. (
  522. { don't split loads of pc to lr and the following move }
  523. not(
  524. (taicpu(curtai).opcode=A_MOV) and
  525. (taicpu(curtai).oper[0]^.typ=top_reg) and
  526. (taicpu(curtai).oper[0]^.reg=NR_R14) and
  527. (taicpu(curtai).oper[1]^.typ=top_reg) and
  528. (taicpu(curtai).oper[1]^.reg=NR_PC)
  529. )
  530. ) then
  531. begin
  532. lastpos:=curpos;
  533. hp:=tai(curtai.next);
  534. objectlibrary.getlabel(l);
  535. curdata.insert(taicpu.op_sym(A_B,l));
  536. curdata.concat(tai_label.create(l));
  537. list.insertlistafter(curtai,curdata);
  538. curtai:=hp;
  539. end
  540. else
  541. curtai:=tai(curtai.next);
  542. end;
  543. list.concatlist(curdata);
  544. curdata.free;
  545. end;
  546. (*
  547. Floating point instruction format information, taken from the linux kernel
  548. ARM Floating Point Instruction Classes
  549. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  550. |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
  551. |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)
  552. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  553. |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
  554. |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
  555. |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
  556. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  557. CPDT data transfer instructions
  558. LDF, STF, LFM (copro 2), SFM (copro 2)
  559. CPDO dyadic arithmetic instructions
  560. ADF, MUF, SUF, RSF, DVF, RDF,
  561. POW, RPW, RMF, FML, FDV, FRD, POL
  562. CPDO monadic arithmetic instructions
  563. MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
  564. SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
  565. CPRT joint arithmetic/data transfer instructions
  566. FIX (arithmetic followed by load/store)
  567. FLT (load/store followed by arithmetic)
  568. CMF, CNF CMFE, CNFE (comparisons)
  569. WFS, RFS (write/read floating point status register)
  570. WFC, RFC (write/read floating point control register)
  571. cond condition codes
  572. P pre/post index bit: 0 = postindex, 1 = preindex
  573. U up/down bit: 0 = stack grows down, 1 = stack grows up
  574. W write back bit: 1 = update base register (Rn)
  575. L load/store bit: 0 = store, 1 = load
  576. Rn base register
  577. Rd destination/source register
  578. Fd floating point destination register
  579. Fn floating point source register
  580. Fm floating point source register or floating point constant
  581. uv transfer length (TABLE 1)
  582. wx register count (TABLE 2)
  583. abcd arithmetic opcode (TABLES 3 & 4)
  584. ef destination size (rounding precision) (TABLE 5)
  585. gh rounding mode (TABLE 6)
  586. j dyadic/monadic bit: 0 = dyadic, 1 = monadic
  587. i constant bit: 1 = constant (TABLE 6)
  588. */
  589. /*
  590. TABLE 1
  591. +-------------------------+---+---+---------+---------+
  592. | Precision | u | v | FPSR.EP | length |
  593. +-------------------------+---+---+---------+---------+
  594. | Single | 0 | 0 | x | 1 words |
  595. | Double | 1 | 1 | x | 2 words |
  596. | Extended | 1 | 1 | x | 3 words |
  597. | Packed decimal | 1 | 1 | 0 | 3 words |
  598. | Expanded packed decimal | 1 | 1 | 1 | 4 words |
  599. +-------------------------+---+---+---------+---------+
  600. Note: x = don't care
  601. */
  602. /*
  603. TABLE 2
  604. +---+---+---------------------------------+
  605. | w | x | Number of registers to transfer |
  606. +---+---+---------------------------------+
  607. | 0 | 1 | 1 |
  608. | 1 | 0 | 2 |
  609. | 1 | 1 | 3 |
  610. | 0 | 0 | 4 |
  611. +---+---+---------------------------------+
  612. */
  613. /*
  614. TABLE 3: Dyadic Floating Point Opcodes
  615. +---+---+---+---+----------+-----------------------+-----------------------+
  616. | a | b | c | d | Mnemonic | Description | Operation |
  617. +---+---+---+---+----------+-----------------------+-----------------------+
  618. | 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
  619. | 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
  620. | 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
  621. | 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
  622. | 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
  623. | 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
  624. | 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
  625. | 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
  626. | 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
  627. | 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
  628. | 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
  629. | 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
  630. | 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
  631. | 1 | 1 | 0 | 1 | | undefined instruction | trap |
  632. | 1 | 1 | 1 | 0 | | undefined instruction | trap |
  633. | 1 | 1 | 1 | 1 | | undefined instruction | trap |
  634. +---+---+---+---+----------+-----------------------+-----------------------+
  635. Note: POW, RPW, POL are deprecated, and are available for backwards
  636. compatibility only.
  637. */
  638. /*
  639. TABLE 4: Monadic Floating Point Opcodes
  640. +---+---+---+---+----------+-----------------------+-----------------------+
  641. | a | b | c | d | Mnemonic | Description | Operation |
  642. +---+---+---+---+----------+-----------------------+-----------------------+
  643. | 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
  644. | 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
  645. | 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
  646. | 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
  647. | 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
  648. | 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
  649. | 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
  650. | 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
  651. | 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
  652. | 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
  653. | 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
  654. | 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
  655. | 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
  656. | 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
  657. | 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
  658. | 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
  659. +---+---+---+---+----------+-----------------------+-----------------------+
  660. Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
  661. available for backwards compatibility only.
  662. */
  663. /*
  664. TABLE 5
  665. +-------------------------+---+---+
  666. | Rounding Precision | e | f |
  667. +-------------------------+---+---+
  668. | IEEE Single precision | 0 | 0 |
  669. | IEEE Double precision | 0 | 1 |
  670. | IEEE Extended precision | 1 | 0 |
  671. | undefined (trap) | 1 | 1 |
  672. +-------------------------+---+---+
  673. */
  674. /*
  675. TABLE 5
  676. +---------------------------------+---+---+
  677. | Rounding Mode | g | h |
  678. +---------------------------------+---+---+
  679. | Round to nearest (default) | 0 | 0 |
  680. | Round toward plus infinity | 0 | 1 |
  681. | Round toward negative infinity | 1 | 0 |
  682. | Round toward zero | 1 | 1 |
  683. +---------------------------------+---+---+
  684. *)
  685. function taicpu.GetString:string;
  686. var
  687. i : longint;
  688. s : string;
  689. addsize : boolean;
  690. begin
  691. s:='['+gas_op2str[opcode];
  692. for i:=0 to ops-1 do
  693. begin
  694. with oper[i]^ do
  695. begin
  696. if i=0 then
  697. s:=s+' '
  698. else
  699. s:=s+',';
  700. { type }
  701. addsize:=false;
  702. if (ot and OT_VREG)=OT_VREG then
  703. s:=s+'vreg'
  704. else
  705. if (ot and OT_FPUREG)=OT_FPUREG then
  706. s:=s+'fpureg'
  707. else
  708. if (ot and OT_REGISTER)=OT_REGISTER then
  709. begin
  710. s:=s+'reg';
  711. addsize:=true;
  712. end
  713. else
  714. if (ot and OT_REGLIST)=OT_REGLIST then
  715. begin
  716. s:=s+'reglist';
  717. addsize:=false;
  718. end
  719. else
  720. if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  721. begin
  722. s:=s+'imm';
  723. addsize:=true;
  724. end
  725. else
  726. if (ot and OT_MEMORY)=OT_MEMORY then
  727. begin
  728. s:=s+'mem';
  729. addsize:=true;
  730. end
  731. else
  732. s:=s+'???';
  733. { size }
  734. if addsize then
  735. begin
  736. if (ot and OT_BITS8)<>0 then
  737. s:=s+'8'
  738. else
  739. if (ot and OT_BITS16)<>0 then
  740. s:=s+'16'
  741. else
  742. if (ot and OT_BITS32)<>0 then
  743. s:=s+'32'
  744. else
  745. s:=s+'??';
  746. { signed }
  747. if (ot and OT_SIGNED)<>0 then
  748. s:=s+'s';
  749. end;
  750. end;
  751. end;
  752. GetString:=s+']';
  753. end;
  754. procedure taicpu.ResetPass1;
  755. begin
  756. { we need to reset everything here, because the choosen insentry
  757. can be invalid for a new situation where the previously optimized
  758. insentry is not correct }
  759. InsEntry:=nil;
  760. InsSize:=0;
  761. LastInsOffset:=-1;
  762. end;
  763. procedure taicpu.ResetPass2;
  764. begin
  765. { we are here in a second pass, check if the instruction can be optimized }
  766. if assigned(InsEntry) and
  767. ((InsEntry^.flags and IF_PASS2)<>0) then
  768. begin
  769. InsEntry:=nil;
  770. InsSize:=0;
  771. end;
  772. LastInsOffset:=-1;
  773. end;
  774. function taicpu.CheckIfValid:boolean;
  775. begin
  776. end;
  777. function taicpu.Pass1(offset:longint):longint;
  778. begin
  779. Pass1:=0;
  780. { Save the old offset and set the new offset }
  781. InsOffset:=Offset;
  782. { Error? }
  783. if (Insentry=nil) and (InsSize=-1) then
  784. exit;
  785. { set the file postion }
  786. aktfilepos:=fileinfo;
  787. { Get InsEntry }
  788. if FindInsEntry then
  789. begin
  790. InsSize:=4;
  791. LastInsOffset:=InsOffset;
  792. Pass1:=InsSize;
  793. exit;
  794. end;
  795. LastInsOffset:=-1;
  796. end;
  797. procedure taicpu.Pass2(objdata:TAsmObjectdata);
  798. begin
  799. end;
  800. procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
  801. begin
  802. end;
  803. procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
  804. begin
  805. end;
  806. procedure taicpu.ppubuildderefimploper(var o:toper);
  807. begin
  808. end;
  809. procedure taicpu.ppuderefoper(var o:toper);
  810. begin
  811. end;
  812. function taicpu.InsEnd:longint;
  813. begin
  814. end;
  815. procedure taicpu.create_ot;
  816. var
  817. i,l,relsize : longint;
  818. begin
  819. if ops=0 then
  820. exit;
  821. { update oper[].ot field }
  822. for i:=0 to ops-1 do
  823. with oper[i]^ do
  824. begin
  825. case typ of
  826. top_regset:
  827. begin
  828. ot:=OT_REGLIST;
  829. end;
  830. top_reg :
  831. begin
  832. case getregtype(reg) of
  833. R_INTREGISTER:
  834. ot:=OT_REG32;
  835. R_FPUREGISTER:
  836. ot:=OT_FPUREG;
  837. else
  838. internalerror(2005090901);
  839. end;
  840. end;
  841. top_ref :
  842. begin
  843. if ref^.refaddr=addr_no then
  844. begin
  845. { create ot field }
  846. { we should get the size here dependend on the
  847. instruction }
  848. if (ot and OT_SIZE_MASK)=0 then
  849. ot:=OT_MEMORY or OT_BITS32
  850. else
  851. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  852. if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
  853. ot:=ot or OT_MEM_OFFS;
  854. { if we need to fix a reference, we do it here }
  855. end
  856. else
  857. begin
  858. l:=ref^.offset;
  859. if assigned(ref^.symbol) then
  860. inc(l,ref^.symbol.address);
  861. if (not assigned(ref^.symbol) or
  862. ((ref^.symbol.currbind<>AB_EXTERNAL) and (ref^.symbol.address<>0))) and
  863. (relsize>=-128) and (relsize<=127) then
  864. ot:=OT_IMM32 or OT_SHORT
  865. else
  866. ot:=OT_IMM32 or OT_NEAR;
  867. end;
  868. end;
  869. top_local :
  870. begin
  871. { we should get the size here dependend on the
  872. instruction }
  873. if (ot and OT_SIZE_MASK)=0 then
  874. ot:=OT_MEMORY or OT_BITS32
  875. else
  876. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  877. end;
  878. top_const :
  879. begin
  880. ot:=OT_IMMEDIATE;
  881. { fixme !!!!
  882. if opsize=S_NO then
  883. message(asmr_e_invalid_opcode_and_operand);
  884. if (opsize<>S_W) and (longint(val)>=-128) and (val<=127) then
  885. ot:=OT_IMM8 or OT_SIGNED
  886. else
  887. ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
  888. }
  889. end;
  890. top_none :
  891. begin
  892. { generated when there was an error in the
  893. assembler reader. It never happends when generating
  894. assembler }
  895. end;
  896. top_shifterop:
  897. begin
  898. end;
  899. else
  900. internalerror(200402261);
  901. end;
  902. end;
  903. end;
  904. function taicpu.Matches(p:PInsEntry):longint;
  905. { * IF_SM stands for Size Match: any operand whose size is not
  906. * explicitly specified by the template is `really' intended to be
  907. * the same size as the first size-specified operand.
  908. * Non-specification is tolerated in the input instruction, but
  909. * _wrong_ specification is not.
  910. *
  911. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  912. * three-operand instructions such as SHLD: it implies that the
  913. * first two operands must match in size, but that the third is
  914. * required to be _unspecified_.
  915. *
  916. * IF_SB invokes Size Byte: operands with unspecified size in the
  917. * template are really bytes, and so no non-byte specification in
  918. * the input instruction will be tolerated. IF_SW similarly invokes
  919. * Size Word, and IF_SD invokes Size Doubleword.
  920. *
  921. * (The default state if neither IF_SM nor IF_SM2 is specified is
  922. * that any operand with unspecified size in the template is
  923. * required to have unspecified size in the instruction too...)
  924. }
  925. var
  926. i,j,asize,oprs : longint;
  927. siz : array[0..3] of longint;
  928. begin
  929. Matches:=100;
  930. { Check the opcode and operands }
  931. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  932. begin
  933. Matches:=0;
  934. exit;
  935. end;
  936. { Check that no spurious colons or TOs are present }
  937. for i:=0 to p^.ops-1 do
  938. if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  939. begin
  940. Matches:=0;
  941. exit;
  942. end;
  943. { Check that the operand flags all match up }
  944. for i:=0 to p^.ops-1 do
  945. begin
  946. if ((p^.optypes[i] and (not oper[i]^.ot)) or
  947. ((p^.optypes[i] and OT_SIZE_MASK) and
  948. ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
  949. begin
  950. if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
  951. (oper[i]^.ot and OT_SIZE_MASK))<>0 then
  952. begin
  953. Matches:=0;
  954. exit;
  955. end
  956. else
  957. Matches:=1;
  958. end;
  959. end;
  960. { Check operand sizes }
  961. { as default an untyped size can get all the sizes, this is different
  962. from nasm, but else we need to do a lot checking which opcodes want
  963. size or not with the automatic size generation }
  964. asize:=longint($ffffffff);
  965. (*
  966. if (p^.flags and IF_SB)<>0 then
  967. asize:=OT_BITS8
  968. else if (p^.flags and IF_SW)<>0 then
  969. asize:=OT_BITS16
  970. else if (p^.flags and IF_SD)<>0 then
  971. asize:=OT_BITS32;
  972. if (p^.flags and IF_ARMASK)<>0 then
  973. begin
  974. siz[0]:=0;
  975. siz[1]:=0;
  976. siz[2]:=0;
  977. if (p^.flags and IF_AR0)<>0 then
  978. siz[0]:=asize
  979. else if (p^.flags and IF_AR1)<>0 then
  980. siz[1]:=asize
  981. else if (p^.flags and IF_AR2)<>0 then
  982. siz[2]:=asize;
  983. end
  984. else
  985. begin
  986. { we can leave because the size for all operands is forced to be
  987. the same
  988. but not if IF_SB IF_SW or IF_SD is set PM }
  989. if asize=-1 then
  990. exit;
  991. siz[0]:=asize;
  992. siz[1]:=asize;
  993. siz[2]:=asize;
  994. end;
  995. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  996. begin
  997. if (p^.flags and IF_SM2)<>0 then
  998. oprs:=2
  999. else
  1000. oprs:=p^.ops;
  1001. for i:=0 to oprs-1 do
  1002. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  1003. begin
  1004. for j:=0 to oprs-1 do
  1005. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  1006. break;
  1007. end;
  1008. end
  1009. else
  1010. oprs:=2;
  1011. { Check operand sizes }
  1012. for i:=0 to p^.ops-1 do
  1013. begin
  1014. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  1015. ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  1016. { Immediates can always include smaller size }
  1017. ((oper[i]^.ot and OT_IMMEDIATE)=0) and
  1018. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
  1019. Matches:=2;
  1020. end;
  1021. *)
  1022. end;
  1023. function taicpu.calcsize(p:PInsEntry):shortint;
  1024. begin
  1025. end;
  1026. procedure taicpu.gencode(objdata:TAsmObjectData);
  1027. begin
  1028. end;
  1029. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  1030. begin
  1031. end;
  1032. procedure taicpu.Swapoperands;
  1033. begin
  1034. end;
  1035. function taicpu.FindInsentry:boolean;
  1036. var
  1037. i : longint;
  1038. begin
  1039. result:=false;
  1040. { Things which may only be done once, not when a second pass is done to
  1041. optimize }
  1042. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  1043. begin
  1044. { create the .ot fields }
  1045. create_ot;
  1046. { set the file postion }
  1047. aktfilepos:=fileinfo;
  1048. end
  1049. else
  1050. begin
  1051. { we've already an insentry so it's valid }
  1052. result:=true;
  1053. exit;
  1054. end;
  1055. { Lookup opcode in the table }
  1056. InsSize:=-1;
  1057. i:=instabcache^[opcode];
  1058. if i=-1 then
  1059. begin
  1060. Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
  1061. exit;
  1062. end;
  1063. insentry:=@instab[i];
  1064. while (insentry^.opcode=opcode) do
  1065. begin
  1066. if matches(insentry)=100 then
  1067. begin
  1068. result:=true;
  1069. exit;
  1070. end;
  1071. inc(i);
  1072. insentry:=@instab[i];
  1073. end;
  1074. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  1075. { No instruction found, set insentry to nil and inssize to -1 }
  1076. insentry:=nil;
  1077. inssize:=-1;
  1078. end;
  1079. end.
  1080. {$ifdef dummy}
  1081. (*
  1082. static void gencode (long segment, long offset, int bits,
  1083. insn *ins, char *codes, long insn_end)
  1084. {
  1085. int has_S_code; /* S - setflag */
  1086. int has_B_code; /* B - setflag */
  1087. int has_T_code; /* T - setflag */
  1088. int has_W_code; /* ! => W flag */
  1089. int has_F_code; /* ^ => S flag */
  1090. int keep;
  1091. unsigned char c;
  1092. unsigned char bytes[4];
  1093. long data, size;
  1094. static int cc_code[] = /* bit pattern of cc */
  1095. { /* order as enum in */
  1096. 0x0E, 0x03, 0x02, 0x00, /* nasm.h */
  1097. 0x0A, 0x0C, 0x08, 0x0D,
  1098. 0x09, 0x0B, 0x04, 0x01,
  1099. 0x05, 0x07, 0x06,
  1100. };
  1101. (*
  1102. #ifdef DEBUG
  1103. static char *CC[] =
  1104. { /* condition code names */
  1105. "AL", "CC", "CS", "EQ",
  1106. "GE", "GT", "HI", "LE",
  1107. "LS", "LT", "MI", "NE",
  1108. "PL", "VC", "VS", "",
  1109. "S"
  1110. };
  1111. *)
  1112. has_S_code = (ins->condition & C_SSETFLAG);
  1113. has_B_code = (ins->condition & C_BSETFLAG);
  1114. has_T_code = (ins->condition & C_TSETFLAG);
  1115. has_W_code = (ins->condition & C_EXSETFLAG);
  1116. has_F_code = (ins->condition & C_FSETFLAG);
  1117. ins->condition = (ins->condition & 0x0F);
  1118. (*
  1119. if (rt_debug)
  1120. {
  1121. printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
  1122. CC[ins->condition & 0x0F]);
  1123. if (has_S_code)
  1124. printf ("S");
  1125. if (has_B_code)
  1126. printf ("B");
  1127. if (has_T_code)
  1128. printf ("T");
  1129. if (has_W_code)
  1130. printf ("!");
  1131. if (has_F_code)
  1132. printf ("^");
  1133. printf ("\n");
  1134. c = *codes;
  1135. printf (" (%d) decode - '0x%02X'\n", ins->operands, c);
  1136. bytes[0] = 0xB;
  1137. bytes[1] = 0xE;
  1138. bytes[2] = 0xE;
  1139. bytes[3] = 0xF;
  1140. }
  1141. *)
  1142. // First condition code in upper nibble
  1143. if (ins->condition < C_NONE)
  1144. {
  1145. c = cc_code[ins->condition] << 4;
  1146. }
  1147. else
  1148. {
  1149. c = cc_code[C_AL] << 4; // is often ALWAYS but not always
  1150. }
  1151. switch (keep = *codes)
  1152. {
  1153. case 1:
  1154. // B, BL
  1155. ++codes;
  1156. c |= *codes++;
  1157. bytes[0] = c;
  1158. if (ins->oprs[0].segment != segment)
  1159. {
  1160. // fais une relocation
  1161. c = 1;
  1162. data = 0; // Let the linker locate ??
  1163. }
  1164. else
  1165. {
  1166. c = 0;
  1167. data = ins->oprs[0].offset - (offset + 8);
  1168. if (data % 4)
  1169. {
  1170. errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
  1171. }
  1172. }
  1173. if (data >= 0x1000)
  1174. {
  1175. errfunc (ERR_NONFATAL, "too long offset");
  1176. }
  1177. data = data >> 2;
  1178. bytes[1] = (data >> 16) & 0xFF;
  1179. bytes[2] = (data >> 8) & 0xFF;
  1180. bytes[3] = (data ) & 0xFF;
  1181. if (c == 1)
  1182. {
  1183. // out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
  1184. out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
  1185. }
  1186. else
  1187. {
  1188. out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1189. }
  1190. return;
  1191. case 2:
  1192. // SWI
  1193. ++codes;
  1194. c |= *codes++;
  1195. bytes[0] = c;
  1196. data = ins->oprs[0].offset;
  1197. bytes[1] = (data >> 16) & 0xFF;
  1198. bytes[2] = (data >> 8) & 0xFF;
  1199. bytes[3] = (data) & 0xFF;
  1200. out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1201. return;
  1202. case 3:
  1203. // BX
  1204. ++codes;
  1205. c |= *codes++;
  1206. bytes[0] = c;
  1207. bytes[1] = *codes++;
  1208. bytes[2] = *codes++;
  1209. bytes[3] = *codes++;
  1210. c = regval (&ins->oprs[0],1);
  1211. if (c == 15) // PC
  1212. {
  1213. errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
  1214. }
  1215. else if (c > 15)
  1216. {
  1217. errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
  1218. }
  1219. bytes[3] |= (c & 0x0F);
  1220. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1221. return;
  1222. case 4: // AND Rd,Rn,Rm
  1223. case 5: // AND Rd,Rn,Rm,<shift>Rs
  1224. case 6: // AND Rd,Rn,Rm,<shift>imm
  1225. case 7: // AND Rd,Rn,<shift>imm
  1226. ++codes;
  1227. #ifdef DEBUG
  1228. if (rt_debug)
  1229. {
  1230. printf (" decode - '0x%02X'\n", keep);
  1231. printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
  1232. }
  1233. #endif
  1234. bytes[0] = c | *codes;
  1235. ++codes;
  1236. bytes[1] = *codes;
  1237. if (has_S_code)
  1238. bytes[1] |= 0x10;
  1239. c = regval (&ins->oprs[1],1);
  1240. // Rn in low nibble
  1241. bytes[1] |= c;
  1242. // Rd in high nibble
  1243. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1244. if (keep != 7)
  1245. {
  1246. // Rm in low nibble
  1247. bytes[3] = regval (&ins->oprs[2],1);
  1248. }
  1249. // Shifts if any
  1250. if (keep == 5 || keep == 6)
  1251. {
  1252. // Shift in bytes 2 and 3
  1253. if (keep == 5)
  1254. {
  1255. // Rs
  1256. c = regval (&ins->oprs[3],1);
  1257. bytes[2] |= c;
  1258. c = 0x10; // Set bit 4 in byte[3]
  1259. }
  1260. if (keep == 6)
  1261. {
  1262. c = (ins->oprs[3].offset) & 0x1F;
  1263. // #imm
  1264. bytes[2] |= c >> 1;
  1265. if (c & 0x01)
  1266. {
  1267. bytes[3] |= 0x80;
  1268. }
  1269. c = 0; // Clr bit 4 in byte[3]
  1270. }
  1271. // <shift>
  1272. c |= shiftval (&ins->oprs[3]) << 5;
  1273. bytes[3] |= c;
  1274. }
  1275. // reg,reg,imm
  1276. if (keep == 7)
  1277. {
  1278. int shimm;
  1279. shimm = imm_shift (ins->oprs[2].offset);
  1280. if (shimm == -1)
  1281. {
  1282. errfunc (ERR_NONFATAL, "cannot create that constant");
  1283. }
  1284. bytes[3] = shimm & 0xFF;
  1285. bytes[2] |= (shimm & 0xF00) >> 8;
  1286. }
  1287. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1288. return;
  1289. case 8: // MOV Rd,Rm
  1290. case 9: // MOV Rd,Rm,<shift>Rs
  1291. case 0xA: // MOV Rd,Rm,<shift>imm
  1292. case 0xB: // MOV Rd,<shift>imm
  1293. ++codes;
  1294. #ifdef DEBUG
  1295. if (rt_debug)
  1296. {
  1297. printf (" decode - '0x%02X'\n", keep);
  1298. printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
  1299. }
  1300. #endif
  1301. bytes[0] = c | *codes;
  1302. ++codes;
  1303. bytes[1] = *codes;
  1304. if (has_S_code)
  1305. bytes[1] |= 0x10;
  1306. // Rd in high nibble
  1307. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1308. if (keep != 0x0B)
  1309. {
  1310. // Rm in low nibble
  1311. bytes[3] = regval (&ins->oprs[1],1);
  1312. }
  1313. // Shifts if any
  1314. if (keep == 0x09 || keep == 0x0A)
  1315. {
  1316. // Shift in bytes 2 and 3
  1317. if (keep == 0x09)
  1318. {
  1319. // Rs
  1320. c = regval (&ins->oprs[2],1);
  1321. bytes[2] |= c;
  1322. c = 0x10; // Set bit 4 in byte[3]
  1323. }
  1324. if (keep == 0x0A)
  1325. {
  1326. c = (ins->oprs[2].offset) & 0x1F;
  1327. // #imm
  1328. bytes[2] |= c >> 1;
  1329. if (c & 0x01)
  1330. {
  1331. bytes[3] |= 0x80;
  1332. }
  1333. c = 0; // Clr bit 4 in byte[3]
  1334. }
  1335. // <shift>
  1336. c |= shiftval (&ins->oprs[2]) << 5;
  1337. bytes[3] |= c;
  1338. }
  1339. // reg,imm
  1340. if (keep == 0x0B)
  1341. {
  1342. int shimm;
  1343. shimm = imm_shift (ins->oprs[1].offset);
  1344. if (shimm == -1)
  1345. {
  1346. errfunc (ERR_NONFATAL, "cannot create that constant");
  1347. }
  1348. bytes[3] = shimm & 0xFF;
  1349. bytes[2] |= (shimm & 0xF00) >> 8;
  1350. }
  1351. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1352. return;
  1353. case 0xC: // CMP Rn,Rm
  1354. case 0xD: // CMP Rn,Rm,<shift>Rs
  1355. case 0xE: // CMP Rn,Rm,<shift>imm
  1356. case 0xF: // CMP Rn,<shift>imm
  1357. ++codes;
  1358. bytes[0] = c | *codes++;
  1359. bytes[1] = *codes;
  1360. // Implicit S code
  1361. bytes[1] |= 0x10;
  1362. c = regval (&ins->oprs[0],1);
  1363. // Rn in low nibble
  1364. bytes[1] |= c;
  1365. // No destination
  1366. bytes[2] = 0;
  1367. if (keep != 0x0B)
  1368. {
  1369. // Rm in low nibble
  1370. bytes[3] = regval (&ins->oprs[1],1);
  1371. }
  1372. // Shifts if any
  1373. if (keep == 0x0D || keep == 0x0E)
  1374. {
  1375. // Shift in bytes 2 and 3
  1376. if (keep == 0x0D)
  1377. {
  1378. // Rs
  1379. c = regval (&ins->oprs[2],1);
  1380. bytes[2] |= c;
  1381. c = 0x10; // Set bit 4 in byte[3]
  1382. }
  1383. if (keep == 0x0E)
  1384. {
  1385. c = (ins->oprs[2].offset) & 0x1F;
  1386. // #imm
  1387. bytes[2] |= c >> 1;
  1388. if (c & 0x01)
  1389. {
  1390. bytes[3] |= 0x80;
  1391. }
  1392. c = 0; // Clr bit 4 in byte[3]
  1393. }
  1394. // <shift>
  1395. c |= shiftval (&ins->oprs[2]) << 5;
  1396. bytes[3] |= c;
  1397. }
  1398. // reg,imm
  1399. if (keep == 0x0F)
  1400. {
  1401. int shimm;
  1402. shimm = imm_shift (ins->oprs[1].offset);
  1403. if (shimm == -1)
  1404. {
  1405. errfunc (ERR_NONFATAL, "cannot create that constant");
  1406. }
  1407. bytes[3] = shimm & 0xFF;
  1408. bytes[2] |= (shimm & 0xF00) >> 8;
  1409. }
  1410. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1411. return;
  1412. case 0x10: // MRS Rd,<psr>
  1413. ++codes;
  1414. bytes[0] = c | *codes++;
  1415. bytes[1] = *codes++;
  1416. // Rd
  1417. c = regval (&ins->oprs[0],1);
  1418. bytes[2] = c << 4;
  1419. bytes[3] = 0;
  1420. c = ins->oprs[1].basereg;
  1421. if (c == R_CPSR || c == R_SPSR)
  1422. {
  1423. if (c == R_SPSR)
  1424. {
  1425. bytes[1] |= 0x40;
  1426. }
  1427. }
  1428. else
  1429. {
  1430. errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
  1431. }
  1432. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1433. return;
  1434. case 0x11: // MSR <psr>,Rm
  1435. case 0x12: // MSR <psrf>,Rm
  1436. case 0x13: // MSR <psrf>,#expression
  1437. ++codes;
  1438. bytes[0] = c | *codes++;
  1439. bytes[1] = *codes++;
  1440. bytes[2] = *codes;
  1441. if (keep == 0x11 || keep == 0x12)
  1442. {
  1443. // Rm
  1444. c = regval (&ins->oprs[1],1);
  1445. bytes[3] = c;
  1446. }
  1447. else
  1448. {
  1449. int shimm;
  1450. shimm = imm_shift (ins->oprs[1].offset);
  1451. if (shimm == -1)
  1452. {
  1453. errfunc (ERR_NONFATAL, "cannot create that constant");
  1454. }
  1455. bytes[3] = shimm & 0xFF;
  1456. bytes[2] |= (shimm & 0xF00) >> 8;
  1457. }
  1458. c = ins->oprs[0].basereg;
  1459. if ( keep == 0x11)
  1460. {
  1461. if ( c == R_CPSR || c == R_SPSR)
  1462. {
  1463. if ( c== R_SPSR)
  1464. {
  1465. bytes[1] |= 0x40;
  1466. }
  1467. }
  1468. else
  1469. {
  1470. errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
  1471. }
  1472. }
  1473. else
  1474. {
  1475. if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
  1476. {
  1477. if ( c== R_SPSR_FLG)
  1478. {
  1479. bytes[1] |= 0x40;
  1480. }
  1481. }
  1482. else
  1483. {
  1484. errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
  1485. }
  1486. }
  1487. break;
  1488. case 0x14: // MUL Rd,Rm,Rs
  1489. case 0x15: // MULA Rd,Rm,Rs,Rn
  1490. ++codes;
  1491. bytes[0] = c | *codes++;
  1492. bytes[1] = *codes++;
  1493. bytes[3] = *codes;
  1494. // Rd
  1495. bytes[1] |= regval (&ins->oprs[0],1);
  1496. if (has_S_code)
  1497. bytes[1] |= 0x10;
  1498. // Rm
  1499. bytes[3] |= regval (&ins->oprs[1],1);
  1500. // Rs
  1501. bytes[2] = regval (&ins->oprs[2],1);
  1502. if (keep == 0x15)
  1503. {
  1504. bytes[2] |= regval (&ins->oprs[3],1) << 4;
  1505. }
  1506. break;
  1507. case 0x16: // SMLAL RdHi,RdLo,Rm,Rs
  1508. ++codes;
  1509. bytes[0] = c | *codes++;
  1510. bytes[1] = *codes++;
  1511. bytes[3] = *codes;
  1512. // RdHi
  1513. bytes[1] |= regval (&ins->oprs[1],1);
  1514. if (has_S_code)
  1515. bytes[1] |= 0x10;
  1516. // RdLo
  1517. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1518. // Rm
  1519. bytes[3] |= regval (&ins->oprs[2],1);
  1520. // Rs
  1521. bytes[2] |= regval (&ins->oprs[3],1);
  1522. break;
  1523. case 0x17: // LDR Rd, expression
  1524. ++codes;
  1525. bytes[0] = c | *codes++;
  1526. bytes[1] = *codes++;
  1527. // Rd
  1528. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1529. if (has_B_code)
  1530. bytes[1] |= 0x40;
  1531. if (has_T_code)
  1532. {
  1533. errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
  1534. }
  1535. if (has_W_code)
  1536. {
  1537. errfunc (ERR_NONFATAL, "'!' not allowed");
  1538. }
  1539. // Rn - implicit R15
  1540. bytes[1] |= 0xF;
  1541. if (ins->oprs[1].segment != segment)
  1542. {
  1543. errfunc (ERR_NONFATAL, "label not in same segment");
  1544. }
  1545. data = ins->oprs[1].offset - (offset + 8);
  1546. if (data < 0)
  1547. {
  1548. data = -data;
  1549. }
  1550. else
  1551. {
  1552. bytes[1] |= 0x80;
  1553. }
  1554. if (data >= 0x1000)
  1555. {
  1556. errfunc (ERR_NONFATAL, "too long offset");
  1557. }
  1558. bytes[2] |= ((data & 0xF00) >> 8);
  1559. bytes[3] = data & 0xFF;
  1560. break;
  1561. case 0x18: // LDR Rd, [Rn]
  1562. ++codes;
  1563. bytes[0] = c | *codes++;
  1564. bytes[1] = *codes++;
  1565. // Rd
  1566. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1567. if (has_B_code)
  1568. bytes[1] |= 0x40;
  1569. if (has_T_code)
  1570. {
  1571. bytes[1] |= 0x20; // write-back
  1572. }
  1573. else
  1574. {
  1575. bytes[0] |= 0x01; // implicit pre-index mode
  1576. }
  1577. if (has_W_code)
  1578. {
  1579. bytes[1] |= 0x20; // write-back
  1580. }
  1581. // Rn
  1582. c = regval (&ins->oprs[1],1);
  1583. bytes[1] |= c;
  1584. if (c == 0x15) // R15
  1585. data = -8;
  1586. else
  1587. data = 0;
  1588. if (data < 0)
  1589. {
  1590. data = -data;
  1591. }
  1592. else
  1593. {
  1594. bytes[1] |= 0x80;
  1595. }
  1596. bytes[2] |= ((data & 0xF00) >> 8);
  1597. bytes[3] = data & 0xFF;
  1598. break;
  1599. case 0x19: // LDR Rd, [Rn,#expression]
  1600. case 0x20: // LDR Rd, [Rn,Rm]
  1601. case 0x21: // LDR Rd, [Rn,Rm,shift]
  1602. ++codes;
  1603. bytes[0] = c | *codes++;
  1604. bytes[1] = *codes++;
  1605. // Rd
  1606. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1607. if (has_B_code)
  1608. bytes[1] |= 0x40;
  1609. // Rn
  1610. c = regval (&ins->oprs[1],1);
  1611. bytes[1] |= c;
  1612. if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
  1613. {
  1614. bytes[0] |= 0x01; // pre-index mode
  1615. if (has_W_code)
  1616. {
  1617. bytes[1] |= 0x20;
  1618. }
  1619. if (has_T_code)
  1620. {
  1621. errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
  1622. }
  1623. }
  1624. else
  1625. {
  1626. if (has_T_code) // Forced write-back in post-index mode
  1627. {
  1628. bytes[1] |= 0x20;
  1629. }
  1630. if (has_W_code)
  1631. {
  1632. errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
  1633. }
  1634. }
  1635. if (keep == 0x19)
  1636. {
  1637. data = ins->oprs[2].offset;
  1638. if (data < 0)
  1639. {
  1640. data = -data;
  1641. }
  1642. else
  1643. {
  1644. bytes[1] |= 0x80;
  1645. }
  1646. if (data >= 0x1000)
  1647. {
  1648. errfunc (ERR_NONFATAL, "too long offset");
  1649. }
  1650. bytes[2] |= ((data & 0xF00) >> 8);
  1651. bytes[3] = data & 0xFF;
  1652. }
  1653. else
  1654. {
  1655. if (ins->oprs[2].minus == 0)
  1656. {
  1657. bytes[1] |= 0x80;
  1658. }
  1659. c = regval (&ins->oprs[2],1);
  1660. bytes[3] = c;
  1661. if (keep == 0x21)
  1662. {
  1663. c = ins->oprs[3].offset;
  1664. if (c > 0x1F)
  1665. {
  1666. errfunc (ERR_NONFATAL, "too large shiftvalue");
  1667. c = c & 0x1F;
  1668. }
  1669. bytes[2] |= c >> 1;
  1670. if (c & 0x01)
  1671. {
  1672. bytes[3] |= 0x80;
  1673. }
  1674. bytes[3] |= shiftval (&ins->oprs[3]) << 5;
  1675. }
  1676. }
  1677. break;
  1678. case 0x22: // LDRH Rd, expression
  1679. ++codes;
  1680. bytes[0] = c | 0x01; // Implicit pre-index
  1681. bytes[1] = *codes++;
  1682. // Rd
  1683. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1684. // Rn - implicit R15
  1685. bytes[1] |= 0xF;
  1686. if (ins->oprs[1].segment != segment)
  1687. {
  1688. errfunc (ERR_NONFATAL, "label not in same segment");
  1689. }
  1690. data = ins->oprs[1].offset - (offset + 8);
  1691. if (data < 0)
  1692. {
  1693. data = -data;
  1694. }
  1695. else
  1696. {
  1697. bytes[1] |= 0x80;
  1698. }
  1699. if (data >= 0x100)
  1700. {
  1701. errfunc (ERR_NONFATAL, "too long offset");
  1702. }
  1703. bytes[3] = *codes++;
  1704. bytes[2] |= ((data & 0xF0) >> 4);
  1705. bytes[3] |= data & 0xF;
  1706. break;
  1707. case 0x23: // LDRH Rd, Rn
  1708. ++codes;
  1709. bytes[0] = c | 0x01; // Implicit pre-index
  1710. bytes[1] = *codes++;
  1711. // Rd
  1712. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1713. // Rn
  1714. c = regval (&ins->oprs[1],1);
  1715. bytes[1] |= c;
  1716. if (c == 0x15) // R15
  1717. data = -8;
  1718. else
  1719. data = 0;
  1720. if (data < 0)
  1721. {
  1722. data = -data;
  1723. }
  1724. else
  1725. {
  1726. bytes[1] |= 0x80;
  1727. }
  1728. if (data >= 0x100)
  1729. {
  1730. errfunc (ERR_NONFATAL, "too long offset");
  1731. }
  1732. bytes[3] = *codes++;
  1733. bytes[2] |= ((data & 0xF0) >> 4);
  1734. bytes[3] |= data & 0xF;
  1735. break;
  1736. case 0x24: // LDRH Rd, Rn, expression
  1737. case 0x25: // LDRH Rd, Rn, Rm
  1738. ++codes;
  1739. bytes[0] = c;
  1740. bytes[1] = *codes++;
  1741. // Rd
  1742. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1743. // Rn
  1744. c = regval (&ins->oprs[1],1);
  1745. bytes[1] |= c;
  1746. if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
  1747. {
  1748. bytes[0] |= 0x01; // pre-index mode
  1749. if (has_W_code)
  1750. {
  1751. bytes[1] |= 0x20;
  1752. }
  1753. }
  1754. else
  1755. {
  1756. if (has_W_code)
  1757. {
  1758. errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
  1759. }
  1760. }
  1761. bytes[3] = *codes++;
  1762. if (keep == 0x24)
  1763. {
  1764. data = ins->oprs[2].offset;
  1765. if (data < 0)
  1766. {
  1767. data = -data;
  1768. }
  1769. else
  1770. {
  1771. bytes[1] |= 0x80;
  1772. }
  1773. if (data >= 0x100)
  1774. {
  1775. errfunc (ERR_NONFATAL, "too long offset");
  1776. }
  1777. bytes[2] |= ((data & 0xF0) >> 4);
  1778. bytes[3] |= data & 0xF;
  1779. }
  1780. else
  1781. {
  1782. if (ins->oprs[2].minus == 0)
  1783. {
  1784. bytes[1] |= 0x80;
  1785. }
  1786. c = regval (&ins->oprs[2],1);
  1787. bytes[3] |= c;
  1788. }
  1789. break;
  1790. case 0x26: // LDM/STM Rn, {reg-list}
  1791. ++codes;
  1792. bytes[0] = c;
  1793. bytes[0] |= ( *codes >> 4) & 0xF;
  1794. bytes[1] = ( *codes << 4) & 0xF0;
  1795. ++codes;
  1796. if (has_W_code)
  1797. {
  1798. bytes[1] |= 0x20;
  1799. }
  1800. if (has_F_code)
  1801. {
  1802. bytes[1] |= 0x40;
  1803. }
  1804. // Rn
  1805. bytes[1] |= regval (&ins->oprs[0],1);
  1806. data = ins->oprs[1].basereg;
  1807. bytes[2] = ((data >> 8) & 0xFF);
  1808. bytes[3] = (data & 0xFF);
  1809. break;
  1810. case 0x27: // SWP Rd, Rm, [Rn]
  1811. ++codes;
  1812. bytes[0] = c;
  1813. bytes[0] |= *codes++;
  1814. bytes[1] = regval (&ins->oprs[2],1);
  1815. if (has_B_code)
  1816. {
  1817. bytes[1] |= 0x40;
  1818. }
  1819. bytes[2] = regval (&ins->oprs[0],1) << 4;
  1820. bytes[3] = *codes++;
  1821. bytes[3] |= regval (&ins->oprs[1],1);
  1822. break;
  1823. default:
  1824. errfunc (ERR_FATAL, "unknown decoding of instruction");
  1825. bytes[0] = c;
  1826. // And a fix nibble
  1827. ++codes;
  1828. bytes[0] |= *codes++;
  1829. if ( *codes == 0x01) // An I bit
  1830. {
  1831. }
  1832. if ( *codes == 0x02) // An I bit
  1833. {
  1834. }
  1835. ++codes;
  1836. }
  1837. out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
  1838. }
  1839. *)
  1840. {$endif dummy
  1841. }