libv8-sgonyea 3.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (500) hide show
  1. data/.gitignore +8 -0
  2. data/.gitmodules +3 -0
  3. data/Gemfile +4 -0
  4. data/README.md +76 -0
  5. data/Rakefile +113 -0
  6. data/ext/libv8/extconf.rb +28 -0
  7. data/lib/libv8.rb +15 -0
  8. data/lib/libv8/Makefile +30 -0
  9. data/lib/libv8/detect_cpu.rb +27 -0
  10. data/lib/libv8/fpic-on-linux-amd64.patch +13 -0
  11. data/lib/libv8/v8/.gitignore +35 -0
  12. data/lib/libv8/v8/AUTHORS +44 -0
  13. data/lib/libv8/v8/ChangeLog +2839 -0
  14. data/lib/libv8/v8/LICENSE +52 -0
  15. data/lib/libv8/v8/LICENSE.strongtalk +29 -0
  16. data/lib/libv8/v8/LICENSE.v8 +26 -0
  17. data/lib/libv8/v8/LICENSE.valgrind +45 -0
  18. data/lib/libv8/v8/SConstruct +1478 -0
  19. data/lib/libv8/v8/build/README.txt +49 -0
  20. data/lib/libv8/v8/build/all.gyp +18 -0
  21. data/lib/libv8/v8/build/armu.gypi +32 -0
  22. data/lib/libv8/v8/build/common.gypi +144 -0
  23. data/lib/libv8/v8/build/gyp_v8 +145 -0
  24. data/lib/libv8/v8/include/v8-debug.h +395 -0
  25. data/lib/libv8/v8/include/v8-preparser.h +117 -0
  26. data/lib/libv8/v8/include/v8-profiler.h +505 -0
  27. data/lib/libv8/v8/include/v8-testing.h +104 -0
  28. data/lib/libv8/v8/include/v8.h +4124 -0
  29. data/lib/libv8/v8/include/v8stdint.h +53 -0
  30. data/lib/libv8/v8/preparser/SConscript +38 -0
  31. data/lib/libv8/v8/preparser/preparser-process.cc +379 -0
  32. data/lib/libv8/v8/src/SConscript +368 -0
  33. data/lib/libv8/v8/src/accessors.cc +767 -0
  34. data/lib/libv8/v8/src/accessors.h +123 -0
  35. data/lib/libv8/v8/src/allocation-inl.h +49 -0
  36. data/lib/libv8/v8/src/allocation.cc +122 -0
  37. data/lib/libv8/v8/src/allocation.h +143 -0
  38. data/lib/libv8/v8/src/api.cc +5845 -0
  39. data/lib/libv8/v8/src/api.h +574 -0
  40. data/lib/libv8/v8/src/apinatives.js +110 -0
  41. data/lib/libv8/v8/src/apiutils.h +73 -0
  42. data/lib/libv8/v8/src/arguments.h +118 -0
  43. data/lib/libv8/v8/src/arm/assembler-arm-inl.h +353 -0
  44. data/lib/libv8/v8/src/arm/assembler-arm.cc +2661 -0
  45. data/lib/libv8/v8/src/arm/assembler-arm.h +1375 -0
  46. data/lib/libv8/v8/src/arm/builtins-arm.cc +1658 -0
  47. data/lib/libv8/v8/src/arm/code-stubs-arm.cc +6398 -0
  48. data/lib/libv8/v8/src/arm/code-stubs-arm.h +673 -0
  49. data/lib/libv8/v8/src/arm/codegen-arm.cc +52 -0
  50. data/lib/libv8/v8/src/arm/codegen-arm.h +91 -0
  51. data/lib/libv8/v8/src/arm/constants-arm.cc +152 -0
  52. data/lib/libv8/v8/src/arm/constants-arm.h +775 -0
  53. data/lib/libv8/v8/src/arm/cpu-arm.cc +120 -0
  54. data/lib/libv8/v8/src/arm/debug-arm.cc +317 -0
  55. data/lib/libv8/v8/src/arm/deoptimizer-arm.cc +754 -0
  56. data/lib/libv8/v8/src/arm/disasm-arm.cc +1506 -0
  57. data/lib/libv8/v8/src/arm/frames-arm.cc +45 -0
  58. data/lib/libv8/v8/src/arm/frames-arm.h +168 -0
  59. data/lib/libv8/v8/src/arm/full-codegen-arm.cc +4375 -0
  60. data/lib/libv8/v8/src/arm/ic-arm.cc +1562 -0
  61. data/lib/libv8/v8/src/arm/lithium-arm.cc +2206 -0
  62. data/lib/libv8/v8/src/arm/lithium-arm.h +2348 -0
  63. data/lib/libv8/v8/src/arm/lithium-codegen-arm.cc +4526 -0
  64. data/lib/libv8/v8/src/arm/lithium-codegen-arm.h +403 -0
  65. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.cc +305 -0
  66. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.h +84 -0
  67. data/lib/libv8/v8/src/arm/macro-assembler-arm.cc +3163 -0
  68. data/lib/libv8/v8/src/arm/macro-assembler-arm.h +1126 -0
  69. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.cc +1287 -0
  70. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.h +253 -0
  71. data/lib/libv8/v8/src/arm/simulator-arm.cc +3424 -0
  72. data/lib/libv8/v8/src/arm/simulator-arm.h +431 -0
  73. data/lib/libv8/v8/src/arm/stub-cache-arm.cc +4243 -0
  74. data/lib/libv8/v8/src/array.js +1366 -0
  75. data/lib/libv8/v8/src/assembler.cc +1207 -0
  76. data/lib/libv8/v8/src/assembler.h +858 -0
  77. data/lib/libv8/v8/src/ast-inl.h +112 -0
  78. data/lib/libv8/v8/src/ast.cc +1146 -0
  79. data/lib/libv8/v8/src/ast.h +2188 -0
  80. data/lib/libv8/v8/src/atomicops.h +167 -0
  81. data/lib/libv8/v8/src/atomicops_internals_arm_gcc.h +145 -0
  82. data/lib/libv8/v8/src/atomicops_internals_mips_gcc.h +169 -0
  83. data/lib/libv8/v8/src/atomicops_internals_x86_gcc.cc +133 -0
  84. data/lib/libv8/v8/src/atomicops_internals_x86_gcc.h +287 -0
  85. data/lib/libv8/v8/src/atomicops_internals_x86_macosx.h +301 -0
  86. data/lib/libv8/v8/src/atomicops_internals_x86_msvc.h +203 -0
  87. data/lib/libv8/v8/src/bignum-dtoa.cc +655 -0
  88. data/lib/libv8/v8/src/bignum-dtoa.h +81 -0
  89. data/lib/libv8/v8/src/bignum.cc +768 -0
  90. data/lib/libv8/v8/src/bignum.h +140 -0
  91. data/lib/libv8/v8/src/bootstrapper.cc +2184 -0
  92. data/lib/libv8/v8/src/bootstrapper.h +188 -0
  93. data/lib/libv8/v8/src/builtins.cc +1707 -0
  94. data/lib/libv8/v8/src/builtins.h +371 -0
  95. data/lib/libv8/v8/src/bytecodes-irregexp.h +105 -0
  96. data/lib/libv8/v8/src/cached-powers.cc +177 -0
  97. data/lib/libv8/v8/src/cached-powers.h +65 -0
  98. data/lib/libv8/v8/src/char-predicates-inl.h +94 -0
  99. data/lib/libv8/v8/src/char-predicates.h +67 -0
  100. data/lib/libv8/v8/src/checks.cc +110 -0
  101. data/lib/libv8/v8/src/checks.h +296 -0
  102. data/lib/libv8/v8/src/circular-queue-inl.h +53 -0
  103. data/lib/libv8/v8/src/circular-queue.cc +122 -0
  104. data/lib/libv8/v8/src/circular-queue.h +103 -0
  105. data/lib/libv8/v8/src/code-stubs.cc +267 -0
  106. data/lib/libv8/v8/src/code-stubs.h +1011 -0
  107. data/lib/libv8/v8/src/code.h +70 -0
  108. data/lib/libv8/v8/src/codegen.cc +231 -0
  109. data/lib/libv8/v8/src/codegen.h +84 -0
  110. data/lib/libv8/v8/src/compilation-cache.cc +540 -0
  111. data/lib/libv8/v8/src/compilation-cache.h +287 -0
  112. data/lib/libv8/v8/src/compiler.cc +786 -0
  113. data/lib/libv8/v8/src/compiler.h +312 -0
  114. data/lib/libv8/v8/src/contexts.cc +347 -0
  115. data/lib/libv8/v8/src/contexts.h +391 -0
  116. data/lib/libv8/v8/src/conversions-inl.h +106 -0
  117. data/lib/libv8/v8/src/conversions.cc +1131 -0
  118. data/lib/libv8/v8/src/conversions.h +135 -0
  119. data/lib/libv8/v8/src/counters.cc +93 -0
  120. data/lib/libv8/v8/src/counters.h +254 -0
  121. data/lib/libv8/v8/src/cpu-profiler-inl.h +101 -0
  122. data/lib/libv8/v8/src/cpu-profiler.cc +609 -0
  123. data/lib/libv8/v8/src/cpu-profiler.h +302 -0
  124. data/lib/libv8/v8/src/cpu.h +69 -0
  125. data/lib/libv8/v8/src/d8-debug.cc +367 -0
  126. data/lib/libv8/v8/src/d8-debug.h +158 -0
  127. data/lib/libv8/v8/src/d8-posix.cc +695 -0
  128. data/lib/libv8/v8/src/d8-readline.cc +130 -0
  129. data/lib/libv8/v8/src/d8-windows.cc +42 -0
  130. data/lib/libv8/v8/src/d8.cc +803 -0
  131. data/lib/libv8/v8/src/d8.gyp +91 -0
  132. data/lib/libv8/v8/src/d8.h +235 -0
  133. data/lib/libv8/v8/src/d8.js +2798 -0
  134. data/lib/libv8/v8/src/data-flow.cc +66 -0
  135. data/lib/libv8/v8/src/data-flow.h +205 -0
  136. data/lib/libv8/v8/src/date.js +1103 -0
  137. data/lib/libv8/v8/src/dateparser-inl.h +127 -0
  138. data/lib/libv8/v8/src/dateparser.cc +178 -0
  139. data/lib/libv8/v8/src/dateparser.h +266 -0
  140. data/lib/libv8/v8/src/debug-agent.cc +447 -0
  141. data/lib/libv8/v8/src/debug-agent.h +129 -0
  142. data/lib/libv8/v8/src/debug-debugger.js +2569 -0
  143. data/lib/libv8/v8/src/debug.cc +3165 -0
  144. data/lib/libv8/v8/src/debug.h +1057 -0
  145. data/lib/libv8/v8/src/deoptimizer.cc +1256 -0
  146. data/lib/libv8/v8/src/deoptimizer.h +602 -0
  147. data/lib/libv8/v8/src/disasm.h +80 -0
  148. data/lib/libv8/v8/src/disassembler.cc +343 -0
  149. data/lib/libv8/v8/src/disassembler.h +58 -0
  150. data/lib/libv8/v8/src/diy-fp.cc +58 -0
  151. data/lib/libv8/v8/src/diy-fp.h +117 -0
  152. data/lib/libv8/v8/src/double.h +238 -0
  153. data/lib/libv8/v8/src/dtoa.cc +103 -0
  154. data/lib/libv8/v8/src/dtoa.h +85 -0
  155. data/lib/libv8/v8/src/execution.cc +849 -0
  156. data/lib/libv8/v8/src/execution.h +297 -0
  157. data/lib/libv8/v8/src/extensions/experimental/break-iterator.cc +250 -0
  158. data/lib/libv8/v8/src/extensions/experimental/break-iterator.h +89 -0
  159. data/lib/libv8/v8/src/extensions/experimental/collator.cc +218 -0
  160. data/lib/libv8/v8/src/extensions/experimental/collator.h +69 -0
  161. data/lib/libv8/v8/src/extensions/experimental/experimental.gyp +94 -0
  162. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.cc +78 -0
  163. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.h +54 -0
  164. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.cc +112 -0
  165. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.h +60 -0
  166. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.cc +43 -0
  167. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.h +49 -0
  168. data/lib/libv8/v8/src/extensions/experimental/i18n.js +180 -0
  169. data/lib/libv8/v8/src/extensions/experimental/language-matcher.cc +251 -0
  170. data/lib/libv8/v8/src/extensions/experimental/language-matcher.h +95 -0
  171. data/lib/libv8/v8/src/extensions/externalize-string-extension.cc +141 -0
  172. data/lib/libv8/v8/src/extensions/externalize-string-extension.h +50 -0
  173. data/lib/libv8/v8/src/extensions/gc-extension.cc +58 -0
  174. data/lib/libv8/v8/src/extensions/gc-extension.h +49 -0
  175. data/lib/libv8/v8/src/factory.cc +1222 -0
  176. data/lib/libv8/v8/src/factory.h +442 -0
  177. data/lib/libv8/v8/src/fast-dtoa.cc +736 -0
  178. data/lib/libv8/v8/src/fast-dtoa.h +83 -0
  179. data/lib/libv8/v8/src/fixed-dtoa.cc +405 -0
  180. data/lib/libv8/v8/src/fixed-dtoa.h +55 -0
  181. data/lib/libv8/v8/src/flag-definitions.h +560 -0
  182. data/lib/libv8/v8/src/flags.cc +551 -0
  183. data/lib/libv8/v8/src/flags.h +79 -0
  184. data/lib/libv8/v8/src/frames-inl.h +247 -0
  185. data/lib/libv8/v8/src/frames.cc +1243 -0
  186. data/lib/libv8/v8/src/frames.h +870 -0
  187. data/lib/libv8/v8/src/full-codegen.cc +1374 -0
  188. data/lib/libv8/v8/src/full-codegen.h +771 -0
  189. data/lib/libv8/v8/src/func-name-inferrer.cc +92 -0
  190. data/lib/libv8/v8/src/func-name-inferrer.h +111 -0
  191. data/lib/libv8/v8/src/gdb-jit.cc +1555 -0
  192. data/lib/libv8/v8/src/gdb-jit.h +143 -0
  193. data/lib/libv8/v8/src/global-handles.cc +665 -0
  194. data/lib/libv8/v8/src/global-handles.h +284 -0
  195. data/lib/libv8/v8/src/globals.h +325 -0
  196. data/lib/libv8/v8/src/handles-inl.h +177 -0
  197. data/lib/libv8/v8/src/handles.cc +987 -0
  198. data/lib/libv8/v8/src/handles.h +382 -0
  199. data/lib/libv8/v8/src/hashmap.cc +230 -0
  200. data/lib/libv8/v8/src/hashmap.h +123 -0
  201. data/lib/libv8/v8/src/heap-inl.h +704 -0
  202. data/lib/libv8/v8/src/heap-profiler.cc +1173 -0
  203. data/lib/libv8/v8/src/heap-profiler.h +397 -0
  204. data/lib/libv8/v8/src/heap.cc +5930 -0
  205. data/lib/libv8/v8/src/heap.h +2268 -0
  206. data/lib/libv8/v8/src/hydrogen-instructions.cc +1769 -0
  207. data/lib/libv8/v8/src/hydrogen-instructions.h +3971 -0
  208. data/lib/libv8/v8/src/hydrogen.cc +6239 -0
  209. data/lib/libv8/v8/src/hydrogen.h +1202 -0
  210. data/lib/libv8/v8/src/ia32/assembler-ia32-inl.h +446 -0
  211. data/lib/libv8/v8/src/ia32/assembler-ia32.cc +2487 -0
  212. data/lib/libv8/v8/src/ia32/assembler-ia32.h +1144 -0
  213. data/lib/libv8/v8/src/ia32/builtins-ia32.cc +1621 -0
  214. data/lib/libv8/v8/src/ia32/code-stubs-ia32.cc +6198 -0
  215. data/lib/libv8/v8/src/ia32/code-stubs-ia32.h +517 -0
  216. data/lib/libv8/v8/src/ia32/codegen-ia32.cc +265 -0
  217. data/lib/libv8/v8/src/ia32/codegen-ia32.h +79 -0
  218. data/lib/libv8/v8/src/ia32/cpu-ia32.cc +88 -0
  219. data/lib/libv8/v8/src/ia32/debug-ia32.cc +312 -0
  220. data/lib/libv8/v8/src/ia32/deoptimizer-ia32.cc +774 -0
  221. data/lib/libv8/v8/src/ia32/disasm-ia32.cc +1628 -0
  222. data/lib/libv8/v8/src/ia32/frames-ia32.cc +45 -0
  223. data/lib/libv8/v8/src/ia32/frames-ia32.h +142 -0
  224. data/lib/libv8/v8/src/ia32/full-codegen-ia32.cc +4338 -0
  225. data/lib/libv8/v8/src/ia32/ic-ia32.cc +1597 -0
  226. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.cc +4461 -0
  227. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.h +375 -0
  228. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.cc +475 -0
  229. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.h +110 -0
  230. data/lib/libv8/v8/src/ia32/lithium-ia32.cc +2261 -0
  231. data/lib/libv8/v8/src/ia32/lithium-ia32.h +2396 -0
  232. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.cc +2136 -0
  233. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.h +775 -0
  234. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.cc +1263 -0
  235. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.h +216 -0
  236. data/lib/libv8/v8/src/ia32/simulator-ia32.cc +30 -0
  237. data/lib/libv8/v8/src/ia32/simulator-ia32.h +74 -0
  238. data/lib/libv8/v8/src/ia32/stub-cache-ia32.cc +3847 -0
  239. data/lib/libv8/v8/src/ic-inl.h +130 -0
  240. data/lib/libv8/v8/src/ic.cc +2577 -0
  241. data/lib/libv8/v8/src/ic.h +736 -0
  242. data/lib/libv8/v8/src/inspector.cc +63 -0
  243. data/lib/libv8/v8/src/inspector.h +62 -0
  244. data/lib/libv8/v8/src/interpreter-irregexp.cc +659 -0
  245. data/lib/libv8/v8/src/interpreter-irregexp.h +49 -0
  246. data/lib/libv8/v8/src/isolate-inl.h +50 -0
  247. data/lib/libv8/v8/src/isolate.cc +1869 -0
  248. data/lib/libv8/v8/src/isolate.h +1382 -0
  249. data/lib/libv8/v8/src/json-parser.cc +504 -0
  250. data/lib/libv8/v8/src/json-parser.h +161 -0
  251. data/lib/libv8/v8/src/json.js +342 -0
  252. data/lib/libv8/v8/src/jsregexp.cc +5385 -0
  253. data/lib/libv8/v8/src/jsregexp.h +1492 -0
  254. data/lib/libv8/v8/src/list-inl.h +212 -0
  255. data/lib/libv8/v8/src/list.h +174 -0
  256. data/lib/libv8/v8/src/lithium-allocator-inl.h +142 -0
  257. data/lib/libv8/v8/src/lithium-allocator.cc +2123 -0
  258. data/lib/libv8/v8/src/lithium-allocator.h +630 -0
  259. data/lib/libv8/v8/src/lithium.cc +190 -0
  260. data/lib/libv8/v8/src/lithium.h +597 -0
  261. data/lib/libv8/v8/src/liveedit-debugger.js +1082 -0
  262. data/lib/libv8/v8/src/liveedit.cc +1691 -0
  263. data/lib/libv8/v8/src/liveedit.h +180 -0
  264. data/lib/libv8/v8/src/liveobjectlist-inl.h +126 -0
  265. data/lib/libv8/v8/src/liveobjectlist.cc +2589 -0
  266. data/lib/libv8/v8/src/liveobjectlist.h +322 -0
  267. data/lib/libv8/v8/src/log-inl.h +59 -0
  268. data/lib/libv8/v8/src/log-utils.cc +428 -0
  269. data/lib/libv8/v8/src/log-utils.h +231 -0
  270. data/lib/libv8/v8/src/log.cc +1993 -0
  271. data/lib/libv8/v8/src/log.h +476 -0
  272. data/lib/libv8/v8/src/macro-assembler.h +120 -0
  273. data/lib/libv8/v8/src/macros.py +178 -0
  274. data/lib/libv8/v8/src/mark-compact.cc +3143 -0
  275. data/lib/libv8/v8/src/mark-compact.h +506 -0
  276. data/lib/libv8/v8/src/math.js +264 -0
  277. data/lib/libv8/v8/src/messages.cc +179 -0
  278. data/lib/libv8/v8/src/messages.h +113 -0
  279. data/lib/libv8/v8/src/messages.js +1096 -0
  280. data/lib/libv8/v8/src/mips/assembler-mips-inl.h +312 -0
  281. data/lib/libv8/v8/src/mips/assembler-mips.cc +1960 -0
  282. data/lib/libv8/v8/src/mips/assembler-mips.h +1138 -0
  283. data/lib/libv8/v8/src/mips/builtins-mips.cc +1628 -0
  284. data/lib/libv8/v8/src/mips/code-stubs-mips.cc +6656 -0
  285. data/lib/libv8/v8/src/mips/code-stubs-mips.h +682 -0
  286. data/lib/libv8/v8/src/mips/codegen-mips.cc +52 -0
  287. data/lib/libv8/v8/src/mips/codegen-mips.h +98 -0
  288. data/lib/libv8/v8/src/mips/constants-mips.cc +352 -0
  289. data/lib/libv8/v8/src/mips/constants-mips.h +739 -0
  290. data/lib/libv8/v8/src/mips/cpu-mips.cc +96 -0
  291. data/lib/libv8/v8/src/mips/debug-mips.cc +308 -0
  292. data/lib/libv8/v8/src/mips/deoptimizer-mips.cc +91 -0
  293. data/lib/libv8/v8/src/mips/disasm-mips.cc +1050 -0
  294. data/lib/libv8/v8/src/mips/frames-mips.cc +47 -0
  295. data/lib/libv8/v8/src/mips/frames-mips.h +219 -0
  296. data/lib/libv8/v8/src/mips/full-codegen-mips.cc +4388 -0
  297. data/lib/libv8/v8/src/mips/ic-mips.cc +1580 -0
  298. data/lib/libv8/v8/src/mips/lithium-codegen-mips.h +65 -0
  299. data/lib/libv8/v8/src/mips/lithium-mips.h +307 -0
  300. data/lib/libv8/v8/src/mips/macro-assembler-mips.cc +4056 -0
  301. data/lib/libv8/v8/src/mips/macro-assembler-mips.h +1214 -0
  302. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.cc +1251 -0
  303. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.h +252 -0
  304. data/lib/libv8/v8/src/mips/simulator-mips.cc +2621 -0
  305. data/lib/libv8/v8/src/mips/simulator-mips.h +401 -0
  306. data/lib/libv8/v8/src/mips/stub-cache-mips.cc +4285 -0
  307. data/lib/libv8/v8/src/mirror-debugger.js +2382 -0
  308. data/lib/libv8/v8/src/mksnapshot.cc +328 -0
  309. data/lib/libv8/v8/src/natives.h +64 -0
  310. data/lib/libv8/v8/src/objects-debug.cc +738 -0
  311. data/lib/libv8/v8/src/objects-inl.h +4323 -0
  312. data/lib/libv8/v8/src/objects-printer.cc +829 -0
  313. data/lib/libv8/v8/src/objects-visiting.cc +148 -0
  314. data/lib/libv8/v8/src/objects-visiting.h +424 -0
  315. data/lib/libv8/v8/src/objects.cc +10585 -0
  316. data/lib/libv8/v8/src/objects.h +6838 -0
  317. data/lib/libv8/v8/src/parser.cc +4997 -0
  318. data/lib/libv8/v8/src/parser.h +765 -0
  319. data/lib/libv8/v8/src/platform-cygwin.cc +779 -0
  320. data/lib/libv8/v8/src/platform-freebsd.cc +826 -0
  321. data/lib/libv8/v8/src/platform-linux.cc +1149 -0
  322. data/lib/libv8/v8/src/platform-macos.cc +830 -0
  323. data/lib/libv8/v8/src/platform-nullos.cc +479 -0
  324. data/lib/libv8/v8/src/platform-openbsd.cc +640 -0
  325. data/lib/libv8/v8/src/platform-posix.cc +424 -0
  326. data/lib/libv8/v8/src/platform-solaris.cc +762 -0
  327. data/lib/libv8/v8/src/platform-tls-mac.h +62 -0
  328. data/lib/libv8/v8/src/platform-tls-win32.h +62 -0
  329. data/lib/libv8/v8/src/platform-tls.h +50 -0
  330. data/lib/libv8/v8/src/platform-win32.cc +2021 -0
  331. data/lib/libv8/v8/src/platform.h +667 -0
  332. data/lib/libv8/v8/src/preparse-data-format.h +62 -0
  333. data/lib/libv8/v8/src/preparse-data.cc +183 -0
  334. data/lib/libv8/v8/src/preparse-data.h +225 -0
  335. data/lib/libv8/v8/src/preparser-api.cc +220 -0
  336. data/lib/libv8/v8/src/preparser.cc +1450 -0
  337. data/lib/libv8/v8/src/preparser.h +493 -0
  338. data/lib/libv8/v8/src/prettyprinter.cc +1493 -0
  339. data/lib/libv8/v8/src/prettyprinter.h +223 -0
  340. data/lib/libv8/v8/src/profile-generator-inl.h +128 -0
  341. data/lib/libv8/v8/src/profile-generator.cc +3098 -0
  342. data/lib/libv8/v8/src/profile-generator.h +1126 -0
  343. data/lib/libv8/v8/src/property.cc +105 -0
  344. data/lib/libv8/v8/src/property.h +365 -0
  345. data/lib/libv8/v8/src/proxy.js +83 -0
  346. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp-inl.h +78 -0
  347. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp.cc +471 -0
  348. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp.h +142 -0
  349. data/lib/libv8/v8/src/regexp-macro-assembler-tracer.cc +373 -0
  350. data/lib/libv8/v8/src/regexp-macro-assembler-tracer.h +104 -0
  351. data/lib/libv8/v8/src/regexp-macro-assembler.cc +267 -0
  352. data/lib/libv8/v8/src/regexp-macro-assembler.h +243 -0
  353. data/lib/libv8/v8/src/regexp-stack.cc +111 -0
  354. data/lib/libv8/v8/src/regexp-stack.h +147 -0
  355. data/lib/libv8/v8/src/regexp.js +483 -0
  356. data/lib/libv8/v8/src/rewriter.cc +360 -0
  357. data/lib/libv8/v8/src/rewriter.h +50 -0
  358. data/lib/libv8/v8/src/runtime-profiler.cc +489 -0
  359. data/lib/libv8/v8/src/runtime-profiler.h +201 -0
  360. data/lib/libv8/v8/src/runtime.cc +12227 -0
  361. data/lib/libv8/v8/src/runtime.h +652 -0
  362. data/lib/libv8/v8/src/runtime.js +649 -0
  363. data/lib/libv8/v8/src/safepoint-table.cc +256 -0
  364. data/lib/libv8/v8/src/safepoint-table.h +270 -0
  365. data/lib/libv8/v8/src/scanner-base.cc +952 -0
  366. data/lib/libv8/v8/src/scanner-base.h +670 -0
  367. data/lib/libv8/v8/src/scanner.cc +345 -0
  368. data/lib/libv8/v8/src/scanner.h +146 -0
  369. data/lib/libv8/v8/src/scopeinfo.cc +646 -0
  370. data/lib/libv8/v8/src/scopeinfo.h +254 -0
  371. data/lib/libv8/v8/src/scopes.cc +1150 -0
  372. data/lib/libv8/v8/src/scopes.h +507 -0
  373. data/lib/libv8/v8/src/serialize.cc +1574 -0
  374. data/lib/libv8/v8/src/serialize.h +589 -0
  375. data/lib/libv8/v8/src/shell.h +55 -0
  376. data/lib/libv8/v8/src/simulator.h +43 -0
  377. data/lib/libv8/v8/src/small-pointer-list.h +163 -0
  378. data/lib/libv8/v8/src/smart-pointer.h +109 -0
  379. data/lib/libv8/v8/src/snapshot-common.cc +83 -0
  380. data/lib/libv8/v8/src/snapshot-empty.cc +54 -0
  381. data/lib/libv8/v8/src/snapshot.h +91 -0
  382. data/lib/libv8/v8/src/spaces-inl.h +529 -0
  383. data/lib/libv8/v8/src/spaces.cc +3145 -0
  384. data/lib/libv8/v8/src/spaces.h +2369 -0
  385. data/lib/libv8/v8/src/splay-tree-inl.h +310 -0
  386. data/lib/libv8/v8/src/splay-tree.h +205 -0
  387. data/lib/libv8/v8/src/string-search.cc +41 -0
  388. data/lib/libv8/v8/src/string-search.h +568 -0
  389. data/lib/libv8/v8/src/string-stream.cc +592 -0
  390. data/lib/libv8/v8/src/string-stream.h +191 -0
  391. data/lib/libv8/v8/src/string.js +994 -0
  392. data/lib/libv8/v8/src/strtod.cc +440 -0
  393. data/lib/libv8/v8/src/strtod.h +40 -0
  394. data/lib/libv8/v8/src/stub-cache.cc +1965 -0
  395. data/lib/libv8/v8/src/stub-cache.h +924 -0
  396. data/lib/libv8/v8/src/third_party/valgrind/valgrind.h +3925 -0
  397. data/lib/libv8/v8/src/token.cc +63 -0
  398. data/lib/libv8/v8/src/token.h +288 -0
  399. data/lib/libv8/v8/src/type-info.cc +507 -0
  400. data/lib/libv8/v8/src/type-info.h +272 -0
  401. data/lib/libv8/v8/src/unbound-queue-inl.h +95 -0
  402. data/lib/libv8/v8/src/unbound-queue.h +69 -0
  403. data/lib/libv8/v8/src/unicode-inl.h +238 -0
  404. data/lib/libv8/v8/src/unicode.cc +1624 -0
  405. data/lib/libv8/v8/src/unicode.h +280 -0
  406. data/lib/libv8/v8/src/uri.js +408 -0
  407. data/lib/libv8/v8/src/utils-inl.h +48 -0
  408. data/lib/libv8/v8/src/utils.cc +371 -0
  409. data/lib/libv8/v8/src/utils.h +800 -0
  410. data/lib/libv8/v8/src/v8-counters.cc +62 -0
  411. data/lib/libv8/v8/src/v8-counters.h +314 -0
  412. data/lib/libv8/v8/src/v8.cc +213 -0
  413. data/lib/libv8/v8/src/v8.h +131 -0
  414. data/lib/libv8/v8/src/v8checks.h +64 -0
  415. data/lib/libv8/v8/src/v8dll-main.cc +44 -0
  416. data/lib/libv8/v8/src/v8globals.h +512 -0
  417. data/lib/libv8/v8/src/v8memory.h +82 -0
  418. data/lib/libv8/v8/src/v8natives.js +1310 -0
  419. data/lib/libv8/v8/src/v8preparserdll-main.cc +39 -0
  420. data/lib/libv8/v8/src/v8threads.cc +464 -0
  421. data/lib/libv8/v8/src/v8threads.h +165 -0
  422. data/lib/libv8/v8/src/v8utils.h +319 -0
  423. data/lib/libv8/v8/src/variables.cc +114 -0
  424. data/lib/libv8/v8/src/variables.h +167 -0
  425. data/lib/libv8/v8/src/version.cc +116 -0
  426. data/lib/libv8/v8/src/version.h +68 -0
  427. data/lib/libv8/v8/src/vm-state-inl.h +138 -0
  428. data/lib/libv8/v8/src/vm-state.h +71 -0
  429. data/lib/libv8/v8/src/win32-headers.h +96 -0
  430. data/lib/libv8/v8/src/x64/assembler-x64-inl.h +462 -0
  431. data/lib/libv8/v8/src/x64/assembler-x64.cc +3027 -0
  432. data/lib/libv8/v8/src/x64/assembler-x64.h +1633 -0
  433. data/lib/libv8/v8/src/x64/builtins-x64.cc +1520 -0
  434. data/lib/libv8/v8/src/x64/code-stubs-x64.cc +5132 -0
  435. data/lib/libv8/v8/src/x64/code-stubs-x64.h +514 -0
  436. data/lib/libv8/v8/src/x64/codegen-x64.cc +146 -0
  437. data/lib/libv8/v8/src/x64/codegen-x64.h +76 -0
  438. data/lib/libv8/v8/src/x64/cpu-x64.cc +88 -0
  439. data/lib/libv8/v8/src/x64/debug-x64.cc +319 -0
  440. data/lib/libv8/v8/src/x64/deoptimizer-x64.cc +815 -0
  441. data/lib/libv8/v8/src/x64/disasm-x64.cc +1832 -0
  442. data/lib/libv8/v8/src/x64/frames-x64.cc +45 -0
  443. data/lib/libv8/v8/src/x64/frames-x64.h +130 -0
  444. data/lib/libv8/v8/src/x64/full-codegen-x64.cc +4318 -0
  445. data/lib/libv8/v8/src/x64/ic-x64.cc +1608 -0
  446. data/lib/libv8/v8/src/x64/lithium-codegen-x64.cc +4267 -0
  447. data/lib/libv8/v8/src/x64/lithium-codegen-x64.h +367 -0
  448. data/lib/libv8/v8/src/x64/lithium-gap-resolver-x64.cc +320 -0
  449. data/lib/libv8/v8/src/x64/lithium-gap-resolver-x64.h +74 -0
  450. data/lib/libv8/v8/src/x64/lithium-x64.cc +2202 -0
  451. data/lib/libv8/v8/src/x64/lithium-x64.h +2333 -0
  452. data/lib/libv8/v8/src/x64/macro-assembler-x64.cc +3745 -0
  453. data/lib/libv8/v8/src/x64/macro-assembler-x64.h +1290 -0
  454. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.cc +1398 -0
  455. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.h +282 -0
  456. data/lib/libv8/v8/src/x64/simulator-x64.cc +27 -0
  457. data/lib/libv8/v8/src/x64/simulator-x64.h +72 -0
  458. data/lib/libv8/v8/src/x64/stub-cache-x64.cc +3610 -0
  459. data/lib/libv8/v8/src/zone-inl.h +140 -0
  460. data/lib/libv8/v8/src/zone.cc +196 -0
  461. data/lib/libv8/v8/src/zone.h +240 -0
  462. data/lib/libv8/v8/tools/codemap.js +265 -0
  463. data/lib/libv8/v8/tools/consarray.js +93 -0
  464. data/lib/libv8/v8/tools/csvparser.js +78 -0
  465. data/lib/libv8/v8/tools/disasm.py +92 -0
  466. data/lib/libv8/v8/tools/freebsd-tick-processor +10 -0
  467. data/lib/libv8/v8/tools/gc-nvp-trace-processor.py +342 -0
  468. data/lib/libv8/v8/tools/gcmole/README +62 -0
  469. data/lib/libv8/v8/tools/gcmole/gccause.lua +60 -0
  470. data/lib/libv8/v8/tools/gcmole/gcmole.cc +1261 -0
  471. data/lib/libv8/v8/tools/gcmole/gcmole.lua +378 -0
  472. data/lib/libv8/v8/tools/generate-ten-powers.scm +286 -0
  473. data/lib/libv8/v8/tools/grokdump.py +841 -0
  474. data/lib/libv8/v8/tools/gyp/v8.gyp +995 -0
  475. data/lib/libv8/v8/tools/js2c.py +364 -0
  476. data/lib/libv8/v8/tools/jsmin.py +280 -0
  477. data/lib/libv8/v8/tools/linux-tick-processor +35 -0
  478. data/lib/libv8/v8/tools/ll_prof.py +942 -0
  479. data/lib/libv8/v8/tools/logreader.js +185 -0
  480. data/lib/libv8/v8/tools/mac-nm +18 -0
  481. data/lib/libv8/v8/tools/mac-tick-processor +6 -0
  482. data/lib/libv8/v8/tools/oom_dump/README +31 -0
  483. data/lib/libv8/v8/tools/oom_dump/SConstruct +42 -0
  484. data/lib/libv8/v8/tools/oom_dump/oom_dump.cc +288 -0
  485. data/lib/libv8/v8/tools/presubmit.py +305 -0
  486. data/lib/libv8/v8/tools/process-heap-prof.py +120 -0
  487. data/lib/libv8/v8/tools/profile.js +751 -0
  488. data/lib/libv8/v8/tools/profile_view.js +219 -0
  489. data/lib/libv8/v8/tools/run-valgrind.py +77 -0
  490. data/lib/libv8/v8/tools/splaytree.js +316 -0
  491. data/lib/libv8/v8/tools/stats-viewer.py +468 -0
  492. data/lib/libv8/v8/tools/test.py +1510 -0
  493. data/lib/libv8/v8/tools/tickprocessor-driver.js +59 -0
  494. data/lib/libv8/v8/tools/tickprocessor.js +877 -0
  495. data/lib/libv8/v8/tools/utils.py +96 -0
  496. data/lib/libv8/v8/tools/visual_studio/README.txt +12 -0
  497. data/lib/libv8/v8/tools/windows-tick-processor.bat +30 -0
  498. data/lib/libv8/version.rb +5 -0
  499. data/libv8.gemspec +36 -0
  500. metadata +578 -0
@@ -0,0 +1,252 @@
1
+ // Copyright 2011 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY 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
+
29
+ #ifndef V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
30
+ #define V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
31
+
32
+ namespace v8 {
33
+ namespace internal {
34
+
35
+ #ifdef V8_INTERPRETED_REGEXP
36
+ class RegExpMacroAssemblerMIPS: public RegExpMacroAssembler {
37
+ public:
38
+ RegExpMacroAssemblerMIPS();
39
+ virtual ~RegExpMacroAssemblerMIPS();
40
+ };
41
+ #else // V8_INTERPRETED_REGEXP
42
+ class RegExpMacroAssemblerMIPS: public NativeRegExpMacroAssembler {
43
+ public:
44
+ RegExpMacroAssemblerMIPS(Mode mode, int registers_to_save);
45
+ virtual ~RegExpMacroAssemblerMIPS();
46
+ virtual int stack_limit_slack();
47
+ virtual void AdvanceCurrentPosition(int by);
48
+ virtual void AdvanceRegister(int reg, int by);
49
+ virtual void Backtrack();
50
+ virtual void Bind(Label* label);
51
+ virtual void CheckAtStart(Label* on_at_start);
52
+ virtual void CheckCharacter(uint32_t c, Label* on_equal);
53
+ virtual void CheckCharacterAfterAnd(uint32_t c,
54
+ uint32_t mask,
55
+ Label* on_equal);
56
+ virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
57
+ virtual void CheckCharacterLT(uc16 limit, Label* on_less);
58
+ virtual void CheckCharacters(Vector<const uc16> str,
59
+ int cp_offset,
60
+ Label* on_failure,
61
+ bool check_end_of_string);
62
+ // A "greedy loop" is a loop that is both greedy and with a simple
63
+ // body. It has a particularly simple implementation.
64
+ virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
65
+ virtual void CheckNotAtStart(Label* on_not_at_start);
66
+ virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
67
+ virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
68
+ Label* on_no_match);
69
+ virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
70
+ virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
71
+ virtual void CheckNotCharacterAfterAnd(uint32_t c,
72
+ uint32_t mask,
73
+ Label* on_not_equal);
74
+ virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
75
+ uc16 minus,
76
+ uc16 mask,
77
+ Label* on_not_equal);
78
+ // Checks whether the given offset from the current position is before
79
+ // the end of the string.
80
+ virtual void CheckPosition(int cp_offset, Label* on_outside_input);
81
+ virtual bool CheckSpecialCharacterClass(uc16 type,
82
+ Label* on_no_match);
83
+ virtual void Fail();
84
+ virtual Handle<HeapObject> GetCode(Handle<String> source);
85
+ virtual void GoTo(Label* label);
86
+ virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
87
+ virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
88
+ virtual void IfRegisterEqPos(int reg, Label* if_eq);
89
+ virtual IrregexpImplementation Implementation();
90
+ virtual void LoadCurrentCharacter(int cp_offset,
91
+ Label* on_end_of_input,
92
+ bool check_bounds = true,
93
+ int characters = 1);
94
+ virtual void PopCurrentPosition();
95
+ virtual void PopRegister(int register_index);
96
+ virtual void PushBacktrack(Label* label);
97
+ virtual void PushCurrentPosition();
98
+ virtual void PushRegister(int register_index,
99
+ StackCheckFlag check_stack_limit);
100
+ virtual void ReadCurrentPositionFromRegister(int reg);
101
+ virtual void ReadStackPointerFromRegister(int reg);
102
+ virtual void SetCurrentPositionFromEnd(int by);
103
+ virtual void SetRegister(int register_index, int to);
104
+ virtual void Succeed();
105
+ virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
106
+ virtual void ClearRegisters(int reg_from, int reg_to);
107
+ virtual void WriteStackPointerToRegister(int reg);
108
+
109
+ // Called from RegExp if the stack-guard is triggered.
110
+ // If the code object is relocated, the return address is fixed before
111
+ // returning.
112
+ static int CheckStackGuardState(Address* return_address,
113
+ Code* re_code,
114
+ Address re_frame);
115
+ private:
116
+ // Offsets from frame_pointer() of function parameters and stored registers.
117
+ static const int kFramePointer = 0;
118
+
119
+ // Above the frame pointer - Stored registers and stack passed parameters.
120
+ // Registers s0 to s7, fp, and ra.
121
+ static const int kStoredRegisters = kFramePointer;
122
+ // Return address (stored from link register, read into pc on return).
123
+ static const int kReturnAddress = kStoredRegisters + 9 * kPointerSize;
124
+ static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
125
+ // Stack frame header.
126
+ static const int kStackFrameHeader = kReturnAddress + kPointerSize;
127
+ // Stack parameters placed by caller.
128
+ static const int kRegisterOutput = kStackFrameHeader + 20;
129
+ static const int kStackHighEnd = kRegisterOutput + kPointerSize;
130
+ static const int kDirectCall = kStackHighEnd + kPointerSize;
131
+ static const int kIsolate = kDirectCall + kPointerSize;
132
+
133
+ // Below the frame pointer.
134
+ // Register parameters stored by setup code.
135
+ static const int kInputEnd = kFramePointer - kPointerSize;
136
+ static const int kInputStart = kInputEnd - kPointerSize;
137
+ static const int kStartIndex = kInputStart - kPointerSize;
138
+ static const int kInputString = kStartIndex - kPointerSize;
139
+ // When adding local variables remember to push space for them in
140
+ // the frame in GetCode.
141
+ static const int kInputStartMinusOne = kInputString - kPointerSize;
142
+ static const int kAtStart = kInputStartMinusOne - kPointerSize;
143
+ // First register address. Following registers are below it on the stack.
144
+ static const int kRegisterZero = kAtStart - kPointerSize;
145
+
146
+ // Initial size of code buffer.
147
+ static const size_t kRegExpCodeSize = 1024;
148
+
149
+ // Load a number of characters at the given offset from the
150
+ // current position, into the current-character register.
151
+ void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
152
+
153
+ // Check whether preemption has been requested.
154
+ void CheckPreemption();
155
+
156
+ // Check whether we are exceeding the stack limit on the backtrack stack.
157
+ void CheckStackLimit();
158
+
159
+
160
+ // Generate a call to CheckStackGuardState.
161
+ void CallCheckStackGuardState(Register scratch);
162
+
163
+ // The ebp-relative location of a regexp register.
164
+ MemOperand register_location(int register_index);
165
+
166
+ // Register holding the current input position as negative offset from
167
+ // the end of the string.
168
+ inline Register current_input_offset() { return t2; }
169
+
170
+ // The register containing the current character after LoadCurrentCharacter.
171
+ inline Register current_character() { return t3; }
172
+
173
+ // Register holding address of the end of the input string.
174
+ inline Register end_of_input_address() { return t6; }
175
+
176
+ // Register holding the frame address. Local variables, parameters and
177
+ // regexp registers are addressed relative to this.
178
+ inline Register frame_pointer() { return fp; }
179
+
180
+ // The register containing the backtrack stack top. Provides a meaningful
181
+ // name to the register.
182
+ inline Register backtrack_stackpointer() { return t4; }
183
+
184
+ // Register holding pointer to the current code object.
185
+ inline Register code_pointer() { return t1; }
186
+
187
+ // Byte size of chars in the string to match (decided by the Mode argument).
188
+ inline int char_size() { return static_cast<int>(mode_); }
189
+
190
+ // Equivalent to a conditional branch to the label, unless the label
191
+ // is NULL, in which case it is a conditional Backtrack.
192
+ void BranchOrBacktrack(Label* to,
193
+ Condition condition,
194
+ Register rs,
195
+ const Operand& rt);
196
+
197
+ // Call and return internally in the generated code in a way that
198
+ // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
199
+ inline void SafeCall(Label* to,
200
+ Condition cond,
201
+ Register rs,
202
+ const Operand& rt);
203
+ inline void SafeReturn();
204
+ inline void SafeCallTarget(Label* name);
205
+
206
+ // Pushes the value of a register on the backtrack stack. Decrements the
207
+ // stack pointer by a word size and stores the register's value there.
208
+ inline void Push(Register source);
209
+
210
+ // Pops a value from the backtrack stack. Reads the word at the stack pointer
211
+ // and increments it by a word size.
212
+ inline void Pop(Register target);
213
+
214
+ // Calls a C function and cleans up the frame alignment done by
215
+ // by FrameAlign. The called function *is* allowed to trigger a garbage
216
+ // collection, but may not take more than four arguments (no arguments
217
+ // passed on the stack), and the first argument will be a pointer to the
218
+ // return address.
219
+ inline void CallCFunctionUsingStub(ExternalReference function,
220
+ int num_arguments);
221
+
222
+
223
+ MacroAssembler* masm_;
224
+
225
+ // Which mode to generate code for (ASCII or UC16).
226
+ Mode mode_;
227
+
228
+ // One greater than maximal register index actually used.
229
+ int num_registers_;
230
+
231
+ // Number of registers to output at the end (the saved registers
232
+ // are always 0..num_saved_registers_-1).
233
+ int num_saved_registers_;
234
+
235
+ // Labels used internally.
236
+ Label entry_label_;
237
+ Label start_label_;
238
+ Label success_label_;
239
+ Label backtrack_label_;
240
+ Label exit_label_;
241
+ Label check_preempt_label_;
242
+ Label stack_overflow_label_;
243
+ Label internal_failure_label_;
244
+ };
245
+
246
+ #endif // V8_INTERPRETED_REGEXP
247
+
248
+
249
+ }} // namespace v8::internal
250
+
251
+ #endif // V8_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
252
+
@@ -0,0 +1,2621 @@
1
+ // Copyright 2011 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY 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
+ #include <stdlib.h>
29
+ #include <math.h>
30
+ #include <limits.h>
31
+ #include <cstdarg>
32
+ #include "v8.h"
33
+
34
+ #if defined(V8_TARGET_ARCH_MIPS)
35
+
36
+ #include "disasm.h"
37
+ #include "assembler.h"
38
+ #include "globals.h" // Need the BitCast.
39
+ #include "mips/constants-mips.h"
40
+ #include "mips/simulator-mips.h"
41
+
42
+
43
+ // Only build the simulator if not compiling for real MIPS hardware.
44
+ #if defined(USE_SIMULATOR)
45
+
46
+ namespace v8 {
47
+ namespace internal {
48
+
49
+ // Utils functions.
50
+ bool HaveSameSign(int32_t a, int32_t b) {
51
+ return ((a ^ b) >= 0);
52
+ }
53
+
54
+
55
+ uint32_t get_fcsr_condition_bit(uint32_t cc) {
56
+ if (cc == 0) {
57
+ return 23;
58
+ } else {
59
+ return 24 + cc;
60
+ }
61
+ }
62
+
63
+
64
+ // This macro provides a platform independent use of sscanf. The reason for
65
+ // SScanF not being implemented in a platform independent was through
66
+ // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
67
+ // Library does not provide vsscanf.
68
+ #define SScanF sscanf // NOLINT
69
+
70
+ // The MipsDebugger class is used by the simulator while debugging simulated
71
+ // code.
72
+ class MipsDebugger {
73
+ public:
74
+ explicit MipsDebugger(Simulator* sim);
75
+ ~MipsDebugger();
76
+
77
+ void Stop(Instruction* instr);
78
+ void Debug();
79
+ // Print all registers with a nice formatting.
80
+ void PrintAllRegs();
81
+ void PrintAllRegsIncludingFPU();
82
+
83
+ private:
84
+ // We set the breakpoint code to 0xfffff to easily recognize it.
85
+ static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
86
+ static const Instr kNopInstr = 0x0;
87
+
88
+ Simulator* sim_;
89
+
90
+ int32_t GetRegisterValue(int regnum);
91
+ int32_t GetFPURegisterValueInt(int regnum);
92
+ int64_t GetFPURegisterValueLong(int regnum);
93
+ float GetFPURegisterValueFloat(int regnum);
94
+ double GetFPURegisterValueDouble(int regnum);
95
+ bool GetValue(const char* desc, int32_t* value);
96
+
97
+ // Set or delete a breakpoint. Returns true if successful.
98
+ bool SetBreakpoint(Instruction* breakpc);
99
+ bool DeleteBreakpoint(Instruction* breakpc);
100
+
101
+ // Undo and redo all breakpoints. This is needed to bracket disassembly and
102
+ // execution to skip past breakpoints when run from the debugger.
103
+ void UndoBreakpoints();
104
+ void RedoBreakpoints();
105
+ };
106
+
107
+ MipsDebugger::MipsDebugger(Simulator* sim) {
108
+ sim_ = sim;
109
+ }
110
+
111
+
112
+ MipsDebugger::~MipsDebugger() {
113
+ }
114
+
115
+
116
+ #ifdef GENERATED_CODE_COVERAGE
117
+ static FILE* coverage_log = NULL;
118
+
119
+
120
+ static void InitializeCoverage() {
121
+ char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
122
+ if (file_name != NULL) {
123
+ coverage_log = fopen(file_name, "aw+");
124
+ }
125
+ }
126
+
127
+
128
+ void MipsDebugger::Stop(Instruction* instr) {
129
+ UNIMPLEMENTED_MIPS();
130
+ char* str = reinterpret_cast<char*>(instr->InstructionBits());
131
+ if (strlen(str) > 0) {
132
+ if (coverage_log != NULL) {
133
+ fprintf(coverage_log, "%s\n", str);
134
+ fflush(coverage_log);
135
+ }
136
+ instr->SetInstructionBits(0x0); // Overwrite with nop.
137
+ }
138
+ sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
139
+ }
140
+
141
+
142
+ #else // GENERATED_CODE_COVERAGE
143
+
144
+ #define UNSUPPORTED() printf("Unsupported instruction.\n");
145
+
146
+ static void InitializeCoverage() {}
147
+
148
+
149
+ void MipsDebugger::Stop(Instruction* instr) {
150
+ const char* str = reinterpret_cast<char*>(instr->InstructionBits());
151
+ PrintF("Simulator hit %s\n", str);
152
+ sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
153
+ Debug();
154
+ }
155
+ #endif // GENERATED_CODE_COVERAGE
156
+
157
+
158
+ int32_t MipsDebugger::GetRegisterValue(int regnum) {
159
+ if (regnum == kNumSimuRegisters) {
160
+ return sim_->get_pc();
161
+ } else {
162
+ return sim_->get_register(regnum);
163
+ }
164
+ }
165
+
166
+
167
+ int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) {
168
+ if (regnum == kNumFPURegisters) {
169
+ return sim_->get_pc();
170
+ } else {
171
+ return sim_->get_fpu_register(regnum);
172
+ }
173
+ }
174
+
175
+
176
+ int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) {
177
+ if (regnum == kNumFPURegisters) {
178
+ return sim_->get_pc();
179
+ } else {
180
+ return sim_->get_fpu_register_long(regnum);
181
+ }
182
+ }
183
+
184
+
185
+ float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
186
+ if (regnum == kNumFPURegisters) {
187
+ return sim_->get_pc();
188
+ } else {
189
+ return sim_->get_fpu_register_float(regnum);
190
+ }
191
+ }
192
+
193
+
194
+ double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
195
+ if (regnum == kNumFPURegisters) {
196
+ return sim_->get_pc();
197
+ } else {
198
+ return sim_->get_fpu_register_double(regnum);
199
+ }
200
+ }
201
+
202
+
203
+ bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
204
+ int regnum = Registers::Number(desc);
205
+ int fpuregnum = FPURegisters::Number(desc);
206
+
207
+ if (regnum != kInvalidRegister) {
208
+ *value = GetRegisterValue(regnum);
209
+ return true;
210
+ } else if (fpuregnum != kInvalidFPURegister) {
211
+ *value = GetFPURegisterValueInt(fpuregnum);
212
+ return true;
213
+ } else if (strncmp(desc, "0x", 2) == 0) {
214
+ return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
215
+ } else {
216
+ return SScanF(desc, "%i", value) == 1;
217
+ }
218
+ return false;
219
+ }
220
+
221
+
222
+ bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
223
+ // Check if a breakpoint can be set. If not return without any side-effects.
224
+ if (sim_->break_pc_ != NULL) {
225
+ return false;
226
+ }
227
+
228
+ // Set the breakpoint.
229
+ sim_->break_pc_ = breakpc;
230
+ sim_->break_instr_ = breakpc->InstructionBits();
231
+ // Not setting the breakpoint instruction in the code itself. It will be set
232
+ // when the debugger shell continues.
233
+ return true;
234
+ }
235
+
236
+
237
+ bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
238
+ if (sim_->break_pc_ != NULL) {
239
+ sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
240
+ }
241
+
242
+ sim_->break_pc_ = NULL;
243
+ sim_->break_instr_ = 0;
244
+ return true;
245
+ }
246
+
247
+
248
+ void MipsDebugger::UndoBreakpoints() {
249
+ if (sim_->break_pc_ != NULL) {
250
+ sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
251
+ }
252
+ }
253
+
254
+
255
+ void MipsDebugger::RedoBreakpoints() {
256
+ if (sim_->break_pc_ != NULL) {
257
+ sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
258
+ }
259
+ }
260
+
261
+
262
+ void MipsDebugger::PrintAllRegs() {
263
+ #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
264
+
265
+ PrintF("\n");
266
+ // at, v0, a0.
267
+ PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
268
+ REG_INFO(1), REG_INFO(2), REG_INFO(4));
269
+ // v1, a1.
270
+ PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
271
+ "", REG_INFO(3), REG_INFO(5));
272
+ // a2.
273
+ PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
274
+ // a3.
275
+ PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
276
+ PrintF("\n");
277
+ // t0-t7, s0-s7
278
+ for (int i = 0; i < 8; i++) {
279
+ PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
280
+ REG_INFO(8+i), REG_INFO(16+i));
281
+ }
282
+ PrintF("\n");
283
+ // t8, k0, LO.
284
+ PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
285
+ REG_INFO(24), REG_INFO(26), REG_INFO(32));
286
+ // t9, k1, HI.
287
+ PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
288
+ REG_INFO(25), REG_INFO(27), REG_INFO(33));
289
+ // sp, fp, gp.
290
+ PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
291
+ REG_INFO(29), REG_INFO(30), REG_INFO(28));
292
+ // pc.
293
+ PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
294
+ REG_INFO(31), REG_INFO(34));
295
+
296
+ #undef REG_INFO
297
+ #undef FPU_REG_INFO
298
+ }
299
+
300
+
301
+ void MipsDebugger::PrintAllRegsIncludingFPU() {
302
+ #define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
303
+ GetFPURegisterValueInt(n+1), \
304
+ GetFPURegisterValueInt(n), \
305
+ GetFPURegisterValueDouble(n)
306
+
307
+ PrintAllRegs();
308
+
309
+ PrintF("\n\n");
310
+ // f0, f1, f2, ... f31.
311
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
312
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
313
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
314
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
315
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
316
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
317
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
318
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
319
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
320
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
321
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
322
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
323
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
324
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
325
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
326
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
327
+
328
+ #undef REG_INFO
329
+ #undef FPU_REG_INFO
330
+ }
331
+
332
+
333
+ void MipsDebugger::Debug() {
334
+ intptr_t last_pc = -1;
335
+ bool done = false;
336
+
337
+ #define COMMAND_SIZE 63
338
+ #define ARG_SIZE 255
339
+
340
+ #define STR(a) #a
341
+ #define XSTR(a) STR(a)
342
+
343
+ char cmd[COMMAND_SIZE + 1];
344
+ char arg1[ARG_SIZE + 1];
345
+ char arg2[ARG_SIZE + 1];
346
+ char* argv[3] = { cmd, arg1, arg2 };
347
+
348
+ // Make sure to have a proper terminating character if reaching the limit.
349
+ cmd[COMMAND_SIZE] = 0;
350
+ arg1[ARG_SIZE] = 0;
351
+ arg2[ARG_SIZE] = 0;
352
+
353
+ // Undo all set breakpoints while running in the debugger shell. This will
354
+ // make them invisible to all commands.
355
+ UndoBreakpoints();
356
+
357
+ while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
358
+ if (last_pc != sim_->get_pc()) {
359
+ disasm::NameConverter converter;
360
+ disasm::Disassembler dasm(converter);
361
+ // Use a reasonably large buffer.
362
+ v8::internal::EmbeddedVector<char, 256> buffer;
363
+ dasm.InstructionDecode(buffer,
364
+ reinterpret_cast<byte*>(sim_->get_pc()));
365
+ PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
366
+ last_pc = sim_->get_pc();
367
+ }
368
+ char* line = ReadLine("sim> ");
369
+ if (line == NULL) {
370
+ break;
371
+ } else {
372
+ // Use sscanf to parse the individual parts of the command line. At the
373
+ // moment no command expects more than two parameters.
374
+ int argc = SScanF(line,
375
+ "%" XSTR(COMMAND_SIZE) "s "
376
+ "%" XSTR(ARG_SIZE) "s "
377
+ "%" XSTR(ARG_SIZE) "s",
378
+ cmd, arg1, arg2);
379
+ if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
380
+ Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
381
+ if (!(instr->IsTrap()) ||
382
+ instr->InstructionBits() == rtCallRedirInstr) {
383
+ sim_->InstructionDecode(
384
+ reinterpret_cast<Instruction*>(sim_->get_pc()));
385
+ } else {
386
+ // Allow si to jump over generated breakpoints.
387
+ PrintF("/!\\ Jumping over generated breakpoint.\n");
388
+ sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
389
+ }
390
+ } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
391
+ // Execute the one instruction we broke at with breakpoints disabled.
392
+ sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
393
+ // Leave the debugger shell.
394
+ done = true;
395
+ } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
396
+ if (argc == 2) {
397
+ int32_t value;
398
+ float fvalue;
399
+ if (strcmp(arg1, "all") == 0) {
400
+ PrintAllRegs();
401
+ } else if (strcmp(arg1, "allf") == 0) {
402
+ PrintAllRegsIncludingFPU();
403
+ } else {
404
+ int regnum = Registers::Number(arg1);
405
+ int fpuregnum = FPURegisters::Number(arg1);
406
+
407
+ if (regnum != kInvalidRegister) {
408
+ value = GetRegisterValue(regnum);
409
+ PrintF("%s: 0x%08x %d \n", arg1, value, value);
410
+ } else if (fpuregnum != kInvalidFPURegister) {
411
+ if (fpuregnum % 2 == 1) {
412
+ value = GetFPURegisterValueInt(fpuregnum);
413
+ fvalue = GetFPURegisterValueFloat(fpuregnum);
414
+ PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
415
+ } else {
416
+ double dfvalue;
417
+ int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
418
+ int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
419
+ dfvalue = GetFPURegisterValueDouble(fpuregnum);
420
+ PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
421
+ FPURegisters::Name(fpuregnum+1),
422
+ FPURegisters::Name(fpuregnum),
423
+ lvalue1,
424
+ lvalue2,
425
+ dfvalue);
426
+ }
427
+ } else {
428
+ PrintF("%s unrecognized\n", arg1);
429
+ }
430
+ }
431
+ } else {
432
+ if (argc == 3) {
433
+ if (strcmp(arg2, "single") == 0) {
434
+ int32_t value;
435
+ float fvalue;
436
+ int fpuregnum = FPURegisters::Number(arg1);
437
+
438
+ if (fpuregnum != kInvalidFPURegister) {
439
+ value = GetFPURegisterValueInt(fpuregnum);
440
+ fvalue = GetFPURegisterValueFloat(fpuregnum);
441
+ PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
442
+ } else {
443
+ PrintF("%s unrecognized\n", arg1);
444
+ }
445
+ } else {
446
+ PrintF("print <fpu register> single\n");
447
+ }
448
+ } else {
449
+ PrintF("print <register> or print <fpu register> single\n");
450
+ }
451
+ }
452
+ } else if ((strcmp(cmd, "po") == 0)
453
+ || (strcmp(cmd, "printobject") == 0)) {
454
+ if (argc == 2) {
455
+ int32_t value;
456
+ if (GetValue(arg1, &value)) {
457
+ Object* obj = reinterpret_cast<Object*>(value);
458
+ PrintF("%s: \n", arg1);
459
+ #ifdef DEBUG
460
+ obj->PrintLn();
461
+ #else
462
+ obj->ShortPrint();
463
+ PrintF("\n");
464
+ #endif
465
+ } else {
466
+ PrintF("%s unrecognized\n", arg1);
467
+ }
468
+ } else {
469
+ PrintF("printobject <value>\n");
470
+ }
471
+ } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
472
+ int32_t* cur = NULL;
473
+ int32_t* end = NULL;
474
+ int next_arg = 1;
475
+
476
+ if (strcmp(cmd, "stack") == 0) {
477
+ cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
478
+ } else { // Command "mem".
479
+ int32_t value;
480
+ if (!GetValue(arg1, &value)) {
481
+ PrintF("%s unrecognized\n", arg1);
482
+ continue;
483
+ }
484
+ cur = reinterpret_cast<int32_t*>(value);
485
+ next_arg++;
486
+ }
487
+
488
+ int32_t words;
489
+ if (argc == next_arg) {
490
+ words = 10;
491
+ } else if (argc == next_arg + 1) {
492
+ if (!GetValue(argv[next_arg], &words)) {
493
+ words = 10;
494
+ }
495
+ }
496
+ end = cur + words;
497
+
498
+ while (cur < end) {
499
+ PrintF(" 0x%08x: 0x%08x %10d",
500
+ reinterpret_cast<intptr_t>(cur), *cur, *cur);
501
+ HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
502
+ int value = *cur;
503
+ Heap* current_heap = v8::internal::Isolate::Current()->heap();
504
+ if (current_heap->Contains(obj) || ((value & 1) == 0)) {
505
+ PrintF(" (");
506
+ if ((value & 1) == 0) {
507
+ PrintF("smi %d", value / 2);
508
+ } else {
509
+ obj->ShortPrint();
510
+ }
511
+ PrintF(")");
512
+ }
513
+ PrintF("\n");
514
+ cur++;
515
+ }
516
+
517
+ } else if ((strcmp(cmd, "disasm") == 0) ||
518
+ (strcmp(cmd, "dpc") == 0) ||
519
+ (strcmp(cmd, "di") == 0)) {
520
+ disasm::NameConverter converter;
521
+ disasm::Disassembler dasm(converter);
522
+ // Use a reasonably large buffer.
523
+ v8::internal::EmbeddedVector<char, 256> buffer;
524
+
525
+ byte* cur = NULL;
526
+ byte* end = NULL;
527
+
528
+ if (argc == 1) {
529
+ cur = reinterpret_cast<byte*>(sim_->get_pc());
530
+ end = cur + (10 * Instruction::kInstrSize);
531
+ } else if (argc == 2) {
532
+ int regnum = Registers::Number(arg1);
533
+ if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
534
+ // The argument is an address or a register name.
535
+ int32_t value;
536
+ if (GetValue(arg1, &value)) {
537
+ cur = reinterpret_cast<byte*>(value);
538
+ // Disassemble 10 instructions at <arg1>.
539
+ end = cur + (10 * Instruction::kInstrSize);
540
+ }
541
+ } else {
542
+ // The argument is the number of instructions.
543
+ int32_t value;
544
+ if (GetValue(arg1, &value)) {
545
+ cur = reinterpret_cast<byte*>(sim_->get_pc());
546
+ // Disassemble <arg1> instructions.
547
+ end = cur + (value * Instruction::kInstrSize);
548
+ }
549
+ }
550
+ } else {
551
+ int32_t value1;
552
+ int32_t value2;
553
+ if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
554
+ cur = reinterpret_cast<byte*>(value1);
555
+ end = cur + (value2 * Instruction::kInstrSize);
556
+ }
557
+ }
558
+
559
+ while (cur < end) {
560
+ dasm.InstructionDecode(buffer, cur);
561
+ PrintF(" 0x%08x %s\n",
562
+ reinterpret_cast<intptr_t>(cur), buffer.start());
563
+ cur += Instruction::kInstrSize;
564
+ }
565
+ } else if (strcmp(cmd, "gdb") == 0) {
566
+ PrintF("relinquishing control to gdb\n");
567
+ v8::internal::OS::DebugBreak();
568
+ PrintF("regaining control from gdb\n");
569
+ } else if (strcmp(cmd, "break") == 0) {
570
+ if (argc == 2) {
571
+ int32_t value;
572
+ if (GetValue(arg1, &value)) {
573
+ if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
574
+ PrintF("setting breakpoint failed\n");
575
+ }
576
+ } else {
577
+ PrintF("%s unrecognized\n", arg1);
578
+ }
579
+ } else {
580
+ PrintF("break <address>\n");
581
+ }
582
+ } else if (strcmp(cmd, "del") == 0) {
583
+ if (!DeleteBreakpoint(NULL)) {
584
+ PrintF("deleting breakpoint failed\n");
585
+ }
586
+ } else if (strcmp(cmd, "flags") == 0) {
587
+ PrintF("No flags on MIPS !\n");
588
+ } else if (strcmp(cmd, "unstop") == 0) {
589
+ PrintF("Unstop command not implemented on MIPS.");
590
+ } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
591
+ // Print registers and disassemble.
592
+ PrintAllRegs();
593
+ PrintF("\n");
594
+
595
+ disasm::NameConverter converter;
596
+ disasm::Disassembler dasm(converter);
597
+ // Use a reasonably large buffer.
598
+ v8::internal::EmbeddedVector<char, 256> buffer;
599
+
600
+ byte* cur = NULL;
601
+ byte* end = NULL;
602
+
603
+ if (argc == 1) {
604
+ cur = reinterpret_cast<byte*>(sim_->get_pc());
605
+ end = cur + (10 * Instruction::kInstrSize);
606
+ } else if (argc == 2) {
607
+ int32_t value;
608
+ if (GetValue(arg1, &value)) {
609
+ cur = reinterpret_cast<byte*>(value);
610
+ // no length parameter passed, assume 10 instructions
611
+ end = cur + (10 * Instruction::kInstrSize);
612
+ }
613
+ } else {
614
+ int32_t value1;
615
+ int32_t value2;
616
+ if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
617
+ cur = reinterpret_cast<byte*>(value1);
618
+ end = cur + (value2 * Instruction::kInstrSize);
619
+ }
620
+ }
621
+
622
+ while (cur < end) {
623
+ dasm.InstructionDecode(buffer, cur);
624
+ PrintF(" 0x%08x %s\n",
625
+ reinterpret_cast<intptr_t>(cur), buffer.start());
626
+ cur += Instruction::kInstrSize;
627
+ }
628
+ } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
629
+ PrintF("cont\n");
630
+ PrintF(" continue execution (alias 'c')\n");
631
+ PrintF("stepi\n");
632
+ PrintF(" step one instruction (alias 'si')\n");
633
+ PrintF("print <register>\n");
634
+ PrintF(" print register content (alias 'p')\n");
635
+ PrintF(" use register name 'all' to print all registers\n");
636
+ PrintF("printobject <register>\n");
637
+ PrintF(" print an object from a register (alias 'po')\n");
638
+ PrintF("stack [<words>]\n");
639
+ PrintF(" dump stack content, default dump 10 words)\n");
640
+ PrintF("mem <address> [<words>]\n");
641
+ PrintF(" dump memory content, default dump 10 words)\n");
642
+ PrintF("flags\n");
643
+ PrintF(" print flags\n");
644
+ PrintF("disasm [<instructions>]\n");
645
+ PrintF("disasm [<address/register>]\n");
646
+ PrintF("disasm [[<address/register>] <instructions>]\n");
647
+ PrintF(" disassemble code, default is 10 instructions\n");
648
+ PrintF(" from pc (alias 'di')\n");
649
+ PrintF("gdb\n");
650
+ PrintF(" enter gdb\n");
651
+ PrintF("break <address>\n");
652
+ PrintF(" set a break point on the address\n");
653
+ PrintF("del\n");
654
+ PrintF(" delete the breakpoint\n");
655
+ PrintF("unstop\n");
656
+ PrintF(" ignore the stop instruction at the current location");
657
+ PrintF(" from now on\n");
658
+ } else {
659
+ PrintF("Unknown command: %s\n", cmd);
660
+ }
661
+ }
662
+ DeleteArray(line);
663
+ }
664
+
665
+ // Add all the breakpoints back to stop execution and enter the debugger
666
+ // shell when hit.
667
+ RedoBreakpoints();
668
+
669
+ #undef COMMAND_SIZE
670
+ #undef ARG_SIZE
671
+
672
+ #undef STR
673
+ #undef XSTR
674
+ }
675
+
676
+
677
+ static bool ICacheMatch(void* one, void* two) {
678
+ ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
679
+ ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
680
+ return one == two;
681
+ }
682
+
683
+
684
+ static uint32_t ICacheHash(void* key) {
685
+ return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
686
+ }
687
+
688
+
689
+ static bool AllOnOnePage(uintptr_t start, int size) {
690
+ intptr_t start_page = (start & ~CachePage::kPageMask);
691
+ intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
692
+ return start_page == end_page;
693
+ }
694
+
695
+
696
+ void Simulator::FlushICache(v8::internal::HashMap* i_cache,
697
+ void* start_addr,
698
+ size_t size) {
699
+ intptr_t start = reinterpret_cast<intptr_t>(start_addr);
700
+ int intra_line = (start & CachePage::kLineMask);
701
+ start -= intra_line;
702
+ size += intra_line;
703
+ size = ((size - 1) | CachePage::kLineMask) + 1;
704
+ int offset = (start & CachePage::kPageMask);
705
+ while (!AllOnOnePage(start, size - 1)) {
706
+ int bytes_to_flush = CachePage::kPageSize - offset;
707
+ FlushOnePage(i_cache, start, bytes_to_flush);
708
+ start += bytes_to_flush;
709
+ size -= bytes_to_flush;
710
+ ASSERT_EQ(0, start & CachePage::kPageMask);
711
+ offset = 0;
712
+ }
713
+ if (size != 0) {
714
+ FlushOnePage(i_cache, start, size);
715
+ }
716
+ }
717
+
718
+
719
+ CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
720
+ v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
721
+ ICacheHash(page),
722
+ true);
723
+ if (entry->value == NULL) {
724
+ CachePage* new_page = new CachePage();
725
+ entry->value = new_page;
726
+ }
727
+ return reinterpret_cast<CachePage*>(entry->value);
728
+ }
729
+
730
+
731
+ // Flush from start up to and not including start + size.
732
+ void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
733
+ intptr_t start,
734
+ int size) {
735
+ ASSERT(size <= CachePage::kPageSize);
736
+ ASSERT(AllOnOnePage(start, size - 1));
737
+ ASSERT((start & CachePage::kLineMask) == 0);
738
+ ASSERT((size & CachePage::kLineMask) == 0);
739
+ void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
740
+ int offset = (start & CachePage::kPageMask);
741
+ CachePage* cache_page = GetCachePage(i_cache, page);
742
+ char* valid_bytemap = cache_page->ValidityByte(offset);
743
+ memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
744
+ }
745
+
746
+
747
+ void Simulator::CheckICache(v8::internal::HashMap* i_cache,
748
+ Instruction* instr) {
749
+ intptr_t address = reinterpret_cast<intptr_t>(instr);
750
+ void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
751
+ void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
752
+ int offset = (address & CachePage::kPageMask);
753
+ CachePage* cache_page = GetCachePage(i_cache, page);
754
+ char* cache_valid_byte = cache_page->ValidityByte(offset);
755
+ bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
756
+ char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
757
+ if (cache_hit) {
758
+ // Check that the data in memory matches the contents of the I-cache.
759
+ CHECK(memcmp(reinterpret_cast<void*>(instr),
760
+ cache_page->CachedData(offset),
761
+ Instruction::kInstrSize) == 0);
762
+ } else {
763
+ // Cache miss. Load memory into the cache.
764
+ memcpy(cached_line, line, CachePage::kLineLength);
765
+ *cache_valid_byte = CachePage::LINE_VALID;
766
+ }
767
+ }
768
+
769
+
770
+ void Simulator::Initialize(Isolate* isolate) {
771
+ if (isolate->simulator_initialized()) return;
772
+ isolate->set_simulator_initialized(true);
773
+ ::v8::internal::ExternalReference::set_redirector(isolate,
774
+ &RedirectExternalReference);
775
+ }
776
+
777
+
778
+ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
779
+ i_cache_ = isolate_->simulator_i_cache();
780
+ if (i_cache_ == NULL) {
781
+ i_cache_ = new v8::internal::HashMap(&ICacheMatch);
782
+ isolate_->set_simulator_i_cache(i_cache_);
783
+ }
784
+ Initialize(isolate);
785
+ // Setup simulator support first. Some of this information is needed to
786
+ // setup the architecture state.
787
+ stack_ = reinterpret_cast<char*>(malloc(stack_size_));
788
+ pc_modified_ = false;
789
+ icount_ = 0;
790
+ break_count_ = 0;
791
+ break_pc_ = NULL;
792
+ break_instr_ = 0;
793
+
794
+ // Setup architecture state.
795
+ // All registers are initialized to zero to start with.
796
+ for (int i = 0; i < kNumSimuRegisters; i++) {
797
+ registers_[i] = 0;
798
+ }
799
+ for (int i = 0; i < kNumFPURegisters; i++) {
800
+ FPUregisters_[i] = 0;
801
+ }
802
+ FCSR_ = 0;
803
+
804
+ // The sp is initialized to point to the bottom (high address) of the
805
+ // allocated stack area. To be safe in potential stack underflows we leave
806
+ // some buffer below.
807
+ registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
808
+ // The ra and pc are initialized to a known bad value that will cause an
809
+ // access violation if the simulator ever tries to execute it.
810
+ registers_[pc] = bad_ra;
811
+ registers_[ra] = bad_ra;
812
+ InitializeCoverage();
813
+ for (int i = 0; i < kNumExceptions; i++) {
814
+ exceptions[i] = 0;
815
+ }
816
+ }
817
+
818
+
819
+ // When the generated code calls an external reference we need to catch that in
820
+ // the simulator. The external reference will be a function compiled for the
821
+ // host architecture. We need to call that function instead of trying to
822
+ // execute it with the simulator. We do that by redirecting the external
823
+ // reference to a swi (software-interrupt) instruction that is handled by
824
+ // the simulator. We write the original destination of the jump just at a known
825
+ // offset from the swi instruction so the simulator knows what to call.
826
+ class Redirection {
827
+ public:
828
+ Redirection(void* external_function, ExternalReference::Type type)
829
+ : external_function_(external_function),
830
+ swi_instruction_(rtCallRedirInstr),
831
+ type_(type),
832
+ next_(NULL) {
833
+ Isolate* isolate = Isolate::Current();
834
+ next_ = isolate->simulator_redirection();
835
+ Simulator::current(isolate)->
836
+ FlushICache(isolate->simulator_i_cache(),
837
+ reinterpret_cast<void*>(&swi_instruction_),
838
+ Instruction::kInstrSize);
839
+ isolate->set_simulator_redirection(this);
840
+ }
841
+
842
+ void* address_of_swi_instruction() {
843
+ return reinterpret_cast<void*>(&swi_instruction_);
844
+ }
845
+
846
+ void* external_function() { return external_function_; }
847
+ ExternalReference::Type type() { return type_; }
848
+
849
+ static Redirection* Get(void* external_function,
850
+ ExternalReference::Type type) {
851
+ Isolate* isolate = Isolate::Current();
852
+ Redirection* current = isolate->simulator_redirection();
853
+ for (; current != NULL; current = current->next_) {
854
+ if (current->external_function_ == external_function) return current;
855
+ }
856
+ return new Redirection(external_function, type);
857
+ }
858
+
859
+ static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
860
+ char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
861
+ char* addr_of_redirection =
862
+ addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
863
+ return reinterpret_cast<Redirection*>(addr_of_redirection);
864
+ }
865
+
866
+ private:
867
+ void* external_function_;
868
+ uint32_t swi_instruction_;
869
+ ExternalReference::Type type_;
870
+ Redirection* next_;
871
+ };
872
+
873
+
874
+ void* Simulator::RedirectExternalReference(void* external_function,
875
+ ExternalReference::Type type) {
876
+ Redirection* redirection = Redirection::Get(external_function, type);
877
+ return redirection->address_of_swi_instruction();
878
+ }
879
+
880
+
881
+ // Get the active Simulator for the current thread.
882
+ Simulator* Simulator::current(Isolate* isolate) {
883
+ v8::internal::Isolate::PerIsolateThreadData* isolate_data =
884
+ isolate->FindOrAllocatePerThreadDataForThisThread();
885
+ ASSERT(isolate_data != NULL);
886
+ ASSERT(isolate_data != NULL);
887
+
888
+ Simulator* sim = isolate_data->simulator();
889
+ if (sim == NULL) {
890
+ // TODO(146): delete the simulator object when a thread/isolate goes away.
891
+ sim = new Simulator(isolate);
892
+ isolate_data->set_simulator(sim);
893
+ }
894
+ return sim;
895
+ }
896
+
897
+
898
+ // Sets the register in the architecture state. It will also deal with updating
899
+ // Simulator internal state for special registers such as PC.
900
+ void Simulator::set_register(int reg, int32_t value) {
901
+ ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
902
+ if (reg == pc) {
903
+ pc_modified_ = true;
904
+ }
905
+
906
+ // Zero register always holds 0.
907
+ registers_[reg] = (reg == 0) ? 0 : value;
908
+ }
909
+
910
+
911
+ void Simulator::set_fpu_register(int fpureg, int32_t value) {
912
+ ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
913
+ FPUregisters_[fpureg] = value;
914
+ }
915
+
916
+
917
+ void Simulator::set_fpu_register_float(int fpureg, float value) {
918
+ ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
919
+ *BitCast<float*>(&FPUregisters_[fpureg]) = value;
920
+ }
921
+
922
+
923
+ void Simulator::set_fpu_register_double(int fpureg, double value) {
924
+ ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
925
+ *BitCast<double*>(&FPUregisters_[fpureg]) = value;
926
+ }
927
+
928
+
929
+ // Get the register from the architecture state. This function does handle
930
+ // the special case of accessing the PC register.
931
+ int32_t Simulator::get_register(int reg) const {
932
+ ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
933
+ if (reg == 0)
934
+ return 0;
935
+ else
936
+ return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
937
+ }
938
+
939
+
940
+ int32_t Simulator::get_fpu_register(int fpureg) const {
941
+ ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
942
+ return FPUregisters_[fpureg];
943
+ }
944
+
945
+
946
+ int64_t Simulator::get_fpu_register_long(int fpureg) const {
947
+ ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
948
+ return *BitCast<int64_t*>(
949
+ const_cast<int32_t*>(&FPUregisters_[fpureg]));
950
+ }
951
+
952
+
953
+ float Simulator::get_fpu_register_float(int fpureg) const {
954
+ ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
955
+ return *BitCast<float*>(
956
+ const_cast<int32_t*>(&FPUregisters_[fpureg]));
957
+ }
958
+
959
+
960
+ double Simulator::get_fpu_register_double(int fpureg) const {
961
+ ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
962
+ return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
963
+ }
964
+
965
+
966
+ // For use in calls that take two double values, constructed either
967
+ // from a0-a3 or f12 and f14.
968
+ void Simulator::GetFpArgs(double* x, double* y) {
969
+ if (!IsMipsSoftFloatABI) {
970
+ *x = get_fpu_register_double(12);
971
+ *y = get_fpu_register_double(14);
972
+ } else {
973
+ // We use a char buffer to get around the strict-aliasing rules which
974
+ // otherwise allow the compiler to optimize away the copy.
975
+ char buffer[sizeof(*x)];
976
+ int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
977
+
978
+ // Registers a0 and a1 -> x.
979
+ reg_buffer[0] = get_register(a0);
980
+ reg_buffer[1] = get_register(a1);
981
+ memcpy(x, buffer, sizeof(buffer));
982
+
983
+ // Registers a2 and a3 -> y.
984
+ reg_buffer[0] = get_register(a2);
985
+ reg_buffer[1] = get_register(a3);
986
+ memcpy(y, buffer, sizeof(buffer));
987
+ }
988
+ }
989
+
990
+
991
+ // For use in calls that take one double value, constructed either
992
+ // from a0 and a1 or f12.
993
+ void Simulator::GetFpArgs(double* x) {
994
+ if (!IsMipsSoftFloatABI) {
995
+ *x = get_fpu_register_double(12);
996
+ } else {
997
+ // We use a char buffer to get around the strict-aliasing rules which
998
+ // otherwise allow the compiler to optimize away the copy.
999
+ char buffer[sizeof(*x)];
1000
+ int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1001
+ // Registers a0 and a1 -> x.
1002
+ reg_buffer[0] = get_register(a0);
1003
+ reg_buffer[1] = get_register(a1);
1004
+ memcpy(x, buffer, sizeof(buffer));
1005
+ }
1006
+ }
1007
+
1008
+
1009
+ // For use in calls that take one double value constructed either
1010
+ // from a0 and a1 or f12 and one integer value.
1011
+ void Simulator::GetFpArgs(double* x, int32_t* y) {
1012
+ if (!IsMipsSoftFloatABI) {
1013
+ *x = get_fpu_register_double(12);
1014
+ *y = get_register(a2);
1015
+ } else {
1016
+ // We use a char buffer to get around the strict-aliasing rules which
1017
+ // otherwise allow the compiler to optimize away the copy.
1018
+ char buffer[sizeof(*x)];
1019
+ int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1020
+ // Registers 0 and 1 -> x.
1021
+ reg_buffer[0] = get_register(a0);
1022
+ reg_buffer[1] = get_register(a1);
1023
+ memcpy(x, buffer, sizeof(buffer));
1024
+
1025
+ // Register 2 -> y.
1026
+ reg_buffer[0] = get_register(a2);
1027
+ memcpy(y, buffer, sizeof(*y));
1028
+ }
1029
+ }
1030
+
1031
+
1032
+ // The return value is either in v0/v1 or f0.
1033
+ void Simulator::SetFpResult(const double& result) {
1034
+ if (!IsMipsSoftFloatABI) {
1035
+ set_fpu_register_double(0, result);
1036
+ } else {
1037
+ char buffer[2 * sizeof(registers_[0])];
1038
+ int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1039
+ memcpy(buffer, &result, sizeof(buffer));
1040
+ // Copy result to v0 and v1.
1041
+ set_register(v0, reg_buffer[0]);
1042
+ set_register(v1, reg_buffer[1]);
1043
+ }
1044
+ }
1045
+
1046
+
1047
+ // Helper functions for setting and testing the FCSR register's bits.
1048
+ void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1049
+ if (value) {
1050
+ FCSR_ |= (1 << cc);
1051
+ } else {
1052
+ FCSR_ &= ~(1 << cc);
1053
+ }
1054
+ }
1055
+
1056
+
1057
+ bool Simulator::test_fcsr_bit(uint32_t cc) {
1058
+ return FCSR_ & (1 << cc);
1059
+ }
1060
+
1061
+
1062
+ // Sets the rounding error codes in FCSR based on the result of the rounding.
1063
+ // Returns true if the operation was invalid.
1064
+ bool Simulator::set_fcsr_round_error(double original, double rounded) {
1065
+ if (!isfinite(original) ||
1066
+ rounded > LONG_MAX ||
1067
+ rounded < LONG_MIN) {
1068
+ set_fcsr_bit(6, true); // Invalid operation.
1069
+ return true;
1070
+ } else if (original != static_cast<double>(rounded)) {
1071
+ set_fcsr_bit(2, true); // Inexact.
1072
+ }
1073
+ return false;
1074
+ }
1075
+
1076
+
1077
+ // Raw access to the PC register.
1078
+ void Simulator::set_pc(int32_t value) {
1079
+ pc_modified_ = true;
1080
+ registers_[pc] = value;
1081
+ }
1082
+
1083
+
1084
+ bool Simulator::has_bad_pc() const {
1085
+ return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1086
+ }
1087
+
1088
+
1089
+ // Raw access to the PC register without the special adjustment when reading.
1090
+ int32_t Simulator::get_pc() const {
1091
+ return registers_[pc];
1092
+ }
1093
+
1094
+
1095
+ // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an
1096
+ // interrupt is caused. On others it does a funky rotation thing. For now we
1097
+ // simply disallow unaligned reads, but at some point we may want to move to
1098
+ // emulating the rotate behaviour. Note that simulator runs have the runtime
1099
+ // system running directly on the host system and only generated code is
1100
+ // executed in the simulator. Since the host is typically IA32 we will not
1101
+ // get the correct MIPS-like behaviour on unaligned accesses.
1102
+
1103
+ int Simulator::ReadW(int32_t addr, Instruction* instr) {
1104
+ if (addr >=0 && addr < 0x400) {
1105
+ // This has to be a NULL-dereference, drop into debugger.
1106
+ MipsDebugger dbg(this);
1107
+ dbg.Debug();
1108
+ }
1109
+ if ((addr & kPointerAlignmentMask) == 0) {
1110
+ intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1111
+ return *ptr;
1112
+ }
1113
+ PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1114
+ addr,
1115
+ reinterpret_cast<intptr_t>(instr));
1116
+ MipsDebugger dbg(this);
1117
+ dbg.Debug();
1118
+ return 0;
1119
+ }
1120
+
1121
+
1122
+ void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1123
+ if (addr >= 0 && addr < 0x400) {
1124
+ // This has to be a NULL-dereference, drop into debugger.
1125
+ MipsDebugger dbg(this);
1126
+ dbg.Debug();
1127
+ }
1128
+ if ((addr & kPointerAlignmentMask) == 0) {
1129
+ intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1130
+ *ptr = value;
1131
+ return;
1132
+ }
1133
+ PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1134
+ addr,
1135
+ reinterpret_cast<intptr_t>(instr));
1136
+ MipsDebugger dbg(this);
1137
+ dbg.Debug();
1138
+ }
1139
+
1140
+
1141
+ double Simulator::ReadD(int32_t addr, Instruction* instr) {
1142
+ if ((addr & kDoubleAlignmentMask) == 0) {
1143
+ double* ptr = reinterpret_cast<double*>(addr);
1144
+ return *ptr;
1145
+ }
1146
+ PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1147
+ addr,
1148
+ reinterpret_cast<intptr_t>(instr));
1149
+ OS::Abort();
1150
+ return 0;
1151
+ }
1152
+
1153
+
1154
+ void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
1155
+ if ((addr & kDoubleAlignmentMask) == 0) {
1156
+ double* ptr = reinterpret_cast<double*>(addr);
1157
+ *ptr = value;
1158
+ return;
1159
+ }
1160
+ PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1161
+ addr,
1162
+ reinterpret_cast<intptr_t>(instr));
1163
+ OS::Abort();
1164
+ }
1165
+
1166
+
1167
+ uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1168
+ if ((addr & 1) == 0) {
1169
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1170
+ return *ptr;
1171
+ }
1172
+ PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1173
+ addr,
1174
+ reinterpret_cast<intptr_t>(instr));
1175
+ OS::Abort();
1176
+ return 0;
1177
+ }
1178
+
1179
+
1180
+ int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1181
+ if ((addr & 1) == 0) {
1182
+ int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1183
+ return *ptr;
1184
+ }
1185
+ PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1186
+ addr,
1187
+ reinterpret_cast<intptr_t>(instr));
1188
+ OS::Abort();
1189
+ return 0;
1190
+ }
1191
+
1192
+
1193
+ void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1194
+ if ((addr & 1) == 0) {
1195
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1196
+ *ptr = value;
1197
+ return;
1198
+ }
1199
+ PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1200
+ addr,
1201
+ reinterpret_cast<intptr_t>(instr));
1202
+ OS::Abort();
1203
+ }
1204
+
1205
+
1206
+ void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1207
+ if ((addr & 1) == 0) {
1208
+ int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1209
+ *ptr = value;
1210
+ return;
1211
+ }
1212
+ PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1213
+ addr,
1214
+ reinterpret_cast<intptr_t>(instr));
1215
+ OS::Abort();
1216
+ }
1217
+
1218
+
1219
+ uint32_t Simulator::ReadBU(int32_t addr) {
1220
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1221
+ return *ptr & 0xff;
1222
+ }
1223
+
1224
+
1225
+ int32_t Simulator::ReadB(int32_t addr) {
1226
+ int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1227
+ return *ptr;
1228
+ }
1229
+
1230
+
1231
+ void Simulator::WriteB(int32_t addr, uint8_t value) {
1232
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1233
+ *ptr = value;
1234
+ }
1235
+
1236
+
1237
+ void Simulator::WriteB(int32_t addr, int8_t value) {
1238
+ int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1239
+ *ptr = value;
1240
+ }
1241
+
1242
+
1243
+ // Returns the limit of the stack area to enable checking for stack overflows.
1244
+ uintptr_t Simulator::StackLimit() const {
1245
+ // Leave a safety margin of 256 bytes to prevent overrunning the stack when
1246
+ // pushing values.
1247
+ return reinterpret_cast<uintptr_t>(stack_) + 256;
1248
+ }
1249
+
1250
+
1251
+ // Unsupported instructions use Format to print an error and stop execution.
1252
+ void Simulator::Format(Instruction* instr, const char* format) {
1253
+ PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1254
+ reinterpret_cast<intptr_t>(instr), format);
1255
+ UNIMPLEMENTED_MIPS();
1256
+ }
1257
+
1258
+
1259
+ // Calls into the V8 runtime are based on this very simple interface.
1260
+ // Note: To be able to return two values from some calls the code in runtime.cc
1261
+ // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1262
+ // 64-bit value. With the code below we assume that all runtime calls return
1263
+ // 64 bits of result. If they don't, the v1 result register contains a bogus
1264
+ // value, which is fine because it is caller-saved.
1265
+ typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1266
+ int32_t arg1,
1267
+ int32_t arg2,
1268
+ int32_t arg3,
1269
+ int32_t arg4,
1270
+ int32_t arg5);
1271
+ typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
1272
+ int32_t arg1,
1273
+ int32_t arg2,
1274
+ int32_t arg3);
1275
+
1276
+ // This signature supports direct call in to API function native callback
1277
+ // (refer to InvocationCallback in v8.h).
1278
+ typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1279
+
1280
+ // This signature supports direct call to accessor getter callback.
1281
+ typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
1282
+ int32_t arg1);
1283
+
1284
+ // Software interrupt instructions are used by the simulator to call into the
1285
+ // C-based V8 runtime. They are also used for debugging with simulator.
1286
+ void Simulator::SoftwareInterrupt(Instruction* instr) {
1287
+ // There are several instructions that could get us here,
1288
+ // the break_ instruction, or several variants of traps. All
1289
+ // Are "SPECIAL" class opcode, and are distinuished by function.
1290
+ int32_t func = instr->FunctionFieldRaw();
1291
+ int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1292
+
1293
+ // We first check if we met a call_rt_redirected.
1294
+ if (instr->InstructionBits() == rtCallRedirInstr) {
1295
+ Redirection* redirection = Redirection::FromSwiInstruction(instr);
1296
+ int32_t arg0 = get_register(a0);
1297
+ int32_t arg1 = get_register(a1);
1298
+ int32_t arg2 = get_register(a2);
1299
+ int32_t arg3 = get_register(a3);
1300
+ int32_t arg4 = 0;
1301
+ int32_t arg5 = 0;
1302
+
1303
+ // Need to check if sp is valid before assigning arg4, arg5.
1304
+ // This is a fix for cctest test-api/CatchStackOverflow which causes
1305
+ // the stack to overflow. For some reason arm doesn't need this
1306
+ // stack check here.
1307
+ int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1308
+ int32_t* stack = reinterpret_cast<int32_t*>(stack_);
1309
+ if (stack_pointer >= stack && stack_pointer < stack + stack_size_ - 5) {
1310
+ // Args 4 and 5 are on the stack after the reserved space for args 0..3.
1311
+ arg4 = stack_pointer[4];
1312
+ arg5 = stack_pointer[5];
1313
+ }
1314
+
1315
+ bool fp_call =
1316
+ (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1317
+ (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1318
+ (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1319
+ (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1320
+
1321
+ if (!IsMipsSoftFloatABI) {
1322
+ // With the hard floating point calling convention, double
1323
+ // arguments are passed in FPU registers. Fetch the arguments
1324
+ // from there and call the builtin using soft floating point
1325
+ // convention.
1326
+ switch (redirection->type()) {
1327
+ case ExternalReference::BUILTIN_FP_FP_CALL:
1328
+ case ExternalReference::BUILTIN_COMPARE_CALL:
1329
+ arg0 = get_fpu_register(f12);
1330
+ arg1 = get_fpu_register(f13);
1331
+ arg2 = get_fpu_register(f14);
1332
+ arg3 = get_fpu_register(f15);
1333
+ break;
1334
+ case ExternalReference::BUILTIN_FP_CALL:
1335
+ arg0 = get_fpu_register(f12);
1336
+ arg1 = get_fpu_register(f13);
1337
+ break;
1338
+ case ExternalReference::BUILTIN_FP_INT_CALL:
1339
+ arg0 = get_fpu_register(f12);
1340
+ arg1 = get_fpu_register(f13);
1341
+ arg2 = get_register(a2);
1342
+ break;
1343
+ default:
1344
+ break;
1345
+ }
1346
+ }
1347
+
1348
+ // This is dodgy but it works because the C entry stubs are never moved.
1349
+ // See comment in codegen-arm.cc and bug 1242173.
1350
+ int32_t saved_ra = get_register(ra);
1351
+
1352
+ intptr_t external =
1353
+ reinterpret_cast<intptr_t>(redirection->external_function());
1354
+
1355
+ // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1356
+ // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1357
+ // simulator. Soft-float has additional abstraction of ExternalReference,
1358
+ // to support serialization.
1359
+ if (fp_call) {
1360
+ SimulatorRuntimeFPCall target =
1361
+ reinterpret_cast<SimulatorRuntimeFPCall>(external);
1362
+ if (::v8::internal::FLAG_trace_sim) {
1363
+ double dval0, dval1;
1364
+ int32_t ival;
1365
+ switch (redirection->type()) {
1366
+ case ExternalReference::BUILTIN_FP_FP_CALL:
1367
+ case ExternalReference::BUILTIN_COMPARE_CALL:
1368
+ GetFpArgs(&dval0, &dval1);
1369
+ PrintF("Call to host function at %p with args %f, %f",
1370
+ FUNCTION_ADDR(target), dval0, dval1);
1371
+ break;
1372
+ case ExternalReference::BUILTIN_FP_CALL:
1373
+ GetFpArgs(&dval0);
1374
+ PrintF("Call to host function at %p with arg %f",
1375
+ FUNCTION_ADDR(target), dval1);
1376
+ break;
1377
+ case ExternalReference::BUILTIN_FP_INT_CALL:
1378
+ GetFpArgs(&dval0, &ival);
1379
+ PrintF("Call to host function at %p with args %f, %d",
1380
+ FUNCTION_ADDR(target), dval0, ival);
1381
+ break;
1382
+ default:
1383
+ UNREACHABLE();
1384
+ break;
1385
+ }
1386
+ }
1387
+ double result = target(arg0, arg1, arg2, arg3);
1388
+ if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
1389
+ SetFpResult(result);
1390
+ } else {
1391
+ int32_t gpreg_pair[2];
1392
+ memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t));
1393
+ set_register(v0, gpreg_pair[0]);
1394
+ set_register(v1, gpreg_pair[1]);
1395
+ }
1396
+ } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1397
+ // See DirectCEntryStub::GenerateCall for explanation of register usage.
1398
+ SimulatorRuntimeDirectApiCall target =
1399
+ reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1400
+ if (::v8::internal::FLAG_trace_sim) {
1401
+ PrintF("Call to host function at %p args %08x\n",
1402
+ FUNCTION_ADDR(target), arg1);
1403
+ }
1404
+ v8::Handle<v8::Value> result = target(arg1);
1405
+ *(reinterpret_cast<int*>(arg0)) = (int32_t) *result;
1406
+ set_register(v0, arg0);
1407
+ } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1408
+ // See DirectCEntryStub::GenerateCall for explanation of register usage.
1409
+ SimulatorRuntimeDirectGetterCall target =
1410
+ reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1411
+ if (::v8::internal::FLAG_trace_sim) {
1412
+ PrintF("Call to host function at %p args %08x %08x\n",
1413
+ FUNCTION_ADDR(target), arg1, arg2);
1414
+ }
1415
+ v8::Handle<v8::Value> result = target(arg1, arg2);
1416
+ *(reinterpret_cast<int*>(arg0)) = (int32_t) *result;
1417
+ set_register(v0, arg0);
1418
+ } else {
1419
+ SimulatorRuntimeCall target =
1420
+ reinterpret_cast<SimulatorRuntimeCall>(external);
1421
+ if (::v8::internal::FLAG_trace_sim) {
1422
+ PrintF(
1423
+ "Call to host function at %p "
1424
+ "args %08x, %08x, %08x, %08x, %08x, %08x\n",
1425
+ FUNCTION_ADDR(target),
1426
+ arg0,
1427
+ arg1,
1428
+ arg2,
1429
+ arg3,
1430
+ arg4,
1431
+ arg5);
1432
+ }
1433
+ int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1434
+ set_register(v0, static_cast<int32_t>(result));
1435
+ set_register(v1, static_cast<int32_t>(result >> 32));
1436
+ }
1437
+ if (::v8::internal::FLAG_trace_sim) {
1438
+ PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
1439
+ }
1440
+ set_register(ra, saved_ra);
1441
+ set_pc(get_register(ra));
1442
+
1443
+ } else if (func == BREAK && code >= 0 && code < 32) {
1444
+ // First 32 break_ codes interpreted as debug-markers/watchpoints.
1445
+ MipsDebugger dbg(this);
1446
+ ++break_count_;
1447
+ PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------"
1448
+ "----------------------------------",
1449
+ code, break_count_, icount_);
1450
+ dbg.PrintAllRegs(); // Print registers and continue running.
1451
+ } else {
1452
+ // All remaining break_ codes, and all traps are handled here.
1453
+ MipsDebugger dbg(this);
1454
+ dbg.Debug();
1455
+ }
1456
+ }
1457
+
1458
+
1459
+ void Simulator::SignalExceptions() {
1460
+ for (int i = 1; i < kNumExceptions; i++) {
1461
+ if (exceptions[i] != 0) {
1462
+ V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
1463
+ }
1464
+ }
1465
+ }
1466
+
1467
+
1468
+ // Handle execution based on instruction types.
1469
+
1470
+ void Simulator::ConfigureTypeRegister(Instruction* instr,
1471
+ int32_t& alu_out,
1472
+ int64_t& i64hilo,
1473
+ uint64_t& u64hilo,
1474
+ int32_t& next_pc,
1475
+ bool& do_interrupt) {
1476
+ // Every local variable declared here needs to be const.
1477
+ // This is to make sure that changed values are sent back to
1478
+ // DecodeTypeRegister correctly.
1479
+
1480
+ // Instruction fields.
1481
+ const Opcode op = instr->OpcodeFieldRaw();
1482
+ const int32_t rs_reg = instr->RsValue();
1483
+ const int32_t rs = get_register(rs_reg);
1484
+ const uint32_t rs_u = static_cast<uint32_t>(rs);
1485
+ const int32_t rt_reg = instr->RtValue();
1486
+ const int32_t rt = get_register(rt_reg);
1487
+ const uint32_t rt_u = static_cast<uint32_t>(rt);
1488
+ const int32_t rd_reg = instr->RdValue();
1489
+ const uint32_t sa = instr->SaValue();
1490
+
1491
+ const int32_t fs_reg = instr->FsValue();
1492
+
1493
+
1494
+ // ---------- Configuration.
1495
+ switch (op) {
1496
+ case COP1: // Coprocessor instructions.
1497
+ switch (instr->RsFieldRaw()) {
1498
+ case BC1: // Handled in DecodeTypeImmed, should never come here.
1499
+ UNREACHABLE();
1500
+ break;
1501
+ case CFC1:
1502
+ // At the moment only FCSR is supported.
1503
+ ASSERT(fs_reg == kFCSRRegister);
1504
+ alu_out = FCSR_;
1505
+ break;
1506
+ case MFC1:
1507
+ alu_out = get_fpu_register(fs_reg);
1508
+ break;
1509
+ case MFHC1:
1510
+ UNIMPLEMENTED_MIPS();
1511
+ break;
1512
+ case CTC1:
1513
+ case MTC1:
1514
+ case MTHC1:
1515
+ // Do the store in the execution step.
1516
+ break;
1517
+ case S:
1518
+ case D:
1519
+ case W:
1520
+ case L:
1521
+ case PS:
1522
+ // Do everything in the execution step.
1523
+ break;
1524
+ default:
1525
+ UNIMPLEMENTED_MIPS();
1526
+ };
1527
+ break;
1528
+ case SPECIAL:
1529
+ switch (instr->FunctionFieldRaw()) {
1530
+ case JR:
1531
+ case JALR:
1532
+ next_pc = get_register(instr->RsValue());
1533
+ break;
1534
+ case SLL:
1535
+ alu_out = rt << sa;
1536
+ break;
1537
+ case SRL:
1538
+ if (rs_reg == 0) {
1539
+ // Regular logical right shift of a word by a fixed number of
1540
+ // bits instruction. RS field is always equal to 0.
1541
+ alu_out = rt_u >> sa;
1542
+ } else {
1543
+ // Logical right-rotate of a word by a fixed number of bits. This
1544
+ // is special case of SRL instruction, added in MIPS32 Release 2.
1545
+ // RS field is equal to 00001.
1546
+ alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1547
+ }
1548
+ break;
1549
+ case SRA:
1550
+ alu_out = rt >> sa;
1551
+ break;
1552
+ case SLLV:
1553
+ alu_out = rt << rs;
1554
+ break;
1555
+ case SRLV:
1556
+ if (sa == 0) {
1557
+ // Regular logical right-shift of a word by a variable number of
1558
+ // bits instruction. SA field is always equal to 0.
1559
+ alu_out = rt_u >> rs;
1560
+ } else {
1561
+ // Logical right-rotate of a word by a variable number of bits.
1562
+ // This is special case od SRLV instruction, added in MIPS32
1563
+ // Release 2. SA field is equal to 00001.
1564
+ alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1565
+ }
1566
+ break;
1567
+ case SRAV:
1568
+ alu_out = rt >> rs;
1569
+ break;
1570
+ case MFHI:
1571
+ alu_out = get_register(HI);
1572
+ break;
1573
+ case MFLO:
1574
+ alu_out = get_register(LO);
1575
+ break;
1576
+ case MULT:
1577
+ i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
1578
+ break;
1579
+ case MULTU:
1580
+ u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
1581
+ break;
1582
+ case ADD:
1583
+ if (HaveSameSign(rs, rt)) {
1584
+ if (rs > 0) {
1585
+ exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
1586
+ } else if (rs < 0) {
1587
+ exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
1588
+ }
1589
+ }
1590
+ alu_out = rs + rt;
1591
+ break;
1592
+ case ADDU:
1593
+ alu_out = rs + rt;
1594
+ break;
1595
+ case SUB:
1596
+ if (!HaveSameSign(rs, rt)) {
1597
+ if (rs > 0) {
1598
+ exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
1599
+ } else if (rs < 0) {
1600
+ exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
1601
+ }
1602
+ }
1603
+ alu_out = rs - rt;
1604
+ break;
1605
+ case SUBU:
1606
+ alu_out = rs - rt;
1607
+ break;
1608
+ case AND:
1609
+ alu_out = rs & rt;
1610
+ break;
1611
+ case OR:
1612
+ alu_out = rs | rt;
1613
+ break;
1614
+ case XOR:
1615
+ alu_out = rs ^ rt;
1616
+ break;
1617
+ case NOR:
1618
+ alu_out = ~(rs | rt);
1619
+ break;
1620
+ case SLT:
1621
+ alu_out = rs < rt ? 1 : 0;
1622
+ break;
1623
+ case SLTU:
1624
+ alu_out = rs_u < rt_u ? 1 : 0;
1625
+ break;
1626
+ // Break and trap instructions.
1627
+ case BREAK:
1628
+
1629
+ do_interrupt = true;
1630
+ break;
1631
+ case TGE:
1632
+ do_interrupt = rs >= rt;
1633
+ break;
1634
+ case TGEU:
1635
+ do_interrupt = rs_u >= rt_u;
1636
+ break;
1637
+ case TLT:
1638
+ do_interrupt = rs < rt;
1639
+ break;
1640
+ case TLTU:
1641
+ do_interrupt = rs_u < rt_u;
1642
+ break;
1643
+ case TEQ:
1644
+ do_interrupt = rs == rt;
1645
+ break;
1646
+ case TNE:
1647
+ do_interrupt = rs != rt;
1648
+ break;
1649
+ case MOVN:
1650
+ case MOVZ:
1651
+ case MOVCI:
1652
+ // No action taken on decode.
1653
+ break;
1654
+ case DIV:
1655
+ case DIVU:
1656
+ // div and divu never raise exceptions.
1657
+ break;
1658
+ default:
1659
+ UNREACHABLE();
1660
+ };
1661
+ break;
1662
+ case SPECIAL2:
1663
+ switch (instr->FunctionFieldRaw()) {
1664
+ case MUL:
1665
+ alu_out = rs_u * rt_u; // Only the lower 32 bits are kept.
1666
+ break;
1667
+ case CLZ:
1668
+ alu_out = __builtin_clz(rs_u);
1669
+ break;
1670
+ default:
1671
+ UNREACHABLE();
1672
+ };
1673
+ break;
1674
+ case SPECIAL3:
1675
+ switch (instr->FunctionFieldRaw()) {
1676
+ case INS: { // Mips32r2 instruction.
1677
+ // Interpret rd field as 5-bit msb of insert.
1678
+ uint16_t msb = rd_reg;
1679
+ // Interpret sa field as 5-bit lsb of insert.
1680
+ uint16_t lsb = sa;
1681
+ uint16_t size = msb - lsb + 1;
1682
+ uint32_t mask = (1 << size) - 1;
1683
+ alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1684
+ break;
1685
+ }
1686
+ case EXT: { // Mips32r2 instruction.
1687
+ // Interpret rd field as 5-bit msb of extract.
1688
+ uint16_t msb = rd_reg;
1689
+ // Interpret sa field as 5-bit lsb of extract.
1690
+ uint16_t lsb = sa;
1691
+ uint16_t size = msb + 1;
1692
+ uint32_t mask = (1 << size) - 1;
1693
+ alu_out = (rs_u & (mask << lsb)) >> lsb;
1694
+ break;
1695
+ }
1696
+ default:
1697
+ UNREACHABLE();
1698
+ };
1699
+ break;
1700
+ default:
1701
+ UNREACHABLE();
1702
+ };
1703
+ }
1704
+
1705
+
1706
+ void Simulator::DecodeTypeRegister(Instruction* instr) {
1707
+ // Instruction fields.
1708
+ const Opcode op = instr->OpcodeFieldRaw();
1709
+ const int32_t rs_reg = instr->RsValue();
1710
+ const int32_t rs = get_register(rs_reg);
1711
+ const uint32_t rs_u = static_cast<uint32_t>(rs);
1712
+ const int32_t rt_reg = instr->RtValue();
1713
+ const int32_t rt = get_register(rt_reg);
1714
+ const uint32_t rt_u = static_cast<uint32_t>(rt);
1715
+ const int32_t rd_reg = instr->RdValue();
1716
+
1717
+ const int32_t fs_reg = instr->FsValue();
1718
+ const int32_t ft_reg = instr->FtValue();
1719
+ const int32_t fd_reg = instr->FdValue();
1720
+ int64_t i64hilo = 0;
1721
+ uint64_t u64hilo = 0;
1722
+
1723
+ // ALU output.
1724
+ // It should not be used as is. Instructions using it should always
1725
+ // initialize it first.
1726
+ int32_t alu_out = 0x12345678;
1727
+
1728
+ // For break and trap instructions.
1729
+ bool do_interrupt = false;
1730
+
1731
+ // For jr and jalr.
1732
+ // Get current pc.
1733
+ int32_t current_pc = get_pc();
1734
+ // Next pc
1735
+ int32_t next_pc = 0;
1736
+
1737
+ // Setup the variables if needed before executing the instruction.
1738
+ ConfigureTypeRegister(instr,
1739
+ alu_out,
1740
+ i64hilo,
1741
+ u64hilo,
1742
+ next_pc,
1743
+ do_interrupt);
1744
+
1745
+ // ---------- Raise exceptions triggered.
1746
+ SignalExceptions();
1747
+
1748
+ // ---------- Execution.
1749
+ switch (op) {
1750
+ case COP1:
1751
+ switch (instr->RsFieldRaw()) {
1752
+ case BC1: // Branch on coprocessor condition.
1753
+ UNREACHABLE();
1754
+ break;
1755
+ case CFC1:
1756
+ set_register(rt_reg, alu_out);
1757
+ case MFC1:
1758
+ set_register(rt_reg, alu_out);
1759
+ break;
1760
+ case MFHC1:
1761
+ UNIMPLEMENTED_MIPS();
1762
+ break;
1763
+ case CTC1:
1764
+ // At the moment only FCSR is supported.
1765
+ ASSERT(fs_reg == kFCSRRegister);
1766
+ FCSR_ = registers_[rt_reg];
1767
+ break;
1768
+ case MTC1:
1769
+ FPUregisters_[fs_reg] = registers_[rt_reg];
1770
+ break;
1771
+ case MTHC1:
1772
+ UNIMPLEMENTED_MIPS();
1773
+ break;
1774
+ case S:
1775
+ float f;
1776
+ switch (instr->FunctionFieldRaw()) {
1777
+ case CVT_D_S:
1778
+ f = get_fpu_register_float(fs_reg);
1779
+ set_fpu_register_double(fd_reg, static_cast<double>(f));
1780
+ break;
1781
+ case CVT_W_S:
1782
+ case CVT_L_S:
1783
+ case TRUNC_W_S:
1784
+ case TRUNC_L_S:
1785
+ case ROUND_W_S:
1786
+ case ROUND_L_S:
1787
+ case FLOOR_W_S:
1788
+ case FLOOR_L_S:
1789
+ case CEIL_W_S:
1790
+ case CEIL_L_S:
1791
+ case CVT_PS_S:
1792
+ UNIMPLEMENTED_MIPS();
1793
+ break;
1794
+ default:
1795
+ UNREACHABLE();
1796
+ }
1797
+ break;
1798
+ case D:
1799
+ double ft, fs;
1800
+ uint32_t cc, fcsr_cc;
1801
+ int64_t i64;
1802
+ fs = get_fpu_register_double(fs_reg);
1803
+ ft = get_fpu_register_double(ft_reg);
1804
+ cc = instr->FCccValue();
1805
+ fcsr_cc = get_fcsr_condition_bit(cc);
1806
+ switch (instr->FunctionFieldRaw()) {
1807
+ case ADD_D:
1808
+ set_fpu_register_double(fd_reg, fs + ft);
1809
+ break;
1810
+ case SUB_D:
1811
+ set_fpu_register_double(fd_reg, fs - ft);
1812
+ break;
1813
+ case MUL_D:
1814
+ set_fpu_register_double(fd_reg, fs * ft);
1815
+ break;
1816
+ case DIV_D:
1817
+ set_fpu_register_double(fd_reg, fs / ft);
1818
+ break;
1819
+ case ABS_D:
1820
+ set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs);
1821
+ break;
1822
+ case MOV_D:
1823
+ set_fpu_register_double(fd_reg, fs);
1824
+ break;
1825
+ case NEG_D:
1826
+ set_fpu_register_double(fd_reg, -fs);
1827
+ break;
1828
+ case SQRT_D:
1829
+ set_fpu_register_double(fd_reg, sqrt(fs));
1830
+ break;
1831
+ case C_UN_D:
1832
+ set_fcsr_bit(fcsr_cc, isnan(fs) || isnan(ft));
1833
+ break;
1834
+ case C_EQ_D:
1835
+ set_fcsr_bit(fcsr_cc, (fs == ft));
1836
+ break;
1837
+ case C_UEQ_D:
1838
+ set_fcsr_bit(fcsr_cc, (fs == ft) || (isnan(fs) || isnan(ft)));
1839
+ break;
1840
+ case C_OLT_D:
1841
+ set_fcsr_bit(fcsr_cc, (fs < ft));
1842
+ break;
1843
+ case C_ULT_D:
1844
+ set_fcsr_bit(fcsr_cc, (fs < ft) || (isnan(fs) || isnan(ft)));
1845
+ break;
1846
+ case C_OLE_D:
1847
+ set_fcsr_bit(fcsr_cc, (fs <= ft));
1848
+ break;
1849
+ case C_ULE_D:
1850
+ set_fcsr_bit(fcsr_cc, (fs <= ft) || (isnan(fs) || isnan(ft)));
1851
+ break;
1852
+ case CVT_W_D: // Convert double to word.
1853
+ // Rounding modes are not yet supported.
1854
+ ASSERT((FCSR_ & 3) == 0);
1855
+ // In rounding mode 0 it should behave like ROUND.
1856
+ case ROUND_W_D: // Round double to word.
1857
+ {
1858
+ double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1859
+ int32_t result = static_cast<int32_t>(rounded);
1860
+ set_fpu_register(fd_reg, result);
1861
+ if (set_fcsr_round_error(fs, rounded)) {
1862
+ set_fpu_register(fd_reg, kFPUInvalidResult);
1863
+ }
1864
+ }
1865
+ break;
1866
+ case TRUNC_W_D: // Truncate double to word (round towards 0).
1867
+ {
1868
+ int32_t result = static_cast<int32_t>(fs);
1869
+ set_fpu_register(fd_reg, result);
1870
+ if (set_fcsr_round_error(fs, static_cast<double>(result))) {
1871
+ set_fpu_register(fd_reg, kFPUInvalidResult);
1872
+ }
1873
+ }
1874
+ break;
1875
+ case FLOOR_W_D: // Round double to word towards negative infinity.
1876
+ {
1877
+ double rounded = floor(fs);
1878
+ int32_t result = static_cast<int32_t>(rounded);
1879
+ set_fpu_register(fd_reg, result);
1880
+ if (set_fcsr_round_error(fs, rounded)) {
1881
+ set_fpu_register(fd_reg, kFPUInvalidResult);
1882
+ }
1883
+ }
1884
+ break;
1885
+ case CEIL_W_D: // Round double to word towards positive infinity.
1886
+ {
1887
+ double rounded = ceil(fs);
1888
+ int32_t result = static_cast<int32_t>(rounded);
1889
+ set_fpu_register(fd_reg, result);
1890
+ if (set_fcsr_round_error(fs, rounded)) {
1891
+ set_fpu_register(fd_reg, kFPUInvalidResult);
1892
+ }
1893
+ }
1894
+ break;
1895
+ case CVT_S_D: // Convert double to float (single).
1896
+ set_fpu_register_float(fd_reg, static_cast<float>(fs));
1897
+ break;
1898
+ case CVT_L_D: // Mips32r2: Truncate double to 64-bit long-word.
1899
+ i64 = static_cast<int64_t>(fs);
1900
+ set_fpu_register(fd_reg, i64 & 0xffffffff);
1901
+ set_fpu_register(fd_reg + 1, i64 >> 32);
1902
+ break;
1903
+ case TRUNC_L_D: // Mips32r2 instruction.
1904
+ i64 = static_cast<int64_t>(fs);
1905
+ set_fpu_register(fd_reg, i64 & 0xffffffff);
1906
+ set_fpu_register(fd_reg + 1, i64 >> 32);
1907
+ break;
1908
+ case ROUND_L_D: { // Mips32r2 instruction.
1909
+ double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1910
+ i64 = static_cast<int64_t>(rounded);
1911
+ set_fpu_register(fd_reg, i64 & 0xffffffff);
1912
+ set_fpu_register(fd_reg + 1, i64 >> 32);
1913
+ break;
1914
+ }
1915
+ case FLOOR_L_D: // Mips32r2 instruction.
1916
+ i64 = static_cast<int64_t>(floor(fs));
1917
+ set_fpu_register(fd_reg, i64 & 0xffffffff);
1918
+ set_fpu_register(fd_reg + 1, i64 >> 32);
1919
+ break;
1920
+ case CEIL_L_D: // Mips32r2 instruction.
1921
+ i64 = static_cast<int64_t>(ceil(fs));
1922
+ set_fpu_register(fd_reg, i64 & 0xffffffff);
1923
+ set_fpu_register(fd_reg + 1, i64 >> 32);
1924
+ break;
1925
+ case C_F_D:
1926
+ UNIMPLEMENTED_MIPS();
1927
+ break;
1928
+ default:
1929
+ UNREACHABLE();
1930
+ }
1931
+ break;
1932
+ case W:
1933
+ switch (instr->FunctionFieldRaw()) {
1934
+ case CVT_S_W: // Convert word to float (single).
1935
+ alu_out = get_fpu_register(fs_reg);
1936
+ set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
1937
+ break;
1938
+ case CVT_D_W: // Convert word to double.
1939
+ alu_out = get_fpu_register(fs_reg);
1940
+ set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
1941
+ break;
1942
+ default:
1943
+ UNREACHABLE();
1944
+ };
1945
+ break;
1946
+ case L:
1947
+ switch (instr->FunctionFieldRaw()) {
1948
+ case CVT_D_L: // Mips32r2 instruction.
1949
+ // Watch the signs here, we want 2 32-bit vals
1950
+ // to make a sign-64.
1951
+ i64 = (uint32_t) get_fpu_register(fs_reg);
1952
+ i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
1953
+ set_fpu_register_double(fd_reg, static_cast<double>(i64));
1954
+ break;
1955
+ case CVT_S_L:
1956
+ UNIMPLEMENTED_MIPS();
1957
+ break;
1958
+ default:
1959
+ UNREACHABLE();
1960
+ }
1961
+ break;
1962
+ case PS:
1963
+ break;
1964
+ default:
1965
+ UNREACHABLE();
1966
+ };
1967
+ break;
1968
+ case SPECIAL:
1969
+ switch (instr->FunctionFieldRaw()) {
1970
+ case JR: {
1971
+ Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
1972
+ current_pc+Instruction::kInstrSize);
1973
+ BranchDelayInstructionDecode(branch_delay_instr);
1974
+ set_pc(next_pc);
1975
+ pc_modified_ = true;
1976
+ break;
1977
+ }
1978
+ case JALR: {
1979
+ Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
1980
+ current_pc+Instruction::kInstrSize);
1981
+ BranchDelayInstructionDecode(branch_delay_instr);
1982
+ set_register(31, current_pc + 2 * Instruction::kInstrSize);
1983
+ set_pc(next_pc);
1984
+ pc_modified_ = true;
1985
+ break;
1986
+ }
1987
+ // Instructions using HI and LO registers.
1988
+ case MULT:
1989
+ set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
1990
+ set_register(HI, static_cast<int32_t>(i64hilo >> 32));
1991
+ break;
1992
+ case MULTU:
1993
+ set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
1994
+ set_register(HI, static_cast<int32_t>(u64hilo >> 32));
1995
+ break;
1996
+ case DIV:
1997
+ // Divide by zero was not checked in the configuration step - div and
1998
+ // divu do not raise exceptions. On division by 0, the result will
1999
+ // be UNPREDICTABLE.
2000
+ if (rt != 0) {
2001
+ set_register(LO, rs / rt);
2002
+ set_register(HI, rs % rt);
2003
+ }
2004
+ break;
2005
+ case DIVU:
2006
+ if (rt_u != 0) {
2007
+ set_register(LO, rs_u / rt_u);
2008
+ set_register(HI, rs_u % rt_u);
2009
+ }
2010
+ break;
2011
+ // Break and trap instructions.
2012
+ case BREAK:
2013
+ case TGE:
2014
+ case TGEU:
2015
+ case TLT:
2016
+ case TLTU:
2017
+ case TEQ:
2018
+ case TNE:
2019
+ if (do_interrupt) {
2020
+ SoftwareInterrupt(instr);
2021
+ }
2022
+ break;
2023
+ // Conditional moves.
2024
+ case MOVN:
2025
+ if (rt) set_register(rd_reg, rs);
2026
+ break;
2027
+ case MOVCI: {
2028
+ uint32_t cc = instr->FBccValue();
2029
+ uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2030
+ if (instr->Bit(16)) { // Read Tf bit.
2031
+ if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2032
+ } else {
2033
+ if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2034
+ }
2035
+ break;
2036
+ }
2037
+ case MOVZ:
2038
+ if (!rt) set_register(rd_reg, rs);
2039
+ break;
2040
+ default: // For other special opcodes we do the default operation.
2041
+ set_register(rd_reg, alu_out);
2042
+ };
2043
+ break;
2044
+ case SPECIAL2:
2045
+ switch (instr->FunctionFieldRaw()) {
2046
+ case MUL:
2047
+ set_register(rd_reg, alu_out);
2048
+ // HI and LO are UNPREDICTABLE after the operation.
2049
+ set_register(LO, Unpredictable);
2050
+ set_register(HI, Unpredictable);
2051
+ break;
2052
+ default: // For other special2 opcodes we do the default operation.
2053
+ set_register(rd_reg, alu_out);
2054
+ }
2055
+ break;
2056
+ case SPECIAL3:
2057
+ switch (instr->FunctionFieldRaw()) {
2058
+ case INS:
2059
+ // Ins instr leaves result in Rt, rather than Rd.
2060
+ set_register(rt_reg, alu_out);
2061
+ break;
2062
+ case EXT:
2063
+ // Ext instr leaves result in Rt, rather than Rd.
2064
+ set_register(rt_reg, alu_out);
2065
+ break;
2066
+ default:
2067
+ UNREACHABLE();
2068
+ };
2069
+ break;
2070
+ // Unimplemented opcodes raised an error in the configuration step before,
2071
+ // so we can use the default here to set the destination register in common
2072
+ // cases.
2073
+ default:
2074
+ set_register(rd_reg, alu_out);
2075
+ };
2076
+ }
2077
+
2078
+
2079
+ // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq).
2080
+ void Simulator::DecodeTypeImmediate(Instruction* instr) {
2081
+ // Instruction fields.
2082
+ Opcode op = instr->OpcodeFieldRaw();
2083
+ int32_t rs = get_register(instr->RsValue());
2084
+ uint32_t rs_u = static_cast<uint32_t>(rs);
2085
+ int32_t rt_reg = instr->RtValue(); // Destination register.
2086
+ int32_t rt = get_register(rt_reg);
2087
+ int16_t imm16 = instr->Imm16Value();
2088
+
2089
+ int32_t ft_reg = instr->FtValue(); // Destination register.
2090
+
2091
+ // Zero extended immediate.
2092
+ uint32_t oe_imm16 = 0xffff & imm16;
2093
+ // Sign extended immediate.
2094
+ int32_t se_imm16 = imm16;
2095
+
2096
+ // Get current pc.
2097
+ int32_t current_pc = get_pc();
2098
+ // Next pc.
2099
+ int32_t next_pc = bad_ra;
2100
+
2101
+ // Used for conditional branch instructions.
2102
+ bool do_branch = false;
2103
+ bool execute_branch_delay_instruction = false;
2104
+
2105
+ // Used for arithmetic instructions.
2106
+ int32_t alu_out = 0;
2107
+ // Floating point.
2108
+ double fp_out = 0.0;
2109
+ uint32_t cc, cc_value, fcsr_cc;
2110
+
2111
+ // Used for memory instructions.
2112
+ int32_t addr = 0x0;
2113
+ // Value to be written in memory.
2114
+ uint32_t mem_value = 0x0;
2115
+
2116
+ // ---------- Configuration (and execution for REGIMM).
2117
+ switch (op) {
2118
+ // ------------- COP1. Coprocessor instructions.
2119
+ case COP1:
2120
+ switch (instr->RsFieldRaw()) {
2121
+ case BC1: // Branch on coprocessor condition.
2122
+ cc = instr->FBccValue();
2123
+ fcsr_cc = get_fcsr_condition_bit(cc);
2124
+ cc_value = test_fcsr_bit(fcsr_cc);
2125
+ do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2126
+ execute_branch_delay_instruction = true;
2127
+ // Set next_pc.
2128
+ if (do_branch) {
2129
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2130
+ } else {
2131
+ next_pc = current_pc + kBranchReturnOffset;
2132
+ }
2133
+ break;
2134
+ default:
2135
+ UNREACHABLE();
2136
+ };
2137
+ break;
2138
+ // ------------- REGIMM class.
2139
+ case REGIMM:
2140
+ switch (instr->RtFieldRaw()) {
2141
+ case BLTZ:
2142
+ do_branch = (rs < 0);
2143
+ break;
2144
+ case BLTZAL:
2145
+ do_branch = rs < 0;
2146
+ break;
2147
+ case BGEZ:
2148
+ do_branch = rs >= 0;
2149
+ break;
2150
+ case BGEZAL:
2151
+ do_branch = rs >= 0;
2152
+ break;
2153
+ default:
2154
+ UNREACHABLE();
2155
+ };
2156
+ switch (instr->RtFieldRaw()) {
2157
+ case BLTZ:
2158
+ case BLTZAL:
2159
+ case BGEZ:
2160
+ case BGEZAL:
2161
+ // Branch instructions common part.
2162
+ execute_branch_delay_instruction = true;
2163
+ // Set next_pc.
2164
+ if (do_branch) {
2165
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2166
+ if (instr->IsLinkingInstruction()) {
2167
+ set_register(31, current_pc + kBranchReturnOffset);
2168
+ }
2169
+ } else {
2170
+ next_pc = current_pc + kBranchReturnOffset;
2171
+ }
2172
+ default:
2173
+ break;
2174
+ };
2175
+ break; // case REGIMM.
2176
+ // ------------- Branch instructions.
2177
+ // When comparing to zero, the encoding of rt field is always 0, so we don't
2178
+ // need to replace rt with zero.
2179
+ case BEQ:
2180
+ do_branch = (rs == rt);
2181
+ break;
2182
+ case BNE:
2183
+ do_branch = rs != rt;
2184
+ break;
2185
+ case BLEZ:
2186
+ do_branch = rs <= 0;
2187
+ break;
2188
+ case BGTZ:
2189
+ do_branch = rs > 0;
2190
+ break;
2191
+ // ------------- Arithmetic instructions.
2192
+ case ADDI:
2193
+ if (HaveSameSign(rs, se_imm16)) {
2194
+ if (rs > 0) {
2195
+ exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2196
+ } else if (rs < 0) {
2197
+ exceptions[kIntegerUnderflow] =
2198
+ rs < (Registers::kMinValue - se_imm16);
2199
+ }
2200
+ }
2201
+ alu_out = rs + se_imm16;
2202
+ break;
2203
+ case ADDIU:
2204
+ alu_out = rs + se_imm16;
2205
+ break;
2206
+ case SLTI:
2207
+ alu_out = (rs < se_imm16) ? 1 : 0;
2208
+ break;
2209
+ case SLTIU:
2210
+ alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2211
+ break;
2212
+ case ANDI:
2213
+ alu_out = rs & oe_imm16;
2214
+ break;
2215
+ case ORI:
2216
+ alu_out = rs | oe_imm16;
2217
+ break;
2218
+ case XORI:
2219
+ alu_out = rs ^ oe_imm16;
2220
+ break;
2221
+ case LUI:
2222
+ alu_out = (oe_imm16 << 16);
2223
+ break;
2224
+ // ------------- Memory instructions.
2225
+ case LB:
2226
+ addr = rs + se_imm16;
2227
+ alu_out = ReadB(addr);
2228
+ break;
2229
+ case LH:
2230
+ addr = rs + se_imm16;
2231
+ alu_out = ReadH(addr, instr);
2232
+ break;
2233
+ case LWL: {
2234
+ // al_offset is offset of the effective address within an aligned word.
2235
+ uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2236
+ uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2237
+ uint32_t mask = (1 << byte_shift * 8) - 1;
2238
+ addr = rs + se_imm16 - al_offset;
2239
+ alu_out = ReadW(addr, instr);
2240
+ alu_out <<= byte_shift * 8;
2241
+ alu_out |= rt & mask;
2242
+ break;
2243
+ }
2244
+ case LW:
2245
+ addr = rs + se_imm16;
2246
+ alu_out = ReadW(addr, instr);
2247
+ break;
2248
+ case LBU:
2249
+ addr = rs + se_imm16;
2250
+ alu_out = ReadBU(addr);
2251
+ break;
2252
+ case LHU:
2253
+ addr = rs + se_imm16;
2254
+ alu_out = ReadHU(addr, instr);
2255
+ break;
2256
+ case LWR: {
2257
+ // al_offset is offset of the effective address within an aligned word.
2258
+ uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2259
+ uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2260
+ uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2261
+ addr = rs + se_imm16 - al_offset;
2262
+ alu_out = ReadW(addr, instr);
2263
+ alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2264
+ alu_out |= rt & mask;
2265
+ break;
2266
+ }
2267
+ case SB:
2268
+ addr = rs + se_imm16;
2269
+ break;
2270
+ case SH:
2271
+ addr = rs + se_imm16;
2272
+ break;
2273
+ case SWL: {
2274
+ uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2275
+ uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2276
+ uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2277
+ addr = rs + se_imm16 - al_offset;
2278
+ mem_value = ReadW(addr, instr) & mask;
2279
+ mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2280
+ break;
2281
+ }
2282
+ case SW:
2283
+ addr = rs + se_imm16;
2284
+ break;
2285
+ case SWR: {
2286
+ uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2287
+ uint32_t mask = (1 << al_offset * 8) - 1;
2288
+ addr = rs + se_imm16 - al_offset;
2289
+ mem_value = ReadW(addr, instr);
2290
+ mem_value = (rt << al_offset * 8) | (mem_value & mask);
2291
+ break;
2292
+ }
2293
+ case LWC1:
2294
+ addr = rs + se_imm16;
2295
+ alu_out = ReadW(addr, instr);
2296
+ break;
2297
+ case LDC1:
2298
+ addr = rs + se_imm16;
2299
+ fp_out = ReadD(addr, instr);
2300
+ break;
2301
+ case SWC1:
2302
+ case SDC1:
2303
+ addr = rs + se_imm16;
2304
+ break;
2305
+ default:
2306
+ UNREACHABLE();
2307
+ };
2308
+
2309
+ // ---------- Raise exceptions triggered.
2310
+ SignalExceptions();
2311
+
2312
+ // ---------- Execution.
2313
+ switch (op) {
2314
+ // ------------- Branch instructions.
2315
+ case BEQ:
2316
+ case BNE:
2317
+ case BLEZ:
2318
+ case BGTZ:
2319
+ // Branch instructions common part.
2320
+ execute_branch_delay_instruction = true;
2321
+ // Set next_pc.
2322
+ if (do_branch) {
2323
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2324
+ if (instr->IsLinkingInstruction()) {
2325
+ set_register(31, current_pc + 2* Instruction::kInstrSize);
2326
+ }
2327
+ } else {
2328
+ next_pc = current_pc + 2 * Instruction::kInstrSize;
2329
+ }
2330
+ break;
2331
+ // ------------- Arithmetic instructions.
2332
+ case ADDI:
2333
+ case ADDIU:
2334
+ case SLTI:
2335
+ case SLTIU:
2336
+ case ANDI:
2337
+ case ORI:
2338
+ case XORI:
2339
+ case LUI:
2340
+ set_register(rt_reg, alu_out);
2341
+ break;
2342
+ // ------------- Memory instructions.
2343
+ case LB:
2344
+ case LH:
2345
+ case LWL:
2346
+ case LW:
2347
+ case LBU:
2348
+ case LHU:
2349
+ case LWR:
2350
+ set_register(rt_reg, alu_out);
2351
+ break;
2352
+ case SB:
2353
+ WriteB(addr, static_cast<int8_t>(rt));
2354
+ break;
2355
+ case SH:
2356
+ WriteH(addr, static_cast<uint16_t>(rt), instr);
2357
+ break;
2358
+ case SWL:
2359
+ WriteW(addr, mem_value, instr);
2360
+ break;
2361
+ case SW:
2362
+ WriteW(addr, rt, instr);
2363
+ break;
2364
+ case SWR:
2365
+ WriteW(addr, mem_value, instr);
2366
+ break;
2367
+ case LWC1:
2368
+ set_fpu_register(ft_reg, alu_out);
2369
+ break;
2370
+ case LDC1:
2371
+ set_fpu_register_double(ft_reg, fp_out);
2372
+ break;
2373
+ case SWC1:
2374
+ addr = rs + se_imm16;
2375
+ WriteW(addr, get_fpu_register(ft_reg), instr);
2376
+ break;
2377
+ case SDC1:
2378
+ addr = rs + se_imm16;
2379
+ WriteD(addr, get_fpu_register_double(ft_reg), instr);
2380
+ break;
2381
+ default:
2382
+ break;
2383
+ };
2384
+
2385
+
2386
+ if (execute_branch_delay_instruction) {
2387
+ // Execute branch delay slot
2388
+ // We don't check for end_sim_pc. First it should not be met as the current
2389
+ // pc is valid. Secondly a jump should always execute its branch delay slot.
2390
+ Instruction* branch_delay_instr =
2391
+ reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
2392
+ BranchDelayInstructionDecode(branch_delay_instr);
2393
+ }
2394
+
2395
+ // If needed update pc after the branch delay execution.
2396
+ if (next_pc != bad_ra) {
2397
+ set_pc(next_pc);
2398
+ }
2399
+ }
2400
+
2401
+
2402
+ // Type 3: instructions using a 26 bytes immediate. (eg: j, jal).
2403
+ void Simulator::DecodeTypeJump(Instruction* instr) {
2404
+ // Get current pc.
2405
+ int32_t current_pc = get_pc();
2406
+ // Get unchanged bits of pc.
2407
+ int32_t pc_high_bits = current_pc & 0xf0000000;
2408
+ // Next pc.
2409
+ int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2410
+
2411
+ // Execute branch delay slot.
2412
+ // We don't check for end_sim_pc. First it should not be met as the current pc
2413
+ // is valid. Secondly a jump should always execute its branch delay slot.
2414
+ Instruction* branch_delay_instr =
2415
+ reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
2416
+ BranchDelayInstructionDecode(branch_delay_instr);
2417
+
2418
+ // Update pc and ra if necessary.
2419
+ // Do this after the branch delay execution.
2420
+ if (instr->IsLinkingInstruction()) {
2421
+ set_register(31, current_pc + 2 * Instruction::kInstrSize);
2422
+ }
2423
+ set_pc(next_pc);
2424
+ pc_modified_ = true;
2425
+ }
2426
+
2427
+
2428
+ // Executes the current instruction.
2429
+ void Simulator::InstructionDecode(Instruction* instr) {
2430
+ if (v8::internal::FLAG_check_icache) {
2431
+ CheckICache(isolate_->simulator_i_cache(), instr);
2432
+ }
2433
+ pc_modified_ = false;
2434
+ if (::v8::internal::FLAG_trace_sim) {
2435
+ disasm::NameConverter converter;
2436
+ disasm::Disassembler dasm(converter);
2437
+ // Use a reasonably large buffer.
2438
+ v8::internal::EmbeddedVector<char, 256> buffer;
2439
+ dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2440
+ PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
2441
+ buffer.start());
2442
+ }
2443
+
2444
+ switch (instr->InstructionType()) {
2445
+ case Instruction::kRegisterType:
2446
+ DecodeTypeRegister(instr);
2447
+ break;
2448
+ case Instruction::kImmediateType:
2449
+ DecodeTypeImmediate(instr);
2450
+ break;
2451
+ case Instruction::kJumpType:
2452
+ DecodeTypeJump(instr);
2453
+ break;
2454
+ default:
2455
+ UNSUPPORTED();
2456
+ }
2457
+ if (!pc_modified_) {
2458
+ set_register(pc, reinterpret_cast<int32_t>(instr) +
2459
+ Instruction::kInstrSize);
2460
+ }
2461
+ }
2462
+
2463
+
2464
+
2465
+ void Simulator::Execute() {
2466
+ // Get the PC to simulate. Cannot use the accessor here as we need the
2467
+ // raw PC value and not the one used as input to arithmetic instructions.
2468
+ int program_counter = get_pc();
2469
+ if (::v8::internal::FLAG_stop_sim_at == 0) {
2470
+ // Fast version of the dispatch loop without checking whether the simulator
2471
+ // should be stopping at a particular executed instruction.
2472
+ while (program_counter != end_sim_pc) {
2473
+ Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2474
+ icount_++;
2475
+ InstructionDecode(instr);
2476
+ program_counter = get_pc();
2477
+ }
2478
+ } else {
2479
+ // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2480
+ // we reach the particular instuction count.
2481
+ while (program_counter != end_sim_pc) {
2482
+ Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2483
+ icount_++;
2484
+ if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2485
+ MipsDebugger dbg(this);
2486
+ dbg.Debug();
2487
+ } else {
2488
+ InstructionDecode(instr);
2489
+ }
2490
+ program_counter = get_pc();
2491
+ }
2492
+ }
2493
+ }
2494
+
2495
+
2496
+ int32_t Simulator::Call(byte* entry, int argument_count, ...) {
2497
+ va_list parameters;
2498
+ va_start(parameters, argument_count);
2499
+ // Setup arguments.
2500
+
2501
+ // First four arguments passed in registers.
2502
+ ASSERT(argument_count >= 4);
2503
+ set_register(a0, va_arg(parameters, int32_t));
2504
+ set_register(a1, va_arg(parameters, int32_t));
2505
+ set_register(a2, va_arg(parameters, int32_t));
2506
+ set_register(a3, va_arg(parameters, int32_t));
2507
+
2508
+ // Remaining arguments passed on stack.
2509
+ int original_stack = get_register(sp);
2510
+ // Compute position of stack on entry to generated code.
2511
+ int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
2512
+ - kCArgsSlotsSize);
2513
+ if (OS::ActivationFrameAlignment() != 0) {
2514
+ entry_stack &= -OS::ActivationFrameAlignment();
2515
+ }
2516
+ // Store remaining arguments on stack, from low to high memory.
2517
+ intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
2518
+ for (int i = 4; i < argument_count; i++) {
2519
+ stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t);
2520
+ }
2521
+ va_end(parameters);
2522
+ set_register(sp, entry_stack);
2523
+
2524
+ // Prepare to execute the code at entry.
2525
+ set_register(pc, reinterpret_cast<int32_t>(entry));
2526
+ // Put down marker for end of simulation. The simulator will stop simulation
2527
+ // when the PC reaches this value. By saving the "end simulation" value into
2528
+ // the LR the simulation stops when returning to this call point.
2529
+ set_register(ra, end_sim_pc);
2530
+
2531
+ // Remember the values of callee-saved registers.
2532
+ // The code below assumes that r9 is not used as sb (static base) in
2533
+ // simulator code and therefore is regarded as a callee-saved register.
2534
+ int32_t s0_val = get_register(s0);
2535
+ int32_t s1_val = get_register(s1);
2536
+ int32_t s2_val = get_register(s2);
2537
+ int32_t s3_val = get_register(s3);
2538
+ int32_t s4_val = get_register(s4);
2539
+ int32_t s5_val = get_register(s5);
2540
+ int32_t s6_val = get_register(s6);
2541
+ int32_t s7_val = get_register(s7);
2542
+ int32_t gp_val = get_register(gp);
2543
+ int32_t sp_val = get_register(sp);
2544
+ int32_t fp_val = get_register(fp);
2545
+
2546
+ // Setup the callee-saved registers with a known value. To be able to check
2547
+ // that they are preserved properly across JS execution.
2548
+ int32_t callee_saved_value = icount_;
2549
+ set_register(s0, callee_saved_value);
2550
+ set_register(s1, callee_saved_value);
2551
+ set_register(s2, callee_saved_value);
2552
+ set_register(s3, callee_saved_value);
2553
+ set_register(s4, callee_saved_value);
2554
+ set_register(s5, callee_saved_value);
2555
+ set_register(s6, callee_saved_value);
2556
+ set_register(s7, callee_saved_value);
2557
+ set_register(gp, callee_saved_value);
2558
+ set_register(fp, callee_saved_value);
2559
+
2560
+ // Start the simulation.
2561
+ Execute();
2562
+
2563
+ // Check that the callee-saved registers have been preserved.
2564
+ CHECK_EQ(callee_saved_value, get_register(s0));
2565
+ CHECK_EQ(callee_saved_value, get_register(s1));
2566
+ CHECK_EQ(callee_saved_value, get_register(s2));
2567
+ CHECK_EQ(callee_saved_value, get_register(s3));
2568
+ CHECK_EQ(callee_saved_value, get_register(s4));
2569
+ CHECK_EQ(callee_saved_value, get_register(s5));
2570
+ CHECK_EQ(callee_saved_value, get_register(s6));
2571
+ CHECK_EQ(callee_saved_value, get_register(s7));
2572
+ CHECK_EQ(callee_saved_value, get_register(gp));
2573
+ CHECK_EQ(callee_saved_value, get_register(fp));
2574
+
2575
+ // Restore callee-saved registers with the original value.
2576
+ set_register(s0, s0_val);
2577
+ set_register(s1, s1_val);
2578
+ set_register(s2, s2_val);
2579
+ set_register(s3, s3_val);
2580
+ set_register(s4, s4_val);
2581
+ set_register(s5, s5_val);
2582
+ set_register(s6, s6_val);
2583
+ set_register(s7, s7_val);
2584
+ set_register(gp, gp_val);
2585
+ set_register(sp, sp_val);
2586
+ set_register(fp, fp_val);
2587
+
2588
+ // Pop stack passed arguments.
2589
+ CHECK_EQ(entry_stack, get_register(sp));
2590
+ set_register(sp, original_stack);
2591
+
2592
+ int32_t result = get_register(v0);
2593
+ return result;
2594
+ }
2595
+
2596
+
2597
+ uintptr_t Simulator::PushAddress(uintptr_t address) {
2598
+ int new_sp = get_register(sp) - sizeof(uintptr_t);
2599
+ uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
2600
+ *stack_slot = address;
2601
+ set_register(sp, new_sp);
2602
+ return new_sp;
2603
+ }
2604
+
2605
+
2606
+ uintptr_t Simulator::PopAddress() {
2607
+ int current_sp = get_register(sp);
2608
+ uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2609
+ uintptr_t address = *stack_slot;
2610
+ set_register(sp, current_sp + sizeof(uintptr_t));
2611
+ return address;
2612
+ }
2613
+
2614
+
2615
+ #undef UNSUPPORTED
2616
+
2617
+ } } // namespace v8::internal
2618
+
2619
+ #endif // USE_SIMULATOR
2620
+
2621
+ #endif // V8_TARGET_ARCH_MIPS