MIPSAssembler.h 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. /*
  2. * Copyright (C) 2009 Apple Inc. All rights reserved.
  3. * Copyright (C) 2009 University of Szeged
  4. * All rights reserved.
  5. * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY MIPS TECHNOLOGIES, INC. ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MIPS TECHNOLOGIES, INC. OR
  20. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  21. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  22. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  23. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  24. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifndef MIPSAssembler_h
  29. #define MIPSAssembler_h
  30. #if ENABLE(ASSEMBLER) && CPU(MIPS)
  31. #include "AssemblerBuffer.h"
  32. #include "JITCompilationEffort.h"
  33. #include <wtf/Assertions.h>
  34. #include <wtf/SegmentedVector.h>
  35. namespace JSC {
  36. typedef uint32_t MIPSWord;
  37. namespace MIPSRegisters {
  38. typedef enum {
  39. r0 = 0,
  40. r1,
  41. r2,
  42. r3,
  43. r4,
  44. r5,
  45. r6,
  46. r7,
  47. r8,
  48. r9,
  49. r10,
  50. r11,
  51. r12,
  52. r13,
  53. r14,
  54. r15,
  55. r16,
  56. r17,
  57. r18,
  58. r19,
  59. r20,
  60. r21,
  61. r22,
  62. r23,
  63. r24,
  64. r25,
  65. r26,
  66. r27,
  67. r28,
  68. r29,
  69. r30,
  70. r31,
  71. zero = r0,
  72. at = r1,
  73. v0 = r2,
  74. v1 = r3,
  75. a0 = r4,
  76. a1 = r5,
  77. a2 = r6,
  78. a3 = r7,
  79. t0 = r8,
  80. t1 = r9,
  81. t2 = r10,
  82. t3 = r11,
  83. t4 = r12,
  84. t5 = r13,
  85. t6 = r14,
  86. t7 = r15,
  87. s0 = r16,
  88. s1 = r17,
  89. s2 = r18,
  90. s3 = r19,
  91. s4 = r20,
  92. s5 = r21,
  93. s6 = r22,
  94. s7 = r23,
  95. t8 = r24,
  96. t9 = r25,
  97. k0 = r26,
  98. k1 = r27,
  99. gp = r28,
  100. sp = r29,
  101. fp = r30,
  102. ra = r31
  103. } RegisterID;
  104. typedef enum {
  105. f0,
  106. f1,
  107. f2,
  108. f3,
  109. f4,
  110. f5,
  111. f6,
  112. f7,
  113. f8,
  114. f9,
  115. f10,
  116. f11,
  117. f12,
  118. f13,
  119. f14,
  120. f15,
  121. f16,
  122. f17,
  123. f18,
  124. f19,
  125. f20,
  126. f21,
  127. f22,
  128. f23,
  129. f24,
  130. f25,
  131. f26,
  132. f27,
  133. f28,
  134. f29,
  135. f30,
  136. f31
  137. } FPRegisterID;
  138. } // namespace MIPSRegisters
  139. class MIPSAssembler {
  140. public:
  141. typedef MIPSRegisters::RegisterID RegisterID;
  142. typedef MIPSRegisters::FPRegisterID FPRegisterID;
  143. typedef SegmentedVector<AssemblerLabel, 64> Jumps;
  144. MIPSAssembler()
  145. : m_indexOfLastWatchpoint(INT_MIN)
  146. , m_indexOfTailOfLastWatchpoint(INT_MIN)
  147. {
  148. }
  149. // MIPS instruction opcode field position
  150. enum {
  151. OP_SH_RD = 11,
  152. OP_SH_RT = 16,
  153. OP_SH_RS = 21,
  154. OP_SH_SHAMT = 6,
  155. OP_SH_CODE = 16,
  156. OP_SH_FD = 6,
  157. OP_SH_FS = 11,
  158. OP_SH_FT = 16
  159. };
  160. void emitInst(MIPSWord op)
  161. {
  162. void* oldBase = m_buffer.data();
  163. m_buffer.putInt(op);
  164. void* newBase = m_buffer.data();
  165. if (oldBase != newBase)
  166. relocateJumps(oldBase, newBase);
  167. }
  168. void nop()
  169. {
  170. emitInst(0x00000000);
  171. }
  172. /* Need to insert one load data delay nop for mips1. */
  173. void loadDelayNop()
  174. {
  175. #if WTF_MIPS_ISA(1)
  176. nop();
  177. #endif
  178. }
  179. /* Need to insert one coprocessor access delay nop for mips1. */
  180. void copDelayNop()
  181. {
  182. #if WTF_MIPS_ISA(1)
  183. nop();
  184. #endif
  185. }
  186. void move(RegisterID rd, RegisterID rs)
  187. {
  188. /* addu */
  189. emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS));
  190. }
  191. /* Set an immediate value to a register. This may generate 1 or 2
  192. instructions. */
  193. void li(RegisterID dest, int imm)
  194. {
  195. if (imm >= -32768 && imm <= 32767)
  196. addiu(dest, MIPSRegisters::zero, imm);
  197. else if (imm >= 0 && imm < 65536)
  198. ori(dest, MIPSRegisters::zero, imm);
  199. else {
  200. lui(dest, imm >> 16);
  201. if (imm & 0xffff)
  202. ori(dest, dest, imm);
  203. }
  204. }
  205. void lui(RegisterID rt, int imm)
  206. {
  207. emitInst(0x3c000000 | (rt << OP_SH_RT) | (imm & 0xffff));
  208. }
  209. void addiu(RegisterID rt, RegisterID rs, int imm)
  210. {
  211. emitInst(0x24000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff));
  212. }
  213. void addu(RegisterID rd, RegisterID rs, RegisterID rt)
  214. {
  215. emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  216. }
  217. void subu(RegisterID rd, RegisterID rs, RegisterID rt)
  218. {
  219. emitInst(0x00000023 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  220. }
  221. void mult(RegisterID rs, RegisterID rt)
  222. {
  223. emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  224. }
  225. void div(RegisterID rs, RegisterID rt)
  226. {
  227. emitInst(0x0000001a | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  228. }
  229. void mfhi(RegisterID rd)
  230. {
  231. emitInst(0x00000010 | (rd << OP_SH_RD));
  232. }
  233. void mflo(RegisterID rd)
  234. {
  235. emitInst(0x00000012 | (rd << OP_SH_RD));
  236. }
  237. void mul(RegisterID rd, RegisterID rs, RegisterID rt)
  238. {
  239. #if WTF_MIPS_ISA_AT_LEAST(32)
  240. emitInst(0x70000002 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  241. #else
  242. mult(rs, rt);
  243. mflo(rd);
  244. #endif
  245. }
  246. void andInsn(RegisterID rd, RegisterID rs, RegisterID rt)
  247. {
  248. emitInst(0x00000024 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  249. }
  250. void andi(RegisterID rt, RegisterID rs, int imm)
  251. {
  252. emitInst(0x30000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff));
  253. }
  254. void nor(RegisterID rd, RegisterID rs, RegisterID rt)
  255. {
  256. emitInst(0x00000027 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  257. }
  258. void orInsn(RegisterID rd, RegisterID rs, RegisterID rt)
  259. {
  260. emitInst(0x00000025 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  261. }
  262. void ori(RegisterID rt, RegisterID rs, int imm)
  263. {
  264. emitInst(0x34000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff));
  265. }
  266. void xorInsn(RegisterID rd, RegisterID rs, RegisterID rt)
  267. {
  268. emitInst(0x00000026 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  269. }
  270. void xori(RegisterID rt, RegisterID rs, int imm)
  271. {
  272. emitInst(0x38000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff));
  273. }
  274. void slt(RegisterID rd, RegisterID rs, RegisterID rt)
  275. {
  276. emitInst(0x0000002a | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  277. }
  278. void sltu(RegisterID rd, RegisterID rs, RegisterID rt)
  279. {
  280. emitInst(0x0000002b | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT));
  281. }
  282. void sltiu(RegisterID rt, RegisterID rs, int imm)
  283. {
  284. emitInst(0x2c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff));
  285. }
  286. void sll(RegisterID rd, RegisterID rt, int shamt)
  287. {
  288. emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT));
  289. }
  290. void sllv(RegisterID rd, RegisterID rt, RegisterID rs)
  291. {
  292. emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS));
  293. }
  294. void sra(RegisterID rd, RegisterID rt, int shamt)
  295. {
  296. emitInst(0x00000003 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT));
  297. }
  298. void srav(RegisterID rd, RegisterID rt, RegisterID rs)
  299. {
  300. emitInst(0x00000007 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS));
  301. }
  302. void srl(RegisterID rd, RegisterID rt, int shamt)
  303. {
  304. emitInst(0x00000002 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT));
  305. }
  306. void srlv(RegisterID rd, RegisterID rt, RegisterID rs)
  307. {
  308. emitInst(0x00000006 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS));
  309. }
  310. void lb(RegisterID rt, RegisterID rs, int offset)
  311. {
  312. emitInst(0x80000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  313. loadDelayNop();
  314. }
  315. void lbu(RegisterID rt, RegisterID rs, int offset)
  316. {
  317. emitInst(0x90000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  318. loadDelayNop();
  319. }
  320. void lw(RegisterID rt, RegisterID rs, int offset)
  321. {
  322. emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  323. loadDelayNop();
  324. }
  325. void lwl(RegisterID rt, RegisterID rs, int offset)
  326. {
  327. emitInst(0x88000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  328. loadDelayNop();
  329. }
  330. void lwr(RegisterID rt, RegisterID rs, int offset)
  331. {
  332. emitInst(0x98000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  333. loadDelayNop();
  334. }
  335. void lh(RegisterID rt, RegisterID rs, int offset)
  336. {
  337. emitInst(0x84000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  338. loadDelayNop();
  339. }
  340. void lhu(RegisterID rt, RegisterID rs, int offset)
  341. {
  342. emitInst(0x94000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  343. loadDelayNop();
  344. }
  345. void sb(RegisterID rt, RegisterID rs, int offset)
  346. {
  347. emitInst(0xa0000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  348. }
  349. void sh(RegisterID rt, RegisterID rs, int offset)
  350. {
  351. emitInst(0xa4000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  352. }
  353. void sw(RegisterID rt, RegisterID rs, int offset)
  354. {
  355. emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff));
  356. }
  357. void jr(RegisterID rs)
  358. {
  359. emitInst(0x00000008 | (rs << OP_SH_RS));
  360. }
  361. void jalr(RegisterID rs)
  362. {
  363. emitInst(0x0000f809 | (rs << OP_SH_RS));
  364. }
  365. void jal()
  366. {
  367. emitInst(0x0c000000);
  368. }
  369. void bkpt()
  370. {
  371. int value = 512; /* BRK_BUG */
  372. emitInst(0x0000000d | ((value & 0x3ff) << OP_SH_CODE));
  373. }
  374. void bgez(RegisterID rs, int imm)
  375. {
  376. emitInst(0x04010000 | (rs << OP_SH_RS) | (imm & 0xffff));
  377. }
  378. void bltz(RegisterID rs, int imm)
  379. {
  380. emitInst(0x04000000 | (rs << OP_SH_RS) | (imm & 0xffff));
  381. }
  382. void beq(RegisterID rs, RegisterID rt, int imm)
  383. {
  384. emitInst(0x10000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
  385. }
  386. void bne(RegisterID rs, RegisterID rt, int imm)
  387. {
  388. emitInst(0x14000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
  389. }
  390. void bc1t()
  391. {
  392. emitInst(0x45010000);
  393. }
  394. void bc1f()
  395. {
  396. emitInst(0x45000000);
  397. }
  398. void appendJump()
  399. {
  400. m_jumps.append(m_buffer.label());
  401. }
  402. void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
  403. {
  404. emitInst(0x46200000 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  405. }
  406. void subd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
  407. {
  408. emitInst(0x46200001 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  409. }
  410. void muld(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
  411. {
  412. emitInst(0x46200002 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  413. }
  414. void divd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
  415. {
  416. emitInst(0x46200003 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  417. }
  418. void lwc1(FPRegisterID ft, RegisterID rs, int offset)
  419. {
  420. emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff));
  421. copDelayNop();
  422. }
  423. void ldc1(FPRegisterID ft, RegisterID rs, int offset)
  424. {
  425. emitInst(0xd4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff));
  426. }
  427. void swc1(FPRegisterID ft, RegisterID rs, int offset)
  428. {
  429. emitInst(0xe4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff));
  430. }
  431. void sdc1(FPRegisterID ft, RegisterID rs, int offset)
  432. {
  433. emitInst(0xf4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff));
  434. }
  435. void mtc1(RegisterID rt, FPRegisterID fs)
  436. {
  437. emitInst(0x44800000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
  438. copDelayNop();
  439. }
  440. void mthc1(RegisterID rt, FPRegisterID fs)
  441. {
  442. emitInst(0x44e00000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
  443. copDelayNop();
  444. }
  445. void mfc1(RegisterID rt, FPRegisterID fs)
  446. {
  447. emitInst(0x44000000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
  448. copDelayNop();
  449. }
  450. void sqrtd(FPRegisterID fd, FPRegisterID fs)
  451. {
  452. emitInst(0x46200004 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  453. }
  454. void movd(FPRegisterID fd, FPRegisterID fs)
  455. {
  456. emitInst(0x46200006 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  457. }
  458. void negd(FPRegisterID fd, FPRegisterID fs)
  459. {
  460. emitInst(0x46200007 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  461. }
  462. void truncwd(FPRegisterID fd, FPRegisterID fs)
  463. {
  464. emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  465. }
  466. void cvtdw(FPRegisterID fd, FPRegisterID fs)
  467. {
  468. emitInst(0x46800021 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  469. }
  470. void cvtds(FPRegisterID fd, FPRegisterID fs)
  471. {
  472. emitInst(0x46000021 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  473. }
  474. void cvtwd(FPRegisterID fd, FPRegisterID fs)
  475. {
  476. emitInst(0x46200024 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  477. }
  478. void cvtsd(FPRegisterID fd, FPRegisterID fs)
  479. {
  480. emitInst(0x46200020 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
  481. }
  482. void ceqd(FPRegisterID fs, FPRegisterID ft)
  483. {
  484. emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  485. copDelayNop();
  486. }
  487. void cngtd(FPRegisterID fs, FPRegisterID ft)
  488. {
  489. emitInst(0x4620003f | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  490. copDelayNop();
  491. }
  492. void cnged(FPRegisterID fs, FPRegisterID ft)
  493. {
  494. emitInst(0x4620003d | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  495. copDelayNop();
  496. }
  497. void cltd(FPRegisterID fs, FPRegisterID ft)
  498. {
  499. emitInst(0x4620003c | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  500. copDelayNop();
  501. }
  502. void cled(FPRegisterID fs, FPRegisterID ft)
  503. {
  504. emitInst(0x4620003e | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  505. copDelayNop();
  506. }
  507. void cueqd(FPRegisterID fs, FPRegisterID ft)
  508. {
  509. emitInst(0x46200033 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  510. copDelayNop();
  511. }
  512. void coled(FPRegisterID fs, FPRegisterID ft)
  513. {
  514. emitInst(0x46200036 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  515. copDelayNop();
  516. }
  517. void coltd(FPRegisterID fs, FPRegisterID ft)
  518. {
  519. emitInst(0x46200034 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  520. copDelayNop();
  521. }
  522. void culed(FPRegisterID fs, FPRegisterID ft)
  523. {
  524. emitInst(0x46200037 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  525. copDelayNop();
  526. }
  527. void cultd(FPRegisterID fs, FPRegisterID ft)
  528. {
  529. emitInst(0x46200035 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
  530. copDelayNop();
  531. }
  532. // General helpers
  533. AssemblerLabel labelIgnoringWatchpoints()
  534. {
  535. return m_buffer.label();
  536. }
  537. AssemblerLabel labelForWatchpoint()
  538. {
  539. AssemblerLabel result = m_buffer.label();
  540. if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint)
  541. result = label();
  542. m_indexOfLastWatchpoint = result.m_offset;
  543. m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
  544. return result;
  545. }
  546. AssemblerLabel label()
  547. {
  548. AssemblerLabel result = m_buffer.label();
  549. while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) {
  550. nop();
  551. result = m_buffer.label();
  552. }
  553. return result;
  554. }
  555. AssemblerLabel align(int alignment)
  556. {
  557. while (!m_buffer.isAligned(alignment))
  558. bkpt();
  559. return label();
  560. }
  561. static void* getRelocatedAddress(void* code, AssemblerLabel label)
  562. {
  563. return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
  564. }
  565. static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
  566. {
  567. return b.m_offset - a.m_offset;
  568. }
  569. // Assembler admin methods:
  570. size_t codeSize() const
  571. {
  572. return m_buffer.codeSize();
  573. }
  574. PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort)
  575. {
  576. RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(vm, ownerUID, effort);
  577. if (!result)
  578. return 0;
  579. relocateJumps(m_buffer.data(), result->start());
  580. return result.release();
  581. }
  582. unsigned debugOffset() { return m_buffer.debugOffset(); }
  583. // Assembly helpers for moving data between fp and registers.
  584. void vmov(RegisterID rd1, RegisterID rd2, FPRegisterID rn)
  585. {
  586. #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
  587. mfc1(rd1, rn);
  588. mfhc1(rd2, rn);
  589. #else
  590. mfc1(rd1, rn);
  591. mfc1(rd2, FPRegisterID(rn + 1));
  592. #endif
  593. }
  594. void vmov(FPRegisterID rd, RegisterID rn1, RegisterID rn2)
  595. {
  596. #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
  597. mtc1(rn1, rd);
  598. mthc1(rn2, rd);
  599. #else
  600. mtc1(rn1, rd);
  601. mtc1(rn2, FPRegisterID(rd + 1));
  602. #endif
  603. }
  604. static unsigned getCallReturnOffset(AssemblerLabel call)
  605. {
  606. // The return address is after a call and a delay slot instruction
  607. return call.m_offset;
  608. }
  609. // Linking & patching:
  610. //
  611. // 'link' and 'patch' methods are for use on unprotected code - such as the code
  612. // within the AssemblerBuffer, and code being patched by the patch buffer. Once
  613. // code has been finalized it is (platform support permitting) within a non-
  614. // writable region of memory; to modify the code in an execute-only execuable
  615. // pool the 'repatch' and 'relink' methods should be used.
  616. static size_t linkDirectJump(void* code, void* to)
  617. {
  618. MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code));
  619. size_t ops = 0;
  620. int32_t slotAddr = reinterpret_cast<int>(insn) + 4;
  621. int32_t toAddr = reinterpret_cast<int>(to);
  622. if ((slotAddr & 0xf0000000) != (toAddr & 0xf0000000)) {
  623. // lui
  624. *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((toAddr >> 16) & 0xffff);
  625. ++insn;
  626. // ori
  627. *insn = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (toAddr & 0xffff);
  628. ++insn;
  629. // jr
  630. *insn = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
  631. ++insn;
  632. ops = 4 * sizeof(MIPSWord);
  633. } else {
  634. // j
  635. *insn = 0x08000000 | ((toAddr & 0x0fffffff) >> 2);
  636. ++insn;
  637. ops = 2 * sizeof(MIPSWord);
  638. }
  639. // nop
  640. *insn = 0x00000000;
  641. return ops;
  642. }
  643. void linkJump(AssemblerLabel from, AssemblerLabel to)
  644. {
  645. ASSERT(to.isSet());
  646. ASSERT(from.isSet());
  647. MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + from.m_offset);
  648. MIPSWord* toPos = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + to.m_offset);
  649. ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5)));
  650. insn = insn - 6;
  651. linkWithOffset(insn, toPos);
  652. }
  653. static void linkJump(void* code, AssemblerLabel from, void* to)
  654. {
  655. ASSERT(from.isSet());
  656. MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
  657. ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5)));
  658. insn = insn - 6;
  659. linkWithOffset(insn, to);
  660. }
  661. static void linkCall(void* code, AssemblerLabel from, void* to)
  662. {
  663. MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
  664. linkCallInternal(insn, to);
  665. }
  666. static void linkPointer(void* code, AssemblerLabel from, void* to)
  667. {
  668. MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
  669. ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
  670. *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
  671. insn++;
  672. ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
  673. *insn = (*insn & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
  674. }
  675. static void relinkJump(void* from, void* to)
  676. {
  677. MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
  678. ASSERT(!(*(insn - 1)) && !(*(insn - 5)));
  679. insn = insn - 6;
  680. int flushSize = linkWithOffset(insn, to);
  681. cacheFlush(insn, flushSize);
  682. }
  683. static void relinkCall(void* from, void* to)
  684. {
  685. void* start;
  686. int size = linkCallInternal(from, to);
  687. if (size == sizeof(MIPSWord))
  688. start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 2 * sizeof(MIPSWord));
  689. else
  690. start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 4 * sizeof(MIPSWord));
  691. cacheFlush(start, size);
  692. }
  693. static void repatchInt32(void* from, int32_t to)
  694. {
  695. MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
  696. ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
  697. *insn = (*insn & 0xffff0000) | ((to >> 16) & 0xffff);
  698. insn++;
  699. ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
  700. *insn = (*insn & 0xffff0000) | (to & 0xffff);
  701. insn--;
  702. cacheFlush(insn, 2 * sizeof(MIPSWord));
  703. }
  704. static int32_t readInt32(void* from)
  705. {
  706. MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
  707. ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
  708. int32_t result = (*insn & 0x0000ffff) << 16;
  709. insn++;
  710. ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
  711. result |= *insn & 0x0000ffff;
  712. return result;
  713. }
  714. static void repatchCompact(void* where, int32_t value)
  715. {
  716. repatchInt32(where, value);
  717. }
  718. static void repatchPointer(void* from, void* to)
  719. {
  720. repatchInt32(from, reinterpret_cast<int32_t>(to));
  721. }
  722. static void* readPointer(void* from)
  723. {
  724. return reinterpret_cast<void*>(readInt32(from));
  725. }
  726. static void* readCallTarget(void* from)
  727. {
  728. MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
  729. insn -= 4;
  730. ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
  731. int32_t result = (*insn & 0x0000ffff) << 16;
  732. insn++;
  733. ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
  734. result |= *insn & 0x0000ffff;
  735. return reinterpret_cast<void*>(result);
  736. }
  737. static void cacheFlush(void* code, size_t size)
  738. {
  739. #if GCC_VERSION_AT_LEAST(4, 3, 0)
  740. #if WTF_MIPS_ISA_REV(2) && !GCC_VERSION_AT_LEAST(4, 4, 3)
  741. int lineSize;
  742. asm("rdhwr %0, $1" : "=r" (lineSize));
  743. //
  744. // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in
  745. // mips_expand_synci_loop that may execute synci one more time.
  746. // "start" points to the fisrt byte of the cache line.
  747. // "end" points to the last byte of the line before the last cache line.
  748. // Because size is always a multiple of 4, this is safe to set
  749. // "end" to the last byte.
  750. //
  751. intptr_t start = reinterpret_cast<intptr_t>(code) & (-lineSize);
  752. intptr_t end = ((reinterpret_cast<intptr_t>(code) + size - 1) & (-lineSize)) - 1;
  753. __builtin___clear_cache(reinterpret_cast<char*>(start), reinterpret_cast<char*>(end));
  754. #else
  755. intptr_t end = reinterpret_cast<intptr_t>(code) + size;
  756. __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
  757. #endif
  758. #else
  759. _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
  760. #endif
  761. }
  762. static ptrdiff_t maxJumpReplacementSize()
  763. {
  764. return sizeof(MIPSWord) * 4;
  765. }
  766. static void revertJumpToMove(void* instructionStart, RegisterID rt, int imm)
  767. {
  768. MIPSWord* insn = static_cast<MIPSWord*>(instructionStart);
  769. size_t codeSize = 2 * sizeof(MIPSWord);
  770. // lui
  771. *insn = 0x3c000000 | (rt << OP_SH_RT) | ((imm >> 16) & 0xffff);
  772. ++insn;
  773. // ori
  774. *insn = 0x34000000 | (rt << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff);
  775. ++insn;
  776. // if jr $t9
  777. if (*insn == 0x03200008) {
  778. *insn = 0x00000000;
  779. codeSize += sizeof(MIPSWord);
  780. }
  781. cacheFlush(insn, codeSize);
  782. }
  783. static void replaceWithJump(void* instructionStart, void* to)
  784. {
  785. ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 3));
  786. ASSERT(!(bitwise_cast<uintptr_t>(to) & 3));
  787. size_t ops = linkDirectJump(instructionStart, to);
  788. cacheFlush(instructionStart, ops);
  789. }
  790. static void replaceWithLoad(void* instructionStart)
  791. {
  792. MIPSWord* insn = reinterpret_cast<MIPSWord*>(instructionStart);
  793. ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
  794. insn++;
  795. ASSERT((*insn & 0xfc0007ff) == 0x00000021); // addu
  796. insn++;
  797. *insn = 0x8c000000 | ((*insn) & 0x3ffffff); // lw
  798. cacheFlush(insn, 4);
  799. }
  800. static void replaceWithAddressComputation(void* instructionStart)
  801. {
  802. MIPSWord* insn = reinterpret_cast<MIPSWord*>(instructionStart);
  803. ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
  804. insn++;
  805. ASSERT((*insn & 0xfc0007ff) == 0x00000021); // addu
  806. insn++;
  807. *insn = 0x24000000 | ((*insn) & 0x3ffffff); // addiu
  808. cacheFlush(insn, 4);
  809. }
  810. private:
  811. /* Update each jump in the buffer of newBase. */
  812. void relocateJumps(void* oldBase, void* newBase)
  813. {
  814. // Check each jump
  815. for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
  816. int pos = iter->m_offset;
  817. MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(newBase) + pos);
  818. insn = insn + 2;
  819. // Need to make sure we have 5 valid instructions after pos
  820. if ((unsigned)pos >= m_buffer.codeSize() - 5 * sizeof(MIPSWord))
  821. continue;
  822. if ((*insn & 0xfc000000) == 0x08000000) { // j
  823. int offset = *insn & 0x03ffffff;
  824. int oldInsnAddress = (int)insn - (int)newBase + (int)oldBase;
  825. int topFourBits = (oldInsnAddress + 4) >> 28;
  826. int oldTargetAddress = (topFourBits << 28) | (offset << 2);
  827. int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase;
  828. int newInsnAddress = (int)insn;
  829. if (((newInsnAddress + 4) >> 28) == (newTargetAddress >> 28))
  830. *insn = 0x08000000 | ((newTargetAddress >> 2) & 0x3ffffff);
  831. else {
  832. /* lui */
  833. *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
  834. /* ori */
  835. *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
  836. /* jr */
  837. *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
  838. }
  839. } else if ((*insn & 0xffe00000) == 0x3c000000) { // lui
  840. int high = (*insn & 0xffff) << 16;
  841. int low = *(insn + 1) & 0xffff;
  842. int oldTargetAddress = high | low;
  843. int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase;
  844. /* lui */
  845. *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
  846. /* ori */
  847. *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
  848. }
  849. }
  850. }
  851. static int linkWithOffset(MIPSWord* insn, void* to)
  852. {
  853. ASSERT((*insn & 0xfc000000) == 0x10000000 // beq
  854. || (*insn & 0xfc000000) == 0x14000000 // bne
  855. || (*insn & 0xffff0000) == 0x45010000 // bc1t
  856. || (*insn & 0xffff0000) == 0x45000000); // bc1f
  857. intptr_t diff = (reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(insn) - 4) >> 2;
  858. if (diff < -32768 || diff > 32767 || *(insn + 2) != 0x10000003) {
  859. /*
  860. Convert the sequence:
  861. beq $2, $3, target
  862. nop
  863. b 1f
  864. nop
  865. nop
  866. nop
  867. 1:
  868. to the new sequence if possible:
  869. bne $2, $3, 1f
  870. nop
  871. j target
  872. nop
  873. nop
  874. nop
  875. 1:
  876. OR to the new sequence:
  877. bne $2, $3, 1f
  878. nop
  879. lui $25, target >> 16
  880. ori $25, $25, target & 0xffff
  881. jr $25
  882. nop
  883. 1:
  884. Note: beq/bne/bc1t/bc1f are converted to bne/beq/bc1f/bc1t.
  885. */
  886. if (*(insn + 2) == 0x10000003) {
  887. if ((*insn & 0xfc000000) == 0x10000000) // beq
  888. *insn = (*insn & 0x03ff0000) | 0x14000005; // bne
  889. else if ((*insn & 0xfc000000) == 0x14000000) // bne
  890. *insn = (*insn & 0x03ff0000) | 0x10000005; // beq
  891. else if ((*insn & 0xffff0000) == 0x45010000) // bc1t
  892. *insn = 0x45000005; // bc1f
  893. else if ((*insn & 0xffff0000) == 0x45000000) // bc1f
  894. *insn = 0x45010005; // bc1t
  895. else
  896. ASSERT(0);
  897. }
  898. insn = insn + 2;
  899. if ((reinterpret_cast<intptr_t>(insn) + 4) >> 28
  900. == reinterpret_cast<intptr_t>(to) >> 28) {
  901. *insn = 0x08000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
  902. *(insn + 1) = 0;
  903. return 4 * sizeof(MIPSWord);
  904. }
  905. intptr_t newTargetAddress = reinterpret_cast<intptr_t>(to);
  906. /* lui */
  907. *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
  908. /* ori */
  909. *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
  910. /* jr */
  911. *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
  912. return 5 * sizeof(MIPSWord);
  913. }
  914. *insn = (*insn & 0xffff0000) | (diff & 0xffff);
  915. return sizeof(MIPSWord);
  916. }
  917. static int linkCallInternal(void* from, void* to)
  918. {
  919. MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
  920. insn = insn - 4;
  921. if ((*(insn + 2) & 0xfc000000) == 0x0c000000) { // jal
  922. if ((reinterpret_cast<intptr_t>(from) - 4) >> 28
  923. == reinterpret_cast<intptr_t>(to) >> 28) {
  924. *(insn + 2) = 0x0c000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
  925. return sizeof(MIPSWord);
  926. }
  927. /* lui $25, (to >> 16) & 0xffff */
  928. *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
  929. /* ori $25, $25, to & 0xffff */
  930. *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (reinterpret_cast<intptr_t>(to) & 0xffff);
  931. /* jalr $25 */
  932. *(insn + 2) = 0x0000f809 | (MIPSRegisters::t9 << OP_SH_RS);
  933. return 3 * sizeof(MIPSWord);
  934. }
  935. ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
  936. ASSERT((*(insn + 1) & 0xfc000000) == 0x34000000); // ori
  937. /* lui */
  938. *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
  939. /* ori */
  940. *(insn + 1) = (*(insn + 1) & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
  941. return 2 * sizeof(MIPSWord);
  942. }
  943. AssemblerBuffer m_buffer;
  944. Jumps m_jumps;
  945. int m_indexOfLastWatchpoint;
  946. int m_indexOfTailOfLastWatchpoint;
  947. };
  948. } // namespace JSC
  949. #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
  950. #endif // MIPSAssembler_h