SH4Assembler.h 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242
  1. /*
  2. * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved.
  3. * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
  4. * Copyright (C) 2008 Apple Inc. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  16. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  18. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  19. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  21. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  22. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  23. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #ifndef SH4Assembler_h
  28. #define SH4Assembler_h
  29. #if ENABLE(ASSEMBLER) && CPU(SH4)
  30. #include "AssemblerBuffer.h"
  31. #include "AssemblerBufferWithConstantPool.h"
  32. #include "JITCompilationEffort.h"
  33. #include <stdarg.h>
  34. #include <stdint.h>
  35. #include <stdio.h>
  36. #include <wtf/Assertions.h>
  37. #include <wtf/DataLog.h>
  38. #include <wtf/Vector.h>
  39. #ifndef NDEBUG
  40. #define SH4_ASSEMBLER_TRACING
  41. #endif
  42. namespace JSC {
  43. typedef uint16_t SH4Word;
  44. enum {
  45. INVALID_OPCODE = 0xffff,
  46. ADD_OPCODE = 0x300c,
  47. ADDIMM_OPCODE = 0x7000,
  48. ADDC_OPCODE = 0x300e,
  49. ADDV_OPCODE = 0x300f,
  50. AND_OPCODE = 0x2009,
  51. ANDIMM_OPCODE = 0xc900,
  52. DIV0_OPCODE = 0x2007,
  53. DIV1_OPCODE = 0x3004,
  54. BF_OPCODE = 0x8b00,
  55. BFS_OPCODE = 0x8f00,
  56. BRA_OPCODE = 0xa000,
  57. BRAF_OPCODE = 0x0023,
  58. NOP_OPCODE = 0x0009,
  59. BSR_OPCODE = 0xb000,
  60. RTS_OPCODE = 0x000b,
  61. BT_OPCODE = 0x8900,
  62. BTS_OPCODE = 0x8d00,
  63. BSRF_OPCODE = 0x0003,
  64. BRK_OPCODE = 0x003b,
  65. FTRC_OPCODE = 0xf03d,
  66. CMPEQ_OPCODE = 0x3000,
  67. CMPEQIMM_OPCODE = 0x8800,
  68. CMPGE_OPCODE = 0x3003,
  69. CMPGT_OPCODE = 0x3007,
  70. CMPHI_OPCODE = 0x3006,
  71. CMPHS_OPCODE = 0x3002,
  72. CMPPL_OPCODE = 0x4015,
  73. CMPPZ_OPCODE = 0x4011,
  74. CMPSTR_OPCODE = 0x200c,
  75. DT_OPCODE = 0x4010,
  76. FCMPEQ_OPCODE = 0xf004,
  77. FCMPGT_OPCODE = 0xf005,
  78. FMOV_OPCODE = 0xf00c,
  79. FADD_OPCODE = 0xf000,
  80. FMUL_OPCODE = 0xf002,
  81. FSUB_OPCODE = 0xf001,
  82. FDIV_OPCODE = 0xf003,
  83. FNEG_OPCODE = 0xf04d,
  84. JMP_OPCODE = 0x402b,
  85. JSR_OPCODE = 0x400b,
  86. LDSPR_OPCODE = 0x402a,
  87. LDSLPR_OPCODE = 0x4026,
  88. MOV_OPCODE = 0x6003,
  89. MOVIMM_OPCODE = 0xe000,
  90. MOVB_WRITE_RN_OPCODE = 0x2000,
  91. MOVB_WRITE_RNDEC_OPCODE = 0x2004,
  92. MOVB_WRITE_R0RN_OPCODE = 0x0004,
  93. MOVB_WRITE_OFFGBR_OPCODE = 0xc000,
  94. MOVB_WRITE_OFFRN_OPCODE = 0x8000,
  95. MOVB_READ_RM_OPCODE = 0x6000,
  96. MOVB_READ_RMINC_OPCODE = 0x6004,
  97. MOVB_READ_R0RM_OPCODE = 0x000c,
  98. MOVB_READ_OFFGBR_OPCODE = 0xc400,
  99. MOVB_READ_OFFRM_OPCODE = 0x8400,
  100. MOVL_WRITE_RN_OPCODE = 0x2002,
  101. MOVL_WRITE_RNDEC_OPCODE = 0x2006,
  102. MOVL_WRITE_R0RN_OPCODE = 0x0006,
  103. MOVL_WRITE_OFFGBR_OPCODE = 0xc200,
  104. MOVL_WRITE_OFFRN_OPCODE = 0x1000,
  105. MOVL_READ_RM_OPCODE = 0x6002,
  106. MOVL_READ_RMINC_OPCODE = 0x6006,
  107. MOVL_READ_R0RM_OPCODE = 0x000e,
  108. MOVL_READ_OFFGBR_OPCODE = 0xc600,
  109. MOVL_READ_OFFPC_OPCODE = 0xd000,
  110. MOVL_READ_OFFRM_OPCODE = 0x5000,
  111. MOVW_WRITE_RN_OPCODE = 0x2001,
  112. MOVW_WRITE_R0RN_OPCODE = 0x0005,
  113. MOVW_READ_RM_OPCODE = 0x6001,
  114. MOVW_READ_RMINC_OPCODE = 0x6005,
  115. MOVW_READ_R0RM_OPCODE = 0x000d,
  116. MOVW_READ_OFFRM_OPCODE = 0x8500,
  117. MOVW_READ_OFFPC_OPCODE = 0x9000,
  118. MOVA_READ_OFFPC_OPCODE = 0xc700,
  119. MOVT_OPCODE = 0x0029,
  120. MULL_OPCODE = 0x0007,
  121. DMULL_L_OPCODE = 0x3005,
  122. STSMACL_OPCODE = 0x001a,
  123. STSMACH_OPCODE = 0x000a,
  124. DMULSL_OPCODE = 0x300d,
  125. NEG_OPCODE = 0x600b,
  126. NEGC_OPCODE = 0x600a,
  127. NOT_OPCODE = 0x6007,
  128. OR_OPCODE = 0x200b,
  129. ORIMM_OPCODE = 0xcb00,
  130. ORBIMM_OPCODE = 0xcf00,
  131. SETS_OPCODE = 0x0058,
  132. SETT_OPCODE = 0x0018,
  133. SHAD_OPCODE = 0x400c,
  134. SHAL_OPCODE = 0x4020,
  135. SHAR_OPCODE = 0x4021,
  136. SHLD_OPCODE = 0x400d,
  137. SHLL_OPCODE = 0x4000,
  138. SHLL2_OPCODE = 0x4008,
  139. SHLL8_OPCODE = 0x4018,
  140. SHLL16_OPCODE = 0x4028,
  141. SHLR_OPCODE = 0x4001,
  142. SHLR2_OPCODE = 0x4009,
  143. SHLR8_OPCODE = 0x4019,
  144. SHLR16_OPCODE = 0x4029,
  145. STSPR_OPCODE = 0x002a,
  146. STSLPR_OPCODE = 0x4022,
  147. FLOAT_OPCODE = 0xf02d,
  148. SUB_OPCODE = 0x3008,
  149. SUBC_OPCODE = 0x300a,
  150. SUBV_OPCODE = 0x300b,
  151. TST_OPCODE = 0x2008,
  152. TSTIMM_OPCODE = 0xc800,
  153. TSTB_OPCODE = 0xcc00,
  154. EXTUB_OPCODE = 0x600c,
  155. EXTUW_OPCODE = 0x600d,
  156. XOR_OPCODE = 0x200a,
  157. XORIMM_OPCODE = 0xca00,
  158. XORB_OPCODE = 0xce00,
  159. FMOVS_READ_RM_INC_OPCODE = 0xf009,
  160. FMOVS_READ_RM_OPCODE = 0xf008,
  161. FMOVS_READ_R0RM_OPCODE = 0xf006,
  162. FMOVS_WRITE_RN_OPCODE = 0xf00a,
  163. FMOVS_WRITE_RN_DEC_OPCODE = 0xf00b,
  164. FMOVS_WRITE_R0RN_OPCODE = 0xf007,
  165. FCNVDS_DRM_FPUL_OPCODE = 0xf0bd,
  166. FCNVSD_FPUL_DRN_OPCODE = 0xf0ad,
  167. LDS_RM_FPUL_OPCODE = 0x405a,
  168. FLDS_FRM_FPUL_OPCODE = 0xf01d,
  169. STS_FPUL_RN_OPCODE = 0x005a,
  170. FSTS_FPUL_FRN_OPCODE = 0xF00d,
  171. LDSFPSCR_OPCODE = 0x406a,
  172. STSFPSCR_OPCODE = 0x006a,
  173. LDSRMFPUL_OPCODE = 0x405a,
  174. FSTSFPULFRN_OPCODE = 0xf00d,
  175. FABS_OPCODE = 0xf05d,
  176. FSQRT_OPCODE = 0xf06d,
  177. FSCHG_OPCODE = 0xf3fd,
  178. CLRT_OPCODE = 8,
  179. };
  180. namespace SH4Registers {
  181. typedef enum {
  182. r0,
  183. r1,
  184. r2,
  185. r3,
  186. r4,
  187. r5,
  188. r6,
  189. r7,
  190. r8,
  191. r9,
  192. r10,
  193. r11,
  194. r12,
  195. r13,
  196. r14, fp = r14,
  197. r15, sp = r15,
  198. pc,
  199. pr,
  200. } RegisterID;
  201. typedef enum {
  202. fr0, dr0 = fr0,
  203. fr1,
  204. fr2, dr2 = fr2,
  205. fr3,
  206. fr4, dr4 = fr4,
  207. fr5,
  208. fr6, dr6 = fr6,
  209. fr7,
  210. fr8, dr8 = fr8,
  211. fr9,
  212. fr10, dr10 = fr10,
  213. fr11,
  214. fr12, dr12 = fr12,
  215. fr13,
  216. fr14, dr14 = fr14,
  217. fr15,
  218. } FPRegisterID;
  219. }
  220. inline uint16_t getOpcodeGroup1(uint16_t opc, int rm, int rn)
  221. {
  222. return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4));
  223. }
  224. inline uint16_t getOpcodeGroup2(uint16_t opc, int rm)
  225. {
  226. return (opc | ((rm & 0xf) << 8));
  227. }
  228. inline uint16_t getOpcodeGroup3(uint16_t opc, int rm, int rn)
  229. {
  230. return (opc | ((rm & 0xf) << 8) | (rn & 0xff));
  231. }
  232. inline uint16_t getOpcodeGroup4(uint16_t opc, int rm, int rn, int offset)
  233. {
  234. return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4) | (offset & 0xf));
  235. }
  236. inline uint16_t getOpcodeGroup5(uint16_t opc, int rm)
  237. {
  238. return (opc | (rm & 0xff));
  239. }
  240. inline uint16_t getOpcodeGroup6(uint16_t opc, int rm)
  241. {
  242. return (opc | (rm & 0xfff));
  243. }
  244. inline uint16_t getOpcodeGroup7(uint16_t opc, int rm)
  245. {
  246. return (opc | ((rm & 0x7) << 9));
  247. }
  248. inline uint16_t getOpcodeGroup8(uint16_t opc, int rm, int rn)
  249. {
  250. return (opc | ((rm & 0x7) << 9) | ((rn & 0x7) << 5));
  251. }
  252. inline uint16_t getOpcodeGroup9(uint16_t opc, int rm, int rn)
  253. {
  254. return (opc | ((rm & 0xf) << 8) | ((rn & 0x7) << 5));
  255. }
  256. inline uint16_t getOpcodeGroup10(uint16_t opc, int rm, int rn)
  257. {
  258. return (opc | ((rm & 0x7) << 9) | ((rn & 0xf) << 4));
  259. }
  260. inline uint16_t getOpcodeGroup11(uint16_t opc, int rm, int rn)
  261. {
  262. return (opc | ((rm & 0xf) << 4) | (rn & 0xf));
  263. }
  264. inline uint16_t getRn(uint16_t x)
  265. {
  266. return ((x & 0xf00) >> 8);
  267. }
  268. inline uint16_t getRm(uint16_t x)
  269. {
  270. return ((x & 0xf0) >> 4);
  271. }
  272. inline uint16_t getDisp(uint16_t x)
  273. {
  274. return (x & 0xf);
  275. }
  276. inline uint16_t getImm8(uint16_t x)
  277. {
  278. return (x & 0xff);
  279. }
  280. inline uint16_t getImm12(uint16_t x)
  281. {
  282. return (x & 0xfff);
  283. }
  284. inline uint16_t getDRn(uint16_t x)
  285. {
  286. return ((x & 0xe00) >> 9);
  287. }
  288. inline uint16_t getDRm(uint16_t x)
  289. {
  290. return ((x & 0xe0) >> 5);
  291. }
  292. class SH4Assembler {
  293. public:
  294. typedef SH4Registers::RegisterID RegisterID;
  295. typedef SH4Registers::FPRegisterID FPRegisterID;
  296. typedef AssemblerBufferWithConstantPool<512, 4, 2, SH4Assembler> SH4Buffer;
  297. static const RegisterID scratchReg1 = SH4Registers::r3;
  298. static const RegisterID scratchReg2 = SH4Registers::r11;
  299. static const uint32_t maxInstructionSize = 16;
  300. enum {
  301. padForAlign8 = 0x00,
  302. padForAlign16 = 0x0009,
  303. padForAlign32 = 0x00090009,
  304. };
  305. enum JumpType {
  306. JumpFar,
  307. JumpNear
  308. };
  309. SH4Assembler()
  310. {
  311. m_claimscratchReg = 0x0;
  312. }
  313. // SH4 condition codes
  314. typedef enum {
  315. EQ = 0x0, // Equal
  316. NE = 0x1, // Not Equal
  317. HS = 0x2, // Unsigned Greater Than equal
  318. HI = 0x3, // Unsigned Greater Than
  319. LS = 0x4, // Unsigned Lower or Same
  320. LI = 0x5, // Unsigned Lower
  321. GE = 0x6, // Greater or Equal
  322. LT = 0x7, // Less Than
  323. GT = 0x8, // Greater Than
  324. LE = 0x9, // Less or Equal
  325. OF = 0xa, // OverFlow
  326. SI = 0xb, // Signed
  327. NS = 0xc, // Not Signed
  328. EQU= 0xd, // Equal or unordered(NaN)
  329. NEU= 0xe,
  330. GTU= 0xf,
  331. GEU= 0x10,
  332. LTU= 0x11,
  333. LEU= 0x12,
  334. } Condition;
  335. // Opaque label types
  336. public:
  337. bool isImmediate(int constant)
  338. {
  339. return ((constant <= 127) && (constant >= -128));
  340. }
  341. RegisterID claimScratch()
  342. {
  343. ASSERT((m_claimscratchReg != 0x3));
  344. if (!(m_claimscratchReg & 0x1)) {
  345. m_claimscratchReg = (m_claimscratchReg | 0x1);
  346. return scratchReg1;
  347. }
  348. m_claimscratchReg = (m_claimscratchReg | 0x2);
  349. return scratchReg2;
  350. }
  351. void releaseScratch(RegisterID scratchR)
  352. {
  353. if (scratchR == scratchReg1)
  354. m_claimscratchReg = (m_claimscratchReg & 0x2);
  355. else
  356. m_claimscratchReg = (m_claimscratchReg & 0x1);
  357. }
  358. // Stack operations
  359. void pushReg(RegisterID reg)
  360. {
  361. if (reg == SH4Registers::pr) {
  362. oneShortOp(getOpcodeGroup2(STSLPR_OPCODE, SH4Registers::sp));
  363. return;
  364. }
  365. oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE, SH4Registers::sp, reg));
  366. }
  367. void popReg(RegisterID reg)
  368. {
  369. if (reg == SH4Registers::pr) {
  370. oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE, SH4Registers::sp));
  371. return;
  372. }
  373. oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, reg, SH4Registers::sp));
  374. }
  375. void movt(RegisterID dst)
  376. {
  377. uint16_t opc = getOpcodeGroup2(MOVT_OPCODE, dst);
  378. oneShortOp(opc);
  379. }
  380. // Arithmetic operations
  381. void addlRegReg(RegisterID src, RegisterID dst)
  382. {
  383. uint16_t opc = getOpcodeGroup1(ADD_OPCODE, dst, src);
  384. oneShortOp(opc);
  385. }
  386. void addclRegReg(RegisterID src, RegisterID dst)
  387. {
  388. uint16_t opc = getOpcodeGroup1(ADDC_OPCODE, dst, src);
  389. oneShortOp(opc);
  390. }
  391. void addvlRegReg(RegisterID src, RegisterID dst)
  392. {
  393. uint16_t opc = getOpcodeGroup1(ADDV_OPCODE, dst, src);
  394. oneShortOp(opc);
  395. }
  396. void addlImm8r(int imm8, RegisterID dst)
  397. {
  398. ASSERT((imm8 <= 127) && (imm8 >= -128));
  399. uint16_t opc = getOpcodeGroup3(ADDIMM_OPCODE, dst, imm8);
  400. oneShortOp(opc);
  401. }
  402. void andlRegReg(RegisterID src, RegisterID dst)
  403. {
  404. uint16_t opc = getOpcodeGroup1(AND_OPCODE, dst, src);
  405. oneShortOp(opc);
  406. }
  407. void andlImm8r(int imm8, RegisterID dst)
  408. {
  409. ASSERT((imm8 <= 255) && (imm8 >= 0));
  410. ASSERT(dst == SH4Registers::r0);
  411. uint16_t opc = getOpcodeGroup5(ANDIMM_OPCODE, imm8);
  412. oneShortOp(opc);
  413. }
  414. void div1lRegReg(RegisterID src, RegisterID dst)
  415. {
  416. uint16_t opc = getOpcodeGroup1(DIV1_OPCODE, dst, src);
  417. oneShortOp(opc);
  418. }
  419. void div0lRegReg(RegisterID src, RegisterID dst)
  420. {
  421. uint16_t opc = getOpcodeGroup1(DIV0_OPCODE, dst, src);
  422. oneShortOp(opc);
  423. }
  424. void notlReg(RegisterID src, RegisterID dst)
  425. {
  426. uint16_t opc = getOpcodeGroup1(NOT_OPCODE, dst, src);
  427. oneShortOp(opc);
  428. }
  429. void orlRegReg(RegisterID src, RegisterID dst)
  430. {
  431. uint16_t opc = getOpcodeGroup1(OR_OPCODE, dst, src);
  432. oneShortOp(opc);
  433. }
  434. void orlImm8r(int imm8, RegisterID dst)
  435. {
  436. ASSERT((imm8 <= 255) && (imm8 >= 0));
  437. ASSERT(dst == SH4Registers::r0);
  438. uint16_t opc = getOpcodeGroup5(ORIMM_OPCODE, imm8);
  439. oneShortOp(opc);
  440. }
  441. void sublRegReg(RegisterID src, RegisterID dst)
  442. {
  443. uint16_t opc = getOpcodeGroup1(SUB_OPCODE, dst, src);
  444. oneShortOp(opc);
  445. }
  446. void subvlRegReg(RegisterID src, RegisterID dst)
  447. {
  448. uint16_t opc = getOpcodeGroup1(SUBV_OPCODE, dst, src);
  449. oneShortOp(opc);
  450. }
  451. void xorlRegReg(RegisterID src, RegisterID dst)
  452. {
  453. uint16_t opc = getOpcodeGroup1(XOR_OPCODE, dst, src);
  454. oneShortOp(opc);
  455. }
  456. void xorlImm8r(int imm8, RegisterID dst)
  457. {
  458. ASSERT((imm8 <= 255) && (imm8 >= 0));
  459. ASSERT(dst == SH4Registers::r0);
  460. uint16_t opc = getOpcodeGroup5(XORIMM_OPCODE, imm8);
  461. oneShortOp(opc);
  462. }
  463. void shllImm8r(int imm, RegisterID dst)
  464. {
  465. switch (imm) {
  466. case 1:
  467. oneShortOp(getOpcodeGroup2(SHLL_OPCODE, dst));
  468. break;
  469. case 2:
  470. oneShortOp(getOpcodeGroup2(SHLL2_OPCODE, dst));
  471. break;
  472. case 8:
  473. oneShortOp(getOpcodeGroup2(SHLL8_OPCODE, dst));
  474. break;
  475. case 16:
  476. oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst));
  477. break;
  478. default:
  479. RELEASE_ASSERT_NOT_REACHED();
  480. }
  481. }
  482. void neg(RegisterID dst, RegisterID src)
  483. {
  484. uint16_t opc = getOpcodeGroup1(NEG_OPCODE, dst, src);
  485. oneShortOp(opc);
  486. }
  487. void shldRegReg(RegisterID dst, RegisterID rShift)
  488. {
  489. oneShortOp(getOpcodeGroup1(SHLD_OPCODE, dst, rShift));
  490. }
  491. void shadRegReg(RegisterID dst, RegisterID rShift)
  492. {
  493. oneShortOp(getOpcodeGroup1(SHAD_OPCODE, dst, rShift));
  494. }
  495. void shlrImm8r(int imm, RegisterID dst)
  496. {
  497. switch (imm) {
  498. case 1:
  499. oneShortOp(getOpcodeGroup2(SHLR_OPCODE, dst));
  500. break;
  501. case 2:
  502. oneShortOp(getOpcodeGroup2(SHLR2_OPCODE, dst));
  503. break;
  504. case 8:
  505. oneShortOp(getOpcodeGroup2(SHLR8_OPCODE, dst));
  506. break;
  507. case 16:
  508. oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst));
  509. break;
  510. default:
  511. RELEASE_ASSERT_NOT_REACHED();
  512. }
  513. }
  514. void shalImm8r(int imm, RegisterID dst)
  515. {
  516. switch (imm) {
  517. case 1:
  518. oneShortOp(getOpcodeGroup2(SHAL_OPCODE, dst));
  519. break;
  520. default:
  521. RELEASE_ASSERT_NOT_REACHED();
  522. }
  523. }
  524. void sharImm8r(int imm, RegisterID dst)
  525. {
  526. switch (imm) {
  527. case 1:
  528. oneShortOp(getOpcodeGroup2(SHAR_OPCODE, dst));
  529. break;
  530. default:
  531. RELEASE_ASSERT_NOT_REACHED();
  532. }
  533. }
  534. void imullRegReg(RegisterID src, RegisterID dst)
  535. {
  536. uint16_t opc = getOpcodeGroup1(MULL_OPCODE, dst, src);
  537. oneShortOp(opc);
  538. }
  539. void dmullRegReg(RegisterID src, RegisterID dst)
  540. {
  541. uint16_t opc = getOpcodeGroup1(DMULL_L_OPCODE, dst, src);
  542. oneShortOp(opc);
  543. }
  544. void dmulslRegReg(RegisterID src, RegisterID dst)
  545. {
  546. uint16_t opc = getOpcodeGroup1(DMULSL_OPCODE, dst, src);
  547. oneShortOp(opc);
  548. }
  549. void stsmacl(RegisterID reg)
  550. {
  551. uint16_t opc = getOpcodeGroup2(STSMACL_OPCODE, reg);
  552. oneShortOp(opc);
  553. }
  554. void stsmach(RegisterID reg)
  555. {
  556. uint16_t opc = getOpcodeGroup2(STSMACH_OPCODE, reg);
  557. oneShortOp(opc);
  558. }
  559. // Comparisons
  560. void cmplRegReg(RegisterID left, RegisterID right, Condition cond)
  561. {
  562. switch (cond) {
  563. case NE:
  564. oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
  565. break;
  566. case GT:
  567. oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, right, left));
  568. break;
  569. case EQ:
  570. oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
  571. break;
  572. case GE:
  573. oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, right, left));
  574. break;
  575. case HS:
  576. oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, right, left));
  577. break;
  578. case HI:
  579. oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, right, left));
  580. break;
  581. case LI:
  582. oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, left, right));
  583. break;
  584. case LS:
  585. oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, left, right));
  586. break;
  587. case LE:
  588. oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, left, right));
  589. break;
  590. case LT:
  591. oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right));
  592. break;
  593. default:
  594. RELEASE_ASSERT_NOT_REACHED();
  595. }
  596. }
  597. void cmppl(RegisterID reg)
  598. {
  599. uint16_t opc = getOpcodeGroup2(CMPPL_OPCODE, reg);
  600. oneShortOp(opc);
  601. }
  602. void cmppz(RegisterID reg)
  603. {
  604. uint16_t opc = getOpcodeGroup2(CMPPZ_OPCODE, reg);
  605. oneShortOp(opc);
  606. }
  607. void cmpEqImmR0(int imm, RegisterID dst)
  608. {
  609. uint16_t opc = getOpcodeGroup5(CMPEQIMM_OPCODE, imm);
  610. oneShortOp(opc);
  611. }
  612. void testlRegReg(RegisterID src, RegisterID dst)
  613. {
  614. uint16_t opc = getOpcodeGroup1(TST_OPCODE, dst, src);
  615. oneShortOp(opc);
  616. }
  617. void testlImm8r(int imm, RegisterID dst)
  618. {
  619. ASSERT((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0));
  620. uint16_t opc = getOpcodeGroup5(TSTIMM_OPCODE, imm);
  621. oneShortOp(opc);
  622. }
  623. void nop()
  624. {
  625. oneShortOp(NOP_OPCODE, false);
  626. }
  627. void sett()
  628. {
  629. oneShortOp(SETT_OPCODE);
  630. }
  631. void clrt()
  632. {
  633. oneShortOp(CLRT_OPCODE);
  634. }
  635. void fschg()
  636. {
  637. oneShortOp(FSCHG_OPCODE);
  638. }
  639. void bkpt()
  640. {
  641. oneShortOp(BRK_OPCODE, false);
  642. }
  643. void branch(uint16_t opc, int label)
  644. {
  645. switch (opc) {
  646. case BT_OPCODE:
  647. ASSERT((label <= 127) && (label >= -128));
  648. oneShortOp(getOpcodeGroup5(BT_OPCODE, label));
  649. break;
  650. case BRA_OPCODE:
  651. ASSERT((label <= 2047) && (label >= -2048));
  652. oneShortOp(getOpcodeGroup6(BRA_OPCODE, label));
  653. break;
  654. case BF_OPCODE:
  655. ASSERT((label <= 127) && (label >= -128));
  656. oneShortOp(getOpcodeGroup5(BF_OPCODE, label));
  657. break;
  658. default:
  659. RELEASE_ASSERT_NOT_REACHED();
  660. }
  661. }
  662. void branch(uint16_t opc, RegisterID reg)
  663. {
  664. switch (opc) {
  665. case BRAF_OPCODE:
  666. oneShortOp(getOpcodeGroup2(BRAF_OPCODE, reg));
  667. break;
  668. case JMP_OPCODE:
  669. oneShortOp(getOpcodeGroup2(JMP_OPCODE, reg));
  670. break;
  671. case JSR_OPCODE:
  672. oneShortOp(getOpcodeGroup2(JSR_OPCODE, reg));
  673. break;
  674. case BSRF_OPCODE:
  675. oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg));
  676. break;
  677. default:
  678. RELEASE_ASSERT_NOT_REACHED();
  679. }
  680. }
  681. void ldspr(RegisterID reg)
  682. {
  683. uint16_t opc = getOpcodeGroup2(LDSPR_OPCODE, reg);
  684. oneShortOp(opc);
  685. }
  686. void stspr(RegisterID reg)
  687. {
  688. uint16_t opc = getOpcodeGroup2(STSPR_OPCODE, reg);
  689. oneShortOp(opc);
  690. }
  691. void extub(RegisterID src, RegisterID dst)
  692. {
  693. uint16_t opc = getOpcodeGroup1(EXTUB_OPCODE, dst, src);
  694. oneShortOp(opc);
  695. }
  696. void extuw(RegisterID src, RegisterID dst)
  697. {
  698. uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src);
  699. oneShortOp(opc);
  700. }
  701. // float operations
  702. void ldsrmfpul(RegisterID src)
  703. {
  704. uint16_t opc = getOpcodeGroup2(LDS_RM_FPUL_OPCODE, src);
  705. oneShortOp(opc);
  706. }
  707. void fneg(FPRegisterID dst)
  708. {
  709. uint16_t opc = getOpcodeGroup2(FNEG_OPCODE, dst);
  710. oneShortOp(opc, true, false);
  711. }
  712. void fsqrt(FPRegisterID dst)
  713. {
  714. uint16_t opc = getOpcodeGroup2(FSQRT_OPCODE, dst);
  715. oneShortOp(opc, true, false);
  716. }
  717. void stsfpulReg(RegisterID src)
  718. {
  719. uint16_t opc = getOpcodeGroup2(STS_FPUL_RN_OPCODE, src);
  720. oneShortOp(opc);
  721. }
  722. void floatfpulfrn(FPRegisterID src)
  723. {
  724. uint16_t opc = getOpcodeGroup2(FLOAT_OPCODE, src);
  725. oneShortOp(opc, true, false);
  726. }
  727. void fmull(FPRegisterID src, FPRegisterID dst)
  728. {
  729. uint16_t opc = getOpcodeGroup1(FMUL_OPCODE, dst, src);
  730. oneShortOp(opc, true, false);
  731. }
  732. void fmovsRegReg(FPRegisterID src, FPRegisterID dst)
  733. {
  734. uint16_t opc = getOpcodeGroup1(FMOV_OPCODE, dst, src);
  735. oneShortOp(opc, true, false);
  736. }
  737. void fmovsReadrm(RegisterID src, FPRegisterID dst)
  738. {
  739. uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_OPCODE, dst, src);
  740. oneShortOp(opc, true, false);
  741. }
  742. void fmovsWriterm(FPRegisterID src, RegisterID dst)
  743. {
  744. uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE, dst, src);
  745. oneShortOp(opc, true, false);
  746. }
  747. void fmovsWriter0r(FPRegisterID src, RegisterID dst)
  748. {
  749. uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE, dst, src);
  750. oneShortOp(opc, true, false);
  751. }
  752. void fmovsReadr0r(RegisterID src, FPRegisterID dst)
  753. {
  754. uint16_t opc = getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE, dst, src);
  755. oneShortOp(opc, true, false);
  756. }
  757. void fmovsReadrminc(RegisterID src, FPRegisterID dst)
  758. {
  759. uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE, dst, src);
  760. oneShortOp(opc, true, false);
  761. }
  762. void fmovsWriterndec(FPRegisterID src, RegisterID dst)
  763. {
  764. uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE, dst, src);
  765. oneShortOp(opc, true, false);
  766. }
  767. void ftrcRegfpul(FPRegisterID src)
  768. {
  769. uint16_t opc = getOpcodeGroup2(FTRC_OPCODE, src);
  770. oneShortOp(opc, true, false);
  771. }
  772. void fldsfpul(FPRegisterID src)
  773. {
  774. uint16_t opc = getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE, src);
  775. oneShortOp(opc);
  776. }
  777. void fstsfpul(FPRegisterID src)
  778. {
  779. uint16_t opc = getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE, src);
  780. oneShortOp(opc);
  781. }
  782. void ldsfpscr(RegisterID reg)
  783. {
  784. uint16_t opc = getOpcodeGroup2(LDSFPSCR_OPCODE, reg);
  785. oneShortOp(opc);
  786. }
  787. void stsfpscr(RegisterID reg)
  788. {
  789. uint16_t opc = getOpcodeGroup2(STSFPSCR_OPCODE, reg);
  790. oneShortOp(opc);
  791. }
  792. // double operations
  793. void dcnvds(FPRegisterID src)
  794. {
  795. uint16_t opc = getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE, src >> 1);
  796. oneShortOp(opc);
  797. }
  798. void dcnvsd(FPRegisterID dst)
  799. {
  800. uint16_t opc = getOpcodeGroup7(FCNVSD_FPUL_DRN_OPCODE, dst >> 1);
  801. oneShortOp(opc);
  802. }
  803. void dcmppeq(FPRegisterID src, FPRegisterID dst)
  804. {
  805. uint16_t opc = getOpcodeGroup8(FCMPEQ_OPCODE, dst >> 1, src >> 1);
  806. oneShortOp(opc);
  807. }
  808. void dcmppgt(FPRegisterID src, FPRegisterID dst)
  809. {
  810. uint16_t opc = getOpcodeGroup8(FCMPGT_OPCODE, dst >> 1, src >> 1);
  811. oneShortOp(opc);
  812. }
  813. void dmulRegReg(FPRegisterID src, FPRegisterID dst)
  814. {
  815. uint16_t opc = getOpcodeGroup8(FMUL_OPCODE, dst >> 1, src >> 1);
  816. oneShortOp(opc);
  817. }
  818. void dsubRegReg(FPRegisterID src, FPRegisterID dst)
  819. {
  820. uint16_t opc = getOpcodeGroup8(FSUB_OPCODE, dst >> 1, src >> 1);
  821. oneShortOp(opc);
  822. }
  823. void daddRegReg(FPRegisterID src, FPRegisterID dst)
  824. {
  825. uint16_t opc = getOpcodeGroup8(FADD_OPCODE, dst >> 1, src >> 1);
  826. oneShortOp(opc);
  827. }
  828. void dmovRegReg(FPRegisterID src, FPRegisterID dst)
  829. {
  830. uint16_t opc = getOpcodeGroup8(FMOV_OPCODE, dst >> 1, src >> 1);
  831. oneShortOp(opc);
  832. }
  833. void ddivRegReg(FPRegisterID src, FPRegisterID dst)
  834. {
  835. uint16_t opc = getOpcodeGroup8(FDIV_OPCODE, dst >> 1, src >> 1);
  836. oneShortOp(opc);
  837. }
  838. void dabs(FPRegisterID dst)
  839. {
  840. uint16_t opc = getOpcodeGroup7(FABS_OPCODE, dst >> 1);
  841. oneShortOp(opc);
  842. }
  843. void dsqrt(FPRegisterID dst)
  844. {
  845. uint16_t opc = getOpcodeGroup7(FSQRT_OPCODE, dst >> 1);
  846. oneShortOp(opc);
  847. }
  848. void dneg(FPRegisterID dst)
  849. {
  850. uint16_t opc = getOpcodeGroup7(FNEG_OPCODE, dst >> 1);
  851. oneShortOp(opc);
  852. }
  853. void fmovReadrm(RegisterID src, FPRegisterID dst)
  854. {
  855. uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_OPCODE, dst >> 1, src);
  856. oneShortOp(opc);
  857. }
  858. void fmovWriterm(FPRegisterID src, RegisterID dst)
  859. {
  860. uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE, dst, src >> 1);
  861. oneShortOp(opc);
  862. }
  863. void fmovWriter0r(FPRegisterID src, RegisterID dst)
  864. {
  865. uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE, dst, src >> 1);
  866. oneShortOp(opc);
  867. }
  868. void fmovReadr0r(RegisterID src, FPRegisterID dst)
  869. {
  870. uint16_t opc = getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE, dst >> 1, src);
  871. oneShortOp(opc);
  872. }
  873. void fmovReadrminc(RegisterID src, FPRegisterID dst)
  874. {
  875. uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE, dst >> 1, src);
  876. oneShortOp(opc);
  877. }
  878. void fmovWriterndec(FPRegisterID src, RegisterID dst)
  879. {
  880. uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE, dst, src >> 1);
  881. oneShortOp(opc);
  882. }
  883. void floatfpulDreg(FPRegisterID src)
  884. {
  885. uint16_t opc = getOpcodeGroup7(FLOAT_OPCODE, src >> 1);
  886. oneShortOp(opc);
  887. }
  888. void ftrcdrmfpul(FPRegisterID src)
  889. {
  890. uint16_t opc = getOpcodeGroup7(FTRC_OPCODE, src >> 1);
  891. oneShortOp(opc);
  892. }
  893. // Various move ops
  894. void movImm8(int imm8, RegisterID dst)
  895. {
  896. ASSERT((imm8 <= 127) && (imm8 >= -128));
  897. uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
  898. oneShortOp(opc);
  899. }
  900. void movlRegReg(RegisterID src, RegisterID dst)
  901. {
  902. uint16_t opc = getOpcodeGroup1(MOV_OPCODE, dst, src);
  903. oneShortOp(opc);
  904. }
  905. void movwRegMem(RegisterID src, RegisterID dst)
  906. {
  907. uint16_t opc = getOpcodeGroup1(MOVW_WRITE_RN_OPCODE, dst, src);
  908. oneShortOp(opc);
  909. }
  910. void movwMemReg(RegisterID src, RegisterID dst)
  911. {
  912. uint16_t opc = getOpcodeGroup1(MOVW_READ_RM_OPCODE, dst, src);
  913. oneShortOp(opc);
  914. }
  915. void movwMemRegIn(RegisterID base, RegisterID dst)
  916. {
  917. uint16_t opc = getOpcodeGroup1(MOVW_READ_RMINC_OPCODE, dst, base);
  918. oneShortOp(opc);
  919. }
  920. void movwPCReg(int offset, RegisterID base, RegisterID dst)
  921. {
  922. ASSERT(base == SH4Registers::pc);
  923. ASSERT((offset <= 255) && (offset >= 0));
  924. uint16_t opc = getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE, dst, offset);
  925. oneShortOp(opc);
  926. }
  927. void movwMemReg(int offset, RegisterID base, RegisterID dst)
  928. {
  929. ASSERT(dst == SH4Registers::r0);
  930. uint16_t opc = getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE, base, offset);
  931. oneShortOp(opc);
  932. }
  933. void movwR0mr(RegisterID src, RegisterID dst)
  934. {
  935. uint16_t opc = getOpcodeGroup1(MOVW_READ_R0RM_OPCODE, dst, src);
  936. oneShortOp(opc);
  937. }
  938. void movwRegMemr0(RegisterID src, RegisterID dst)
  939. {
  940. uint16_t opc = getOpcodeGroup1(MOVW_WRITE_R0RN_OPCODE, dst, src);
  941. oneShortOp(opc);
  942. }
  943. void movlRegMem(RegisterID src, int offset, RegisterID base)
  944. {
  945. ASSERT((offset <= 15) && (offset >= 0));
  946. if (!offset) {
  947. oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src));
  948. return;
  949. }
  950. oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE, base, src, offset));
  951. }
  952. void movlRegMem(RegisterID src, RegisterID base)
  953. {
  954. uint16_t opc = getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src);
  955. oneShortOp(opc);
  956. }
  957. void movlMemReg(int offset, RegisterID base, RegisterID dst)
  958. {
  959. if (base == SH4Registers::pc) {
  960. ASSERT((offset <= 255) && (offset >= 0));
  961. oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, dst, offset));
  962. return;
  963. }
  964. ASSERT((offset <= 15) && (offset >= 0));
  965. if (!offset) {
  966. oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base));
  967. return;
  968. }
  969. oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
  970. }
  971. void movlMemRegCompact(int offset, RegisterID base, RegisterID dst)
  972. {
  973. oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
  974. }
  975. void movbRegMem(RegisterID src, RegisterID base)
  976. {
  977. uint16_t opc = getOpcodeGroup1(MOVB_WRITE_RN_OPCODE, base, src);
  978. oneShortOp(opc);
  979. }
  980. void movbMemReg(int offset, RegisterID base, RegisterID dst)
  981. {
  982. ASSERT(dst == SH4Registers::r0);
  983. uint16_t opc = getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE, base, offset);
  984. oneShortOp(opc);
  985. }
  986. void movbR0mr(RegisterID src, RegisterID dst)
  987. {
  988. uint16_t opc = getOpcodeGroup1(MOVB_READ_R0RM_OPCODE, dst, src);
  989. oneShortOp(opc);
  990. }
  991. void movbMemReg(RegisterID src, RegisterID dst)
  992. {
  993. uint16_t opc = getOpcodeGroup1(MOVB_READ_RM_OPCODE, dst, src);
  994. oneShortOp(opc);
  995. }
  996. void movbMemRegIn(RegisterID base, RegisterID dst)
  997. {
  998. uint16_t opc = getOpcodeGroup1(MOVB_READ_RMINC_OPCODE, dst, base);
  999. oneShortOp(opc);
  1000. }
  1001. void movbRegMemr0(RegisterID src, RegisterID dst)
  1002. {
  1003. uint16_t opc = getOpcodeGroup1(MOVB_WRITE_R0RN_OPCODE, dst, src);
  1004. oneShortOp(opc);
  1005. }
  1006. void movlMemReg(RegisterID base, RegisterID dst)
  1007. {
  1008. uint16_t opc = getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base);
  1009. oneShortOp(opc);
  1010. }
  1011. void movlMemRegIn(RegisterID base, RegisterID dst)
  1012. {
  1013. uint16_t opc = getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, dst, base);
  1014. oneShortOp(opc);
  1015. }
  1016. void movlR0mr(RegisterID src, RegisterID dst)
  1017. {
  1018. uint16_t opc = getOpcodeGroup1(MOVL_READ_R0RM_OPCODE, dst, src);
  1019. oneShortOp(opc);
  1020. }
  1021. void movlRegMemr0(RegisterID src, RegisterID dst)
  1022. {
  1023. uint16_t opc = getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE, dst, src);
  1024. oneShortOp(opc);
  1025. }
  1026. void movlImm8r(int imm8, RegisterID dst)
  1027. {
  1028. ASSERT((imm8 <= 127) && (imm8 >= -128));
  1029. uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
  1030. oneShortOp(opc);
  1031. }
  1032. void loadConstant(uint32_t constant, RegisterID dst)
  1033. {
  1034. if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) {
  1035. movImm8(constant, dst);
  1036. return;
  1037. }
  1038. uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
  1039. m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
  1040. printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
  1041. m_buffer.putShortWithConstantInt(opc, constant, true);
  1042. }
  1043. void loadConstantUnReusable(uint32_t constant, RegisterID dst, bool ensureSpace = false)
  1044. {
  1045. uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
  1046. if (ensureSpace)
  1047. m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
  1048. printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
  1049. m_buffer.putShortWithConstantInt(opc, constant);
  1050. }
  1051. // Flow control
  1052. AssemblerLabel call()
  1053. {
  1054. RegisterID scr = claimScratch();
  1055. m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
  1056. loadConstantUnReusable(0x0, scr);
  1057. branch(JSR_OPCODE, scr);
  1058. nop();
  1059. releaseScratch(scr);
  1060. return m_buffer.label();
  1061. }
  1062. AssemblerLabel call(RegisterID dst)
  1063. {
  1064. m_buffer.ensureSpace(maxInstructionSize + 2);
  1065. branch(JSR_OPCODE, dst);
  1066. nop();
  1067. return m_buffer.label();
  1068. }
  1069. AssemblerLabel jmp()
  1070. {
  1071. RegisterID scr = claimScratch();
  1072. m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
  1073. AssemblerLabel label = m_buffer.label();
  1074. loadConstantUnReusable(0x0, scr);
  1075. branch(BRAF_OPCODE, scr);
  1076. nop();
  1077. releaseScratch(scr);
  1078. return label;
  1079. }
  1080. void extraInstrForBranch(RegisterID dst)
  1081. {
  1082. loadConstantUnReusable(0x0, dst);
  1083. nop();
  1084. nop();
  1085. }
  1086. AssemblerLabel jmp(RegisterID dst)
  1087. {
  1088. jmpReg(dst);
  1089. return m_buffer.label();
  1090. }
  1091. void jmpReg(RegisterID dst)
  1092. {
  1093. m_buffer.ensureSpace(maxInstructionSize + 2);
  1094. branch(JMP_OPCODE, dst);
  1095. nop();
  1096. }
  1097. AssemblerLabel jne()
  1098. {
  1099. AssemblerLabel label = m_buffer.label();
  1100. branch(BF_OPCODE, 0);
  1101. return label;
  1102. }
  1103. AssemblerLabel je()
  1104. {
  1105. AssemblerLabel label = m_buffer.label();
  1106. branch(BT_OPCODE, 0);
  1107. return label;
  1108. }
  1109. AssemblerLabel bra()
  1110. {
  1111. AssemblerLabel label = m_buffer.label();
  1112. branch(BRA_OPCODE, 0);
  1113. return label;
  1114. }
  1115. void ret()
  1116. {
  1117. m_buffer.ensureSpace(maxInstructionSize + 2);
  1118. oneShortOp(RTS_OPCODE, false);
  1119. }
  1120. AssemblerLabel labelIgnoringWatchpoints()
  1121. {
  1122. m_buffer.ensureSpaceForAnyInstruction();
  1123. return m_buffer.label();
  1124. }
  1125. AssemblerLabel label()
  1126. {
  1127. m_buffer.ensureSpaceForAnyInstruction();
  1128. return m_buffer.label();
  1129. }
  1130. int sizeOfConstantPool()
  1131. {
  1132. return m_buffer.sizeOfConstantPool();
  1133. }
  1134. AssemblerLabel align(int alignment)
  1135. {
  1136. m_buffer.ensureSpace(maxInstructionSize + 2);
  1137. while (!m_buffer.isAligned(alignment)) {
  1138. nop();
  1139. m_buffer.ensureSpace(maxInstructionSize + 2);
  1140. }
  1141. return label();
  1142. }
  1143. static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress)
  1144. {
  1145. uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
  1146. *reinterpret_cast<uint32_t*>(address) = newAddress;
  1147. }
  1148. static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr)
  1149. {
  1150. uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
  1151. return *reinterpret_cast<uint32_t*>(address);
  1152. }
  1153. static uint16_t* getInstructionPtr(void* code, int offset)
  1154. {
  1155. return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code) + offset);
  1156. }
  1157. static void linkJump(void* code, AssemblerLabel from, void* to)
  1158. {
  1159. ASSERT(from.isSet());
  1160. uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
  1161. uint16_t instruction = *instructionPtr;
  1162. int offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(code)) - from.m_offset;
  1163. if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
  1164. /* BT label ==> BF 2
  1165. nop LDR reg
  1166. nop braf @reg
  1167. nop nop
  1168. */
  1169. offsetBits -= 8;
  1170. instruction ^= 0x0202;
  1171. *instructionPtr++ = instruction;
  1172. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
  1173. instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
  1174. *instructionPtr = instruction;
  1175. printBlockInstr(instructionPtr - 2, from.m_offset, 3);
  1176. return;
  1177. }
  1178. /* MOV #imm, reg => LDR reg
  1179. braf @reg braf @reg
  1180. nop nop
  1181. */
  1182. ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
  1183. offsetBits -= 4;
  1184. if (offsetBits >= -4096 && offsetBits <= 4094) {
  1185. *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
  1186. *(++instructionPtr) = NOP_OPCODE;
  1187. printBlockInstr(instructionPtr - 1, from.m_offset, 2);
  1188. return;
  1189. }
  1190. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
  1191. printInstr(*instructionPtr, from.m_offset + 2);
  1192. }
  1193. static void linkCall(void* code, AssemblerLabel from, void* to)
  1194. {
  1195. uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
  1196. instructionPtr -= 3;
  1197. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
  1198. }
  1199. static void linkPointer(void* code, AssemblerLabel where, void* value)
  1200. {
  1201. uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset);
  1202. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value));
  1203. }
  1204. static unsigned getCallReturnOffset(AssemblerLabel call)
  1205. {
  1206. ASSERT(call.isSet());
  1207. return call.m_offset;
  1208. }
  1209. static uint32_t* getLdrImmAddressOnPool(SH4Word* insn, uint32_t* constPool)
  1210. {
  1211. return (constPool + (*insn & 0xff));
  1212. }
  1213. static SH4Word patchConstantPoolLoad(SH4Word load, int value)
  1214. {
  1215. return ((load & ~0xff) | value);
  1216. }
  1217. static SH4Buffer::TwoShorts placeConstantPoolBarrier(int offset)
  1218. {
  1219. ASSERT(((offset >> 1) <= 2047) && ((offset >> 1) >= -2048));
  1220. SH4Buffer::TwoShorts m_barrier;
  1221. m_barrier.high = (BRA_OPCODE | (offset >> 1));
  1222. m_barrier.low = NOP_OPCODE;
  1223. printInstr(((BRA_OPCODE | (offset >> 1))), 0);
  1224. printInstr(NOP_OPCODE, 0);
  1225. return m_barrier;
  1226. }
  1227. static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr)
  1228. {
  1229. SH4Word* instructionPtr = reinterpret_cast<SH4Word*>(loadAddr);
  1230. SH4Word instruction = *instructionPtr;
  1231. SH4Word index = instruction & 0xff;
  1232. if ((instruction & 0xf000) != MOVIMM_OPCODE)
  1233. return;
  1234. ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024);
  1235. int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4);
  1236. instruction &=0xf00;
  1237. instruction |= 0xd000;
  1238. offset &= 0x03ff;
  1239. instruction |= (offset >> 2);
  1240. *instructionPtr = instruction;
  1241. printInstr(instruction, reinterpret_cast<uint32_t>(loadAddr));
  1242. }
  1243. static void repatchPointer(void* where, void* value)
  1244. {
  1245. patchPointer(where, value);
  1246. }
  1247. static void* readPointer(void* code)
  1248. {
  1249. return reinterpret_cast<void*>(readInt32(code));
  1250. }
  1251. static void repatchInt32(void* where, int32_t value)
  1252. {
  1253. uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
  1254. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value);
  1255. }
  1256. static void repatchCompact(void* where, int32_t value)
  1257. {
  1258. ASSERT(value >= 0);
  1259. ASSERT(value <= 60);
  1260. *reinterpret_cast<uint16_t*>(where) = ((*reinterpret_cast<uint16_t*>(where) & 0xfff0) | (value >> 2));
  1261. cacheFlush(reinterpret_cast<uint16_t*>(where), sizeof(uint16_t));
  1262. }
  1263. static void relinkCall(void* from, void* to)
  1264. {
  1265. uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from);
  1266. instructionPtr -= 3;
  1267. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
  1268. }
  1269. static void relinkJump(void* from, void* to)
  1270. {
  1271. uint16_t* instructionPtr = reinterpret_cast<uint16_t*> (from);
  1272. uint16_t instruction = *instructionPtr;
  1273. int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
  1274. if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) {
  1275. offsetBits -= 8;
  1276. instructionPtr++;
  1277. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
  1278. instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
  1279. *instructionPtr = instruction;
  1280. printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3);
  1281. return;
  1282. }
  1283. ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
  1284. offsetBits -= 4;
  1285. if (offsetBits >= -4096 && offsetBits <= 4094) {
  1286. *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
  1287. *(++instructionPtr) = NOP_OPCODE;
  1288. printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2);
  1289. return;
  1290. }
  1291. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
  1292. printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from));
  1293. }
  1294. // Linking & patching
  1295. static ptrdiff_t maxJumpReplacementSize()
  1296. {
  1297. return sizeof(SH4Word) * 6;
  1298. }
  1299. static void replaceWithJump(void *instructionStart, void *to)
  1300. {
  1301. SH4Word* instruction = reinterpret_cast<SH4Word*>(instructionStart);
  1302. intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + 2 * sizeof(SH4Word));
  1303. int nbinst = 0;
  1304. if ((difference >= -4096) && (difference <= 4094)) {
  1305. instruction[0] = getOpcodeGroup6(BRA_OPCODE, difference >> 1);
  1306. instruction[1] = NOP_OPCODE;
  1307. cacheFlush(instruction, sizeof(SH4Word) * 2);
  1308. return;
  1309. }
  1310. instruction[nbinst++] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, scratchReg2, 1);
  1311. instruction[nbinst++] = getOpcodeGroup2(JMP_OPCODE, scratchReg2);
  1312. instruction[nbinst++] = NOP_OPCODE;
  1313. if (!(reinterpret_cast<unsigned>(instruction) & 3))
  1314. instruction[nbinst++] = NOP_OPCODE;
  1315. instruction[nbinst++] = reinterpret_cast<unsigned>(to) & 0xffff;
  1316. instruction[nbinst++] = reinterpret_cast<unsigned>(to) >> 16;
  1317. cacheFlush(instruction, sizeof(SH4Word) * nbinst);
  1318. }
  1319. static void revertJump(void* instructionStart, void *immptr)
  1320. {
  1321. SH4Word *insn = reinterpret_cast<SH4Word*>(instructionStart);
  1322. ASSERT((insn[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
  1323. changePCrelativeAddress(insn[0] & 0x00ff, insn, reinterpret_cast<uint32_t>(immptr));
  1324. }
  1325. void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type = JumpFar)
  1326. {
  1327. ASSERT(to.isSet());
  1328. ASSERT(from.isSet());
  1329. uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset);
  1330. uint16_t instruction = *instructionPtr;
  1331. int offsetBits;
  1332. if (type == JumpNear) {
  1333. ASSERT((instruction == BT_OPCODE) || (instruction == BF_OPCODE) || (instruction == BRA_OPCODE));
  1334. int offset = (codeSize() - from.m_offset) - 4;
  1335. *instructionPtr++ = instruction | (offset >> 1);
  1336. printInstr(*instructionPtr, from.m_offset + 2);
  1337. return;
  1338. }
  1339. if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
  1340. /* BT label => BF 2
  1341. nop LDR reg
  1342. nop braf @reg
  1343. nop nop
  1344. */
  1345. offsetBits = (to.m_offset - from.m_offset) - 8;
  1346. instruction ^= 0x0202;
  1347. *instructionPtr++ = instruction;
  1348. if ((*instructionPtr & 0xf000) == 0xe000) {
  1349. uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
  1350. *addr = offsetBits;
  1351. } else
  1352. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
  1353. instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
  1354. *instructionPtr = instruction;
  1355. printBlockInstr(instructionPtr - 2, from.m_offset, 3);
  1356. return;
  1357. }
  1358. /* MOV # imm, reg => LDR reg
  1359. braf @reg braf @reg
  1360. nop nop
  1361. */
  1362. ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
  1363. offsetBits = (to.m_offset - from.m_offset) - 4;
  1364. if (offsetBits >= -4096 && offsetBits <= 4094) {
  1365. *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
  1366. *(++instructionPtr) = NOP_OPCODE;
  1367. printBlockInstr(instructionPtr - 1, from.m_offset, 2);
  1368. return;
  1369. }
  1370. instruction = *instructionPtr;
  1371. if ((instruction & 0xf000) == 0xe000) {
  1372. uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
  1373. *addr = offsetBits - 2;
  1374. printInstr(*instructionPtr, from.m_offset + 2);
  1375. return;
  1376. }
  1377. changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
  1378. printInstr(*instructionPtr, from.m_offset + 2);
  1379. }
  1380. static void* getRelocatedAddress(void* code, AssemblerLabel label)
  1381. {
  1382. return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
  1383. }
  1384. static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
  1385. {
  1386. return b.m_offset - a.m_offset;
  1387. }
  1388. static void patchPointer(void* code, AssemblerLabel where, void* value)
  1389. {
  1390. patchPointer(reinterpret_cast<uint32_t*>(code) + where.m_offset, value);
  1391. }
  1392. static void patchPointer(void* code, void* value)
  1393. {
  1394. patchInt32(code, reinterpret_cast<uint32_t>(value));
  1395. }
  1396. static void patchInt32(void* code, uint32_t value)
  1397. {
  1398. changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code), value);
  1399. }
  1400. static uint32_t readInt32(void* code)
  1401. {
  1402. return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code));
  1403. }
  1404. static void* readCallTarget(void* from)
  1405. {
  1406. uint16_t* instructionPtr = static_cast<uint16_t*>(from);
  1407. instructionPtr -= 3;
  1408. return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr & 0xff), instructionPtr));
  1409. }
  1410. PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort)
  1411. {
  1412. return m_buffer.executableCopy(vm, ownerUID, effort);
  1413. }
  1414. static void cacheFlush(void* code, size_t size)
  1415. {
  1416. #if OS(LINUX)
  1417. // Flush each page separately, otherwise the whole flush will fail if an uncommited page is in the area.
  1418. unsigned currentPage = reinterpret_cast<unsigned>(code) & ~(pageSize() - 1);
  1419. unsigned lastPage = (reinterpret_cast<unsigned>(code) + size - 1) & ~(pageSize() - 1);
  1420. do {
  1421. #if defined CACHEFLUSH_D_L2
  1422. syscall(__NR_cacheflush, currentPage, pageSize(), CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2);
  1423. #else
  1424. syscall(__NR_cacheflush, currentPage, pageSize(), CACHEFLUSH_D_WB | CACHEFLUSH_I);
  1425. #endif
  1426. currentPage += pageSize();
  1427. } while (lastPage >= currentPage);
  1428. #else
  1429. #error "The cacheFlush support is missing on this platform."
  1430. #endif
  1431. }
  1432. void prefix(uint16_t pre)
  1433. {
  1434. m_buffer.putByte(pre);
  1435. }
  1436. void oneShortOp(uint16_t opcode, bool checksize = true, bool isDouble = true)
  1437. {
  1438. printInstr(opcode, m_buffer.codeSize(), isDouble);
  1439. if (checksize)
  1440. m_buffer.ensureSpace(maxInstructionSize);
  1441. m_buffer.putShortUnchecked(opcode);
  1442. }
  1443. void ensureSpace(int space)
  1444. {
  1445. m_buffer.ensureSpace(space);
  1446. }
  1447. void ensureSpace(int insnSpace, int constSpace)
  1448. {
  1449. m_buffer.ensureSpace(insnSpace, constSpace);
  1450. }
  1451. // Administrative methods
  1452. void* data() const { return m_buffer.data(); }
  1453. size_t codeSize() const { return m_buffer.codeSize(); }
  1454. #ifdef SH4_ASSEMBLER_TRACING
  1455. static void printInstr(uint16_t opc, unsigned size, bool isdoubleInst = true)
  1456. {
  1457. if (!getenv("JavaScriptCoreDumpJIT"))
  1458. return;
  1459. const char *format = 0;
  1460. printfStdoutInstr("offset: 0x%8.8x\t", size);
  1461. switch (opc) {
  1462. case BRK_OPCODE:
  1463. format = " BRK\n";
  1464. break;
  1465. case NOP_OPCODE:
  1466. format = " NOP\n";
  1467. break;
  1468. case RTS_OPCODE:
  1469. format =" *RTS\n";
  1470. break;
  1471. case SETS_OPCODE:
  1472. format = " SETS\n";
  1473. break;
  1474. case SETT_OPCODE:
  1475. format = " SETT\n";
  1476. break;
  1477. case CLRT_OPCODE:
  1478. format = " CLRT\n";
  1479. break;
  1480. case FSCHG_OPCODE:
  1481. format = " FSCHG\n";
  1482. break;
  1483. }
  1484. if (format) {
  1485. printfStdoutInstr(format);
  1486. return;
  1487. }
  1488. switch (opc & 0xf0ff) {
  1489. case BRAF_OPCODE:
  1490. format = " *BRAF R%d\n";
  1491. break;
  1492. case DT_OPCODE:
  1493. format = " DT R%d\n";
  1494. break;
  1495. case CMPPL_OPCODE:
  1496. format = " CMP/PL R%d\n";
  1497. break;
  1498. case CMPPZ_OPCODE:
  1499. format = " CMP/PZ R%d\n";
  1500. break;
  1501. case JMP_OPCODE:
  1502. format = " *JMP @R%d\n";
  1503. break;
  1504. case JSR_OPCODE:
  1505. format = " *JSR @R%d\n";
  1506. break;
  1507. case LDSPR_OPCODE:
  1508. format = " LDS R%d, PR\n";
  1509. break;
  1510. case LDSLPR_OPCODE:
  1511. format = " LDS.L @R%d+, PR\n";
  1512. break;
  1513. case MOVT_OPCODE:
  1514. format = " MOVT R%d\n";
  1515. break;
  1516. case SHAL_OPCODE:
  1517. format = " SHAL R%d\n";
  1518. break;
  1519. case SHAR_OPCODE:
  1520. format = " SHAR R%d\n";
  1521. break;
  1522. case SHLL_OPCODE:
  1523. format = " SHLL R%d\n";
  1524. break;
  1525. case SHLL2_OPCODE:
  1526. format = " SHLL2 R%d\n";
  1527. break;
  1528. case SHLL8_OPCODE:
  1529. format = " SHLL8 R%d\n";
  1530. break;
  1531. case SHLL16_OPCODE:
  1532. format = " SHLL16 R%d\n";
  1533. break;
  1534. case SHLR_OPCODE:
  1535. format = " SHLR R%d\n";
  1536. break;
  1537. case SHLR2_OPCODE:
  1538. format = " SHLR2 R%d\n";
  1539. break;
  1540. case SHLR8_OPCODE:
  1541. format = " SHLR8 R%d\n";
  1542. break;
  1543. case SHLR16_OPCODE:
  1544. format = " SHLR16 R%d\n";
  1545. break;
  1546. case STSPR_OPCODE:
  1547. format = " STS PR, R%d\n";
  1548. break;
  1549. case STSLPR_OPCODE:
  1550. format = " STS.L PR, @-R%d\n";
  1551. break;
  1552. case LDS_RM_FPUL_OPCODE:
  1553. format = " LDS R%d, FPUL\n";
  1554. break;
  1555. case STS_FPUL_RN_OPCODE:
  1556. format = " STS FPUL, R%d \n";
  1557. break;
  1558. case FLDS_FRM_FPUL_OPCODE:
  1559. format = " FLDS FR%d, FPUL\n";
  1560. break;
  1561. case FSTS_FPUL_FRN_OPCODE:
  1562. format = " FSTS FPUL, R%d \n";
  1563. break;
  1564. case LDSFPSCR_OPCODE:
  1565. format = " LDS R%d, FPSCR \n";
  1566. break;
  1567. case STSFPSCR_OPCODE:
  1568. format = " STS FPSCR, R%d \n";
  1569. break;
  1570. case STSMACL_OPCODE:
  1571. format = " STS MACL, R%d \n";
  1572. break;
  1573. case STSMACH_OPCODE:
  1574. format = " STS MACH, R%d \n";
  1575. break;
  1576. case BSRF_OPCODE:
  1577. format = " *BSRF R%d";
  1578. break;
  1579. case FTRC_OPCODE:
  1580. format = " FTRC FR%d, FPUL\n";
  1581. break;
  1582. }
  1583. if (format) {
  1584. printfStdoutInstr(format, getRn(opc));
  1585. return;
  1586. }
  1587. switch (opc & 0xf0ff) {
  1588. case FNEG_OPCODE:
  1589. format = " FNEG DR%d\n";
  1590. break;
  1591. case FLOAT_OPCODE:
  1592. format = " FLOAT DR%d\n";
  1593. break;
  1594. case FTRC_OPCODE:
  1595. format = " FTRC FR%d, FPUL\n";
  1596. break;
  1597. case FABS_OPCODE:
  1598. format = " FABS FR%d\n";
  1599. break;
  1600. case FSQRT_OPCODE:
  1601. format = " FSQRT FR%d\n";
  1602. break;
  1603. case FCNVDS_DRM_FPUL_OPCODE:
  1604. format = " FCNVDS FR%d, FPUL\n";
  1605. break;
  1606. case FCNVSD_FPUL_DRN_OPCODE:
  1607. format = " FCNVSD FPUL, FR%d\n";
  1608. break;
  1609. }
  1610. if (format) {
  1611. if (isdoubleInst)
  1612. printfStdoutInstr(format, getDRn(opc) << 1);
  1613. else
  1614. printfStdoutInstr(format, getRn(opc));
  1615. return;
  1616. }
  1617. switch (opc & 0xf00f) {
  1618. case ADD_OPCODE:
  1619. format = " ADD R%d, R%d\n";
  1620. break;
  1621. case ADDC_OPCODE:
  1622. format = " ADDC R%d, R%d\n";
  1623. break;
  1624. case ADDV_OPCODE:
  1625. format = " ADDV R%d, R%d\n";
  1626. break;
  1627. case AND_OPCODE:
  1628. format = " AND R%d, R%d\n";
  1629. break;
  1630. case DIV1_OPCODE:
  1631. format = " DIV1 R%d, R%d\n";
  1632. break;
  1633. case CMPEQ_OPCODE:
  1634. format = " CMP/EQ R%d, R%d\n";
  1635. break;
  1636. case CMPGE_OPCODE:
  1637. format = " CMP/GE R%d, R%d\n";
  1638. break;
  1639. case CMPGT_OPCODE:
  1640. format = " CMP/GT R%d, R%d\n";
  1641. break;
  1642. case CMPHI_OPCODE:
  1643. format = " CMP/HI R%d, R%d\n";
  1644. break;
  1645. case CMPHS_OPCODE:
  1646. format = " CMP/HS R%d, R%d\n";
  1647. break;
  1648. case MOV_OPCODE:
  1649. format = " MOV R%d, R%d\n";
  1650. break;
  1651. case MOVB_WRITE_RN_OPCODE:
  1652. format = " MOV.B R%d, @R%d\n";
  1653. break;
  1654. case MOVB_WRITE_RNDEC_OPCODE:
  1655. format = " MOV.B R%d, @-R%d\n";
  1656. break;
  1657. case MOVB_WRITE_R0RN_OPCODE:
  1658. format = " MOV.B R%d, @(R0, R%d)\n";
  1659. break;
  1660. case MOVB_READ_RM_OPCODE:
  1661. format = " MOV.B @R%d, R%d\n";
  1662. break;
  1663. case MOVB_READ_RMINC_OPCODE:
  1664. format = " MOV.B @R%d+, R%d\n";
  1665. break;
  1666. case MOVB_READ_R0RM_OPCODE:
  1667. format = " MOV.B @(R0, R%d), R%d\n";
  1668. break;
  1669. case MOVL_WRITE_RN_OPCODE:
  1670. format = " MOV.L R%d, @R%d\n";
  1671. break;
  1672. case MOVL_WRITE_RNDEC_OPCODE:
  1673. format = " MOV.L R%d, @-R%d\n";
  1674. break;
  1675. case MOVL_WRITE_R0RN_OPCODE:
  1676. format = " MOV.L R%d, @(R0, R%d)\n";
  1677. break;
  1678. case MOVL_READ_RM_OPCODE:
  1679. format = " MOV.L @R%d, R%d\n";
  1680. break;
  1681. case MOVL_READ_RMINC_OPCODE:
  1682. format = " MOV.L @R%d+, R%d\n";
  1683. break;
  1684. case MOVL_READ_R0RM_OPCODE:
  1685. format = " MOV.L @(R0, R%d), R%d\n";
  1686. break;
  1687. case MULL_OPCODE:
  1688. format = " MUL.L R%d, R%d\n";
  1689. break;
  1690. case DMULL_L_OPCODE:
  1691. format = " DMULU.L R%d, R%d\n";
  1692. break;
  1693. case DMULSL_OPCODE:
  1694. format = " DMULS.L R%d, R%d\n";
  1695. break;
  1696. case NEG_OPCODE:
  1697. format = " NEG R%d, R%d\n";
  1698. break;
  1699. case NEGC_OPCODE:
  1700. format = " NEGC R%d, R%d\n";
  1701. break;
  1702. case NOT_OPCODE:
  1703. format = " NOT R%d, R%d\n";
  1704. break;
  1705. case OR_OPCODE:
  1706. format = " OR R%d, R%d\n";
  1707. break;
  1708. case SHAD_OPCODE:
  1709. format = " SHAD R%d, R%d\n";
  1710. break;
  1711. case SHLD_OPCODE:
  1712. format = " SHLD R%d, R%d\n";
  1713. break;
  1714. case SUB_OPCODE:
  1715. format = " SUB R%d, R%d\n";
  1716. break;
  1717. case SUBC_OPCODE:
  1718. format = " SUBC R%d, R%d\n";
  1719. break;
  1720. case SUBV_OPCODE:
  1721. format = " SUBV R%d, R%d\n";
  1722. break;
  1723. case TST_OPCODE:
  1724. format = " TST R%d, R%d\n";
  1725. break;
  1726. case XOR_OPCODE:
  1727. format = " XOR R%d, R%d\n";break;
  1728. case MOVW_WRITE_RN_OPCODE:
  1729. format = " MOV.W R%d, @R%d\n";
  1730. break;
  1731. case MOVW_READ_RM_OPCODE:
  1732. format = " MOV.W @R%d, R%d\n";
  1733. break;
  1734. case MOVW_READ_RMINC_OPCODE:
  1735. format = " MOV.W @R%d+, R%d\n";
  1736. break;
  1737. case MOVW_READ_R0RM_OPCODE:
  1738. format = " MOV.W @(R0, R%d), R%d\n";
  1739. break;
  1740. case MOVW_WRITE_R0RN_OPCODE:
  1741. format = " MOV.W R%d, @(R0, R%d)\n";
  1742. break;
  1743. case EXTUB_OPCODE:
  1744. format = " EXTU.B R%d, R%d\n";
  1745. break;
  1746. case EXTUW_OPCODE:
  1747. format = " EXTU.W R%d, R%d\n";
  1748. break;
  1749. }
  1750. if (format) {
  1751. printfStdoutInstr(format, getRm(opc), getRn(opc));
  1752. return;
  1753. }
  1754. switch (opc & 0xf00f) {
  1755. case FSUB_OPCODE:
  1756. format = " FSUB FR%d, FR%d\n";
  1757. break;
  1758. case FADD_OPCODE:
  1759. format = " FADD FR%d, FR%d\n";
  1760. break;
  1761. case FDIV_OPCODE:
  1762. format = " FDIV FR%d, FR%d\n";
  1763. break;
  1764. case FMUL_OPCODE:
  1765. format = " DMULL FR%d, FR%d\n";
  1766. break;
  1767. case FMOV_OPCODE:
  1768. format = " FMOV FR%d, FR%d\n";
  1769. break;
  1770. case FCMPEQ_OPCODE:
  1771. format = " FCMP/EQ FR%d, FR%d\n";
  1772. break;
  1773. case FCMPGT_OPCODE:
  1774. format = " FCMP/GT FR%d, FR%d\n";
  1775. break;
  1776. }
  1777. if (format) {
  1778. if (isdoubleInst)
  1779. printfStdoutInstr(format, getDRm(opc) << 1, getDRn(opc) << 1);
  1780. else
  1781. printfStdoutInstr(format, getRm(opc), getRn(opc));
  1782. return;
  1783. }
  1784. switch (opc & 0xf00f) {
  1785. case FMOVS_WRITE_RN_DEC_OPCODE:
  1786. format = " %s FR%d, @-R%d\n";
  1787. break;
  1788. case FMOVS_WRITE_RN_OPCODE:
  1789. format = " %s FR%d, @R%d\n";
  1790. break;
  1791. case FMOVS_WRITE_R0RN_OPCODE:
  1792. format = " %s FR%d, @(R0, R%d)\n";
  1793. break;
  1794. }
  1795. if (format) {
  1796. if (isdoubleInst)
  1797. printfStdoutInstr(format, "FMOV", getDRm(opc) << 1, getDRn(opc));
  1798. else
  1799. printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
  1800. return;
  1801. }
  1802. switch (opc & 0xf00f) {
  1803. case FMOVS_READ_RM_OPCODE:
  1804. format = " %s @R%d, FR%d\n";
  1805. break;
  1806. case FMOVS_READ_RM_INC_OPCODE:
  1807. format = " %s @R%d+, FR%d\n";
  1808. break;
  1809. case FMOVS_READ_R0RM_OPCODE:
  1810. format = " %s @(R0, R%d), FR%d\n";
  1811. break;
  1812. }
  1813. if (format) {
  1814. if (isdoubleInst)
  1815. printfStdoutInstr(format, "FMOV", getDRm(opc), getDRn(opc) << 1);
  1816. else
  1817. printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
  1818. return;
  1819. }
  1820. switch (opc & 0xff00) {
  1821. case BF_OPCODE:
  1822. format = " BF %d\n";
  1823. break;
  1824. case BFS_OPCODE:
  1825. format = " *BF/S %d\n";
  1826. break;
  1827. case ANDIMM_OPCODE:
  1828. format = " AND #%d, R0\n";
  1829. break;
  1830. case BT_OPCODE:
  1831. format = " BT %d\n";
  1832. break;
  1833. case BTS_OPCODE:
  1834. format = " *BT/S %d\n";
  1835. break;
  1836. case CMPEQIMM_OPCODE:
  1837. format = " CMP/EQ #%d, R0\n";
  1838. break;
  1839. case MOVB_WRITE_OFFGBR_OPCODE:
  1840. format = " MOV.B R0, @(%d, GBR)\n";
  1841. break;
  1842. case MOVB_READ_OFFGBR_OPCODE:
  1843. format = " MOV.B @(%d, GBR), R0\n";
  1844. break;
  1845. case MOVL_WRITE_OFFGBR_OPCODE:
  1846. format = " MOV.L R0, @(%d, GBR)\n";
  1847. break;
  1848. case MOVL_READ_OFFGBR_OPCODE:
  1849. format = " MOV.L @(%d, GBR), R0\n";
  1850. break;
  1851. case MOVA_READ_OFFPC_OPCODE:
  1852. format = " MOVA @(%d, PC), R0\n";
  1853. break;
  1854. case ORIMM_OPCODE:
  1855. format = " OR #%d, R0\n";
  1856. break;
  1857. case ORBIMM_OPCODE:
  1858. format = " OR.B #%d, @(R0, GBR)\n";
  1859. break;
  1860. case TSTIMM_OPCODE:
  1861. format = " TST #%d, R0\n";
  1862. break;
  1863. case TSTB_OPCODE:
  1864. format = " TST.B %d, @(R0, GBR)\n";
  1865. break;
  1866. case XORIMM_OPCODE:
  1867. format = " XOR #%d, R0\n";
  1868. break;
  1869. case XORB_OPCODE:
  1870. format = " XOR.B %d, @(R0, GBR)\n";
  1871. break;
  1872. }
  1873. if (format) {
  1874. printfStdoutInstr(format, getImm8(opc));
  1875. return;
  1876. }
  1877. switch (opc & 0xff00) {
  1878. case MOVB_WRITE_OFFRN_OPCODE:
  1879. format = " MOV.B R0, @(%d, R%d)\n";
  1880. break;
  1881. case MOVB_READ_OFFRM_OPCODE:
  1882. format = " MOV.B @(%d, R%d), R0\n";
  1883. break;
  1884. }
  1885. if (format) {
  1886. printfStdoutInstr(format, getDisp(opc), getRm(opc));
  1887. return;
  1888. }
  1889. switch (opc & 0xf000) {
  1890. case BRA_OPCODE:
  1891. format = " *BRA %d\n";
  1892. break;
  1893. case BSR_OPCODE:
  1894. format = " *BSR %d\n";
  1895. break;
  1896. }
  1897. if (format) {
  1898. printfStdoutInstr(format, getImm12(opc));
  1899. return;
  1900. }
  1901. switch (opc & 0xf000) {
  1902. case MOVL_READ_OFFPC_OPCODE:
  1903. format = " MOV.L @(%d, PC), R%d\n";
  1904. break;
  1905. case ADDIMM_OPCODE:
  1906. format = " ADD #%d, R%d\n";
  1907. break;
  1908. case MOVIMM_OPCODE:
  1909. format = " MOV #%d, R%d\n";
  1910. break;
  1911. case MOVW_READ_OFFPC_OPCODE:
  1912. format = " MOV.W @(%d, PC), R%d\n";
  1913. break;
  1914. }
  1915. if (format) {
  1916. printfStdoutInstr(format, getImm8(opc), getRn(opc));
  1917. return;
  1918. }
  1919. switch (opc & 0xf000) {
  1920. case MOVL_WRITE_OFFRN_OPCODE:
  1921. format = " MOV.L R%d, @(%d, R%d)\n";
  1922. printfStdoutInstr(format, getRm(opc), getDisp(opc), getRn(opc));
  1923. break;
  1924. case MOVL_READ_OFFRM_OPCODE:
  1925. format = " MOV.L @(%d, R%d), R%d\n";
  1926. printfStdoutInstr(format, getDisp(opc), getRm(opc), getRn(opc));
  1927. break;
  1928. }
  1929. }
  1930. static void printfStdoutInstr(const char* format, ...)
  1931. {
  1932. if (getenv("JavaScriptCoreDumpJIT")) {
  1933. va_list args;
  1934. va_start(args, format);
  1935. vprintfStdoutInstr(format, args);
  1936. va_end(args);
  1937. }
  1938. }
  1939. static void vprintfStdoutInstr(const char* format, va_list args)
  1940. {
  1941. if (getenv("JavaScriptCoreDumpJIT"))
  1942. WTF::dataLogFV(format, args);
  1943. }
  1944. static void printBlockInstr(uint16_t* first, unsigned offset, int nbInstr)
  1945. {
  1946. printfStdoutInstr(">> repatch instructions after link\n");
  1947. for (int i = 0; i <= nbInstr; i++)
  1948. printInstr(*(first + i), offset + i);
  1949. printfStdoutInstr(">> end repatch\n");
  1950. }
  1951. #else
  1952. static void printInstr(uint16_t opc, unsigned size, bool isdoubleInst = true) { };
  1953. static void printBlockInstr(uint16_t* first, unsigned offset, int nbInstr) { };
  1954. #endif
  1955. static void replaceWithLoad(void* instructionStart)
  1956. {
  1957. SH4Word* insPtr = reinterpret_cast<SH4Word*>(instructionStart);
  1958. insPtr += 2; // skip MOV and ADD opcodes
  1959. if (((*insPtr) & 0xf00f) != MOVL_READ_RM_OPCODE) {
  1960. *insPtr = MOVL_READ_RM_OPCODE | (*insPtr & 0x0ff0);
  1961. cacheFlush(insPtr, sizeof(SH4Word));
  1962. }
  1963. }
  1964. static void replaceWithAddressComputation(void* instructionStart)
  1965. {
  1966. SH4Word* insPtr = reinterpret_cast<SH4Word*>(instructionStart);
  1967. insPtr += 2; // skip MOV and ADD opcodes
  1968. if (((*insPtr) & 0xf00f) != MOV_OPCODE) {
  1969. *insPtr = MOV_OPCODE | (*insPtr & 0x0ff0);
  1970. cacheFlush(insPtr, sizeof(SH4Word));
  1971. }
  1972. }
  1973. private:
  1974. SH4Buffer m_buffer;
  1975. int m_claimscratchReg;
  1976. };
  1977. } // namespace JSC
  1978. #endif // ENABLE(ASSEMBLER) && CPU(SH4)
  1979. #endif // SH4Assembler_h