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,253 @@
1
+ // Copyright 2006-2008 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
+ #ifndef V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
29
+ #define V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
30
+
31
+ namespace v8 {
32
+ namespace internal {
33
+
34
+
35
+ #ifdef V8_INTERPRETED_REGEXP
36
+ class RegExpMacroAssemblerARM: public RegExpMacroAssembler {
37
+ public:
38
+ RegExpMacroAssemblerARM();
39
+ virtual ~RegExpMacroAssemblerARM();
40
+ };
41
+
42
+ #else // V8_INTERPRETED_REGEXP
43
+ class RegExpMacroAssemblerARM: public NativeRegExpMacroAssembler {
44
+ public:
45
+ RegExpMacroAssemblerARM(Mode mode, int registers_to_save);
46
+ virtual ~RegExpMacroAssemblerARM();
47
+ virtual int stack_limit_slack();
48
+ virtual void AdvanceCurrentPosition(int by);
49
+ virtual void AdvanceRegister(int reg, int by);
50
+ virtual void Backtrack();
51
+ virtual void Bind(Label* label);
52
+ virtual void CheckAtStart(Label* on_at_start);
53
+ virtual void CheckCharacter(unsigned c, Label* on_equal);
54
+ virtual void CheckCharacterAfterAnd(unsigned c,
55
+ unsigned mask,
56
+ Label* on_equal);
57
+ virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
58
+ virtual void CheckCharacterLT(uc16 limit, Label* on_less);
59
+ virtual void CheckCharacters(Vector<const uc16> str,
60
+ int cp_offset,
61
+ Label* on_failure,
62
+ bool check_end_of_string);
63
+ // A "greedy loop" is a loop that is both greedy and with a simple
64
+ // body. It has a particularly simple implementation.
65
+ virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
66
+ virtual void CheckNotAtStart(Label* on_not_at_start);
67
+ virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
68
+ virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
69
+ Label* on_no_match);
70
+ virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
71
+ virtual void CheckNotCharacter(unsigned c, Label* on_not_equal);
72
+ virtual void CheckNotCharacterAfterAnd(unsigned c,
73
+ unsigned mask,
74
+ Label* on_not_equal);
75
+ virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
76
+ uc16 minus,
77
+ uc16 mask,
78
+ Label* on_not_equal);
79
+ // Checks whether the given offset from the current position is before
80
+ // the end of the string.
81
+ virtual void CheckPosition(int cp_offset, Label* on_outside_input);
82
+ virtual bool CheckSpecialCharacterClass(uc16 type,
83
+ Label* on_no_match);
84
+ virtual void Fail();
85
+ virtual Handle<HeapObject> GetCode(Handle<String> source);
86
+ virtual void GoTo(Label* label);
87
+ virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
88
+ virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
89
+ virtual void IfRegisterEqPos(int reg, Label* if_eq);
90
+ virtual IrregexpImplementation Implementation();
91
+ virtual void LoadCurrentCharacter(int cp_offset,
92
+ Label* on_end_of_input,
93
+ bool check_bounds = true,
94
+ int characters = 1);
95
+ virtual void PopCurrentPosition();
96
+ virtual void PopRegister(int register_index);
97
+ virtual void PushBacktrack(Label* label);
98
+ virtual void PushCurrentPosition();
99
+ virtual void PushRegister(int register_index,
100
+ StackCheckFlag check_stack_limit);
101
+ virtual void ReadCurrentPositionFromRegister(int reg);
102
+ virtual void ReadStackPointerFromRegister(int reg);
103
+ virtual void SetCurrentPositionFromEnd(int by);
104
+ virtual void SetRegister(int register_index, int to);
105
+ virtual void Succeed();
106
+ virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
107
+ virtual void ClearRegisters(int reg_from, int reg_to);
108
+ virtual void WriteStackPointerToRegister(int reg);
109
+
110
+ // Called from RegExp if the stack-guard is triggered.
111
+ // If the code object is relocated, the return address is fixed before
112
+ // returning.
113
+ static int CheckStackGuardState(Address* return_address,
114
+ Code* re_code,
115
+ Address re_frame);
116
+ private:
117
+ // Offsets from frame_pointer() of function parameters and stored registers.
118
+ static const int kFramePointer = 0;
119
+
120
+ // Above the frame pointer - Stored registers and stack passed parameters.
121
+ // Register 4..11.
122
+ static const int kStoredRegisters = kFramePointer;
123
+ // Return address (stored from link register, read into pc on return).
124
+ static const int kReturnAddress = kStoredRegisters + 8 * kPointerSize;
125
+ static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
126
+ // Stack parameters placed by caller.
127
+ static const int kRegisterOutput = kSecondaryReturnAddress + kPointerSize;
128
+ static const int kStackHighEnd = kRegisterOutput + kPointerSize;
129
+ static const int kDirectCall = kStackHighEnd + kPointerSize;
130
+ static const int kIsolate = kDirectCall + kPointerSize;
131
+
132
+ // Below the frame pointer.
133
+ // Register parameters stored by setup code.
134
+ static const int kInputEnd = kFramePointer - kPointerSize;
135
+ static const int kInputStart = kInputEnd - kPointerSize;
136
+ static const int kStartIndex = kInputStart - kPointerSize;
137
+ static const int kInputString = kStartIndex - kPointerSize;
138
+ // When adding local variables remember to push space for them in
139
+ // the frame in GetCode.
140
+ static const int kInputStartMinusOne = kInputString - kPointerSize;
141
+ static const int kAtStart = kInputStartMinusOne - kPointerSize;
142
+ // First register address. Following registers are below it on the stack.
143
+ static const int kRegisterZero = kAtStart - kPointerSize;
144
+
145
+ // Initial size of code buffer.
146
+ static const size_t kRegExpCodeSize = 1024;
147
+
148
+ static const int kBacktrackConstantPoolSize = 4;
149
+
150
+ // Load a number of characters at the given offset from the
151
+ // current position, into the current-character register.
152
+ void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
153
+
154
+ // Check whether preemption has been requested.
155
+ void CheckPreemption();
156
+
157
+ // Check whether we are exceeding the stack limit on the backtrack stack.
158
+ void CheckStackLimit();
159
+
160
+ void EmitBacktrackConstantPool();
161
+ int GetBacktrackConstantPoolEntry();
162
+
163
+
164
+ // Generate a call to CheckStackGuardState.
165
+ void CallCheckStackGuardState(Register scratch);
166
+
167
+ // The ebp-relative location of a regexp register.
168
+ MemOperand register_location(int register_index);
169
+
170
+ // Register holding the current input position as negative offset from
171
+ // the end of the string.
172
+ inline Register current_input_offset() { return r6; }
173
+
174
+ // The register containing the current character after LoadCurrentCharacter.
175
+ inline Register current_character() { return r7; }
176
+
177
+ // Register holding address of the end of the input string.
178
+ inline Register end_of_input_address() { return r10; }
179
+
180
+ // Register holding the frame address. Local variables, parameters and
181
+ // regexp registers are addressed relative to this.
182
+ inline Register frame_pointer() { return fp; }
183
+
184
+ // The register containing the backtrack stack top. Provides a meaningful
185
+ // name to the register.
186
+ inline Register backtrack_stackpointer() { return r8; }
187
+
188
+ // Register holding pointer to the current code object.
189
+ inline Register code_pointer() { return r5; }
190
+
191
+ // Byte size of chars in the string to match (decided by the Mode argument)
192
+ inline int char_size() { return static_cast<int>(mode_); }
193
+
194
+ // Equivalent to a conditional branch to the label, unless the label
195
+ // is NULL, in which case it is a conditional Backtrack.
196
+ void BranchOrBacktrack(Condition condition, Label* to);
197
+
198
+ // Call and return internally in the generated code in a way that
199
+ // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
200
+ inline void SafeCall(Label* to, Condition cond = al);
201
+ inline void SafeReturn();
202
+ inline void SafeCallTarget(Label* name);
203
+
204
+ // Pushes the value of a register on the backtrack stack. Decrements the
205
+ // stack pointer by a word size and stores the register's value there.
206
+ inline void Push(Register source);
207
+
208
+ // Pops a value from the backtrack stack. Reads the word at the stack pointer
209
+ // and increments it by a word size.
210
+ inline void Pop(Register target);
211
+
212
+ // Calls a C function and cleans up the frame alignment done by
213
+ // by FrameAlign. The called function *is* allowed to trigger a garbage
214
+ // collection, but may not take more than four arguments (no arguments
215
+ // passed on the stack), and the first argument will be a pointer to the
216
+ // return address.
217
+ inline void CallCFunctionUsingStub(ExternalReference function,
218
+ int num_arguments);
219
+
220
+
221
+ MacroAssembler* masm_;
222
+
223
+ // Which mode to generate code for (ASCII or UC16).
224
+ Mode mode_;
225
+
226
+ // One greater than maximal register index actually used.
227
+ int num_registers_;
228
+
229
+ // Number of registers to output at the end (the saved registers
230
+ // are always 0..num_saved_registers_-1)
231
+ int num_saved_registers_;
232
+
233
+ // Manage a small pre-allocated pool for writing label targets
234
+ // to for pushing backtrack addresses.
235
+ int backtrack_constant_pool_offset_;
236
+ int backtrack_constant_pool_capacity_;
237
+
238
+ // Labels used internally.
239
+ Label entry_label_;
240
+ Label start_label_;
241
+ Label success_label_;
242
+ Label backtrack_label_;
243
+ Label exit_label_;
244
+ Label check_preempt_label_;
245
+ Label stack_overflow_label_;
246
+ };
247
+
248
+ #endif // V8_INTERPRETED_REGEXP
249
+
250
+
251
+ }} // namespace v8::internal
252
+
253
+ #endif // V8_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
@@ -0,0 +1,3424 @@
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 <cstdarg>
31
+ #include "v8.h"
32
+
33
+ #if defined(V8_TARGET_ARCH_ARM)
34
+
35
+ #include "disasm.h"
36
+ #include "assembler.h"
37
+ #include "arm/constants-arm.h"
38
+ #include "arm/simulator-arm.h"
39
+
40
+ #if defined(USE_SIMULATOR)
41
+
42
+ // Only build the simulator if not compiling for real ARM hardware.
43
+ namespace v8 {
44
+ namespace internal {
45
+
46
+ // This macro provides a platform independent use of sscanf. The reason for
47
+ // SScanF not being implemented in a platform independent way through
48
+ // ::v8::internal::OS in the same way as SNPrintF is that the
49
+ // Windows C Run-Time Library does not provide vsscanf.
50
+ #define SScanF sscanf // NOLINT
51
+
52
+ // The ArmDebugger class is used by the simulator while debugging simulated ARM
53
+ // code.
54
+ class ArmDebugger {
55
+ public:
56
+ explicit ArmDebugger(Simulator* sim);
57
+ ~ArmDebugger();
58
+
59
+ void Stop(Instruction* instr);
60
+ void Debug();
61
+
62
+ private:
63
+ static const Instr kBreakpointInstr =
64
+ (al | (7*B25) | (1*B24) | kBreakpoint);
65
+ static const Instr kNopInstr = (al | (13*B21));
66
+
67
+ Simulator* sim_;
68
+
69
+ int32_t GetRegisterValue(int regnum);
70
+ double GetRegisterPairDoubleValue(int regnum);
71
+ double GetVFPDoubleRegisterValue(int regnum);
72
+ bool GetValue(const char* desc, int32_t* value);
73
+ bool GetVFPSingleValue(const char* desc, float* value);
74
+ bool GetVFPDoubleValue(const char* desc, double* value);
75
+
76
+ // Set or delete a breakpoint. Returns true if successful.
77
+ bool SetBreakpoint(Instruction* breakpc);
78
+ bool DeleteBreakpoint(Instruction* breakpc);
79
+
80
+ // Undo and redo all breakpoints. This is needed to bracket disassembly and
81
+ // execution to skip past breakpoints when run from the debugger.
82
+ void UndoBreakpoints();
83
+ void RedoBreakpoints();
84
+ };
85
+
86
+
87
+ ArmDebugger::ArmDebugger(Simulator* sim) {
88
+ sim_ = sim;
89
+ }
90
+
91
+
92
+ ArmDebugger::~ArmDebugger() {
93
+ }
94
+
95
+
96
+
97
+ #ifdef GENERATED_CODE_COVERAGE
98
+ static FILE* coverage_log = NULL;
99
+
100
+
101
+ static void InitializeCoverage() {
102
+ char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
103
+ if (file_name != NULL) {
104
+ coverage_log = fopen(file_name, "aw+");
105
+ }
106
+ }
107
+
108
+
109
+ void ArmDebugger::Stop(Instruction* instr) {
110
+ // Get the stop code.
111
+ uint32_t code = instr->SvcValue() & kStopCodeMask;
112
+ // Retrieve the encoded address, which comes just after this stop.
113
+ char** msg_address =
114
+ reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
115
+ char* msg = *msg_address;
116
+ ASSERT(msg != NULL);
117
+
118
+ // Update this stop description.
119
+ if (isWatchedStop(code) && !watched_stops[code].desc) {
120
+ watched_stops[code].desc = msg;
121
+ }
122
+
123
+ if (strlen(msg) > 0) {
124
+ if (coverage_log != NULL) {
125
+ fprintf(coverage_log, "%s\n", msg);
126
+ fflush(coverage_log);
127
+ }
128
+ // Overwrite the instruction and address with nops.
129
+ instr->SetInstructionBits(kNopInstr);
130
+ reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr);
131
+ }
132
+ sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
133
+ }
134
+
135
+ #else // ndef GENERATED_CODE_COVERAGE
136
+
137
+ static void InitializeCoverage() {
138
+ }
139
+
140
+
141
+ void ArmDebugger::Stop(Instruction* instr) {
142
+ // Get the stop code.
143
+ uint32_t code = instr->SvcValue() & kStopCodeMask;
144
+ // Retrieve the encoded address, which comes just after this stop.
145
+ char* msg = *reinterpret_cast<char**>(sim_->get_pc()
146
+ + Instruction::kInstrSize);
147
+ // Update this stop description.
148
+ if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) {
149
+ sim_->watched_stops[code].desc = msg;
150
+ }
151
+ // Print the stop message and code if it is not the default code.
152
+ if (code != kMaxStopCode) {
153
+ PrintF("Simulator hit stop %u: %s\n", code, msg);
154
+ } else {
155
+ PrintF("Simulator hit %s\n", msg);
156
+ }
157
+ sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
158
+ Debug();
159
+ }
160
+ #endif
161
+
162
+
163
+ int32_t ArmDebugger::GetRegisterValue(int regnum) {
164
+ if (regnum == kPCRegister) {
165
+ return sim_->get_pc();
166
+ } else {
167
+ return sim_->get_register(regnum);
168
+ }
169
+ }
170
+
171
+
172
+ double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
173
+ return sim_->get_double_from_register_pair(regnum);
174
+ }
175
+
176
+
177
+ double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
178
+ return sim_->get_double_from_d_register(regnum);
179
+ }
180
+
181
+
182
+ bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
183
+ int regnum = Registers::Number(desc);
184
+ if (regnum != kNoRegister) {
185
+ *value = GetRegisterValue(regnum);
186
+ return true;
187
+ } else {
188
+ if (strncmp(desc, "0x", 2) == 0) {
189
+ return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
190
+ } else {
191
+ return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
192
+ }
193
+ }
194
+ return false;
195
+ }
196
+
197
+
198
+ bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
199
+ bool is_double;
200
+ int regnum = VFPRegisters::Number(desc, &is_double);
201
+ if (regnum != kNoRegister && !is_double) {
202
+ *value = sim_->get_float_from_s_register(regnum);
203
+ return true;
204
+ }
205
+ return false;
206
+ }
207
+
208
+
209
+ bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
210
+ bool is_double;
211
+ int regnum = VFPRegisters::Number(desc, &is_double);
212
+ if (regnum != kNoRegister && is_double) {
213
+ *value = sim_->get_double_from_d_register(regnum);
214
+ return true;
215
+ }
216
+ return false;
217
+ }
218
+
219
+
220
+ bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
221
+ // Check if a breakpoint can be set. If not return without any side-effects.
222
+ if (sim_->break_pc_ != NULL) {
223
+ return false;
224
+ }
225
+
226
+ // Set the breakpoint.
227
+ sim_->break_pc_ = breakpc;
228
+ sim_->break_instr_ = breakpc->InstructionBits();
229
+ // Not setting the breakpoint instruction in the code itself. It will be set
230
+ // when the debugger shell continues.
231
+ return true;
232
+ }
233
+
234
+
235
+ bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
236
+ if (sim_->break_pc_ != NULL) {
237
+ sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
238
+ }
239
+
240
+ sim_->break_pc_ = NULL;
241
+ sim_->break_instr_ = 0;
242
+ return true;
243
+ }
244
+
245
+
246
+ void ArmDebugger::UndoBreakpoints() {
247
+ if (sim_->break_pc_ != NULL) {
248
+ sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
249
+ }
250
+ }
251
+
252
+
253
+ void ArmDebugger::RedoBreakpoints() {
254
+ if (sim_->break_pc_ != NULL) {
255
+ sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
256
+ }
257
+ }
258
+
259
+
260
+ void ArmDebugger::Debug() {
261
+ intptr_t last_pc = -1;
262
+ bool done = false;
263
+
264
+ #define COMMAND_SIZE 63
265
+ #define ARG_SIZE 255
266
+
267
+ #define STR(a) #a
268
+ #define XSTR(a) STR(a)
269
+
270
+ char cmd[COMMAND_SIZE + 1];
271
+ char arg1[ARG_SIZE + 1];
272
+ char arg2[ARG_SIZE + 1];
273
+ char* argv[3] = { cmd, arg1, arg2 };
274
+
275
+ // make sure to have a proper terminating character if reaching the limit
276
+ cmd[COMMAND_SIZE] = 0;
277
+ arg1[ARG_SIZE] = 0;
278
+ arg2[ARG_SIZE] = 0;
279
+
280
+ // Undo all set breakpoints while running in the debugger shell. This will
281
+ // make them invisible to all commands.
282
+ UndoBreakpoints();
283
+
284
+ while (!done) {
285
+ if (last_pc != sim_->get_pc()) {
286
+ disasm::NameConverter converter;
287
+ disasm::Disassembler dasm(converter);
288
+ // use a reasonably large buffer
289
+ v8::internal::EmbeddedVector<char, 256> buffer;
290
+ dasm.InstructionDecode(buffer,
291
+ reinterpret_cast<byte*>(sim_->get_pc()));
292
+ PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
293
+ last_pc = sim_->get_pc();
294
+ }
295
+ char* line = ReadLine("sim> ");
296
+ if (line == NULL) {
297
+ break;
298
+ } else {
299
+ // Use sscanf to parse the individual parts of the command line. At the
300
+ // moment no command expects more than two parameters.
301
+ int argc = SScanF(line,
302
+ "%" XSTR(COMMAND_SIZE) "s "
303
+ "%" XSTR(ARG_SIZE) "s "
304
+ "%" XSTR(ARG_SIZE) "s",
305
+ cmd, arg1, arg2);
306
+ if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
307
+ sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
308
+ } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
309
+ // Execute the one instruction we broke at with breakpoints disabled.
310
+ sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
311
+ // Leave the debugger shell.
312
+ done = true;
313
+ } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
314
+ if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
315
+ int32_t value;
316
+ float svalue;
317
+ double dvalue;
318
+ if (strcmp(arg1, "all") == 0) {
319
+ for (int i = 0; i < kNumRegisters; i++) {
320
+ value = GetRegisterValue(i);
321
+ PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value);
322
+ if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
323
+ i < 8 &&
324
+ (i % 2) == 0) {
325
+ dvalue = GetRegisterPairDoubleValue(i);
326
+ PrintF(" (%f)\n", dvalue);
327
+ } else {
328
+ PrintF("\n");
329
+ }
330
+ }
331
+ for (int i = 0; i < kNumVFPDoubleRegisters; i++) {
332
+ dvalue = GetVFPDoubleRegisterValue(i);
333
+ uint64_t as_words = BitCast<uint64_t>(dvalue);
334
+ PrintF("%3s: %f 0x%08x %08x\n",
335
+ VFPRegisters::Name(i, true),
336
+ dvalue,
337
+ static_cast<uint32_t>(as_words >> 32),
338
+ static_cast<uint32_t>(as_words & 0xffffffff));
339
+ }
340
+ } else {
341
+ if (GetValue(arg1, &value)) {
342
+ PrintF("%s: 0x%08x %d \n", arg1, value, value);
343
+ } else if (GetVFPSingleValue(arg1, &svalue)) {
344
+ uint32_t as_word = BitCast<uint32_t>(svalue);
345
+ PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
346
+ } else if (GetVFPDoubleValue(arg1, &dvalue)) {
347
+ uint64_t as_words = BitCast<uint64_t>(dvalue);
348
+ PrintF("%s: %f 0x%08x %08x\n",
349
+ arg1,
350
+ dvalue,
351
+ static_cast<uint32_t>(as_words >> 32),
352
+ static_cast<uint32_t>(as_words & 0xffffffff));
353
+ } else {
354
+ PrintF("%s unrecognized\n", arg1);
355
+ }
356
+ }
357
+ } else {
358
+ PrintF("print <register>\n");
359
+ }
360
+ } else if ((strcmp(cmd, "po") == 0)
361
+ || (strcmp(cmd, "printobject") == 0)) {
362
+ if (argc == 2) {
363
+ int32_t value;
364
+ if (GetValue(arg1, &value)) {
365
+ Object* obj = reinterpret_cast<Object*>(value);
366
+ PrintF("%s: \n", arg1);
367
+ #ifdef DEBUG
368
+ obj->PrintLn();
369
+ #else
370
+ obj->ShortPrint();
371
+ PrintF("\n");
372
+ #endif
373
+ } else {
374
+ PrintF("%s unrecognized\n", arg1);
375
+ }
376
+ } else {
377
+ PrintF("printobject <value>\n");
378
+ }
379
+ } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
380
+ int32_t* cur = NULL;
381
+ int32_t* end = NULL;
382
+ int next_arg = 1;
383
+
384
+ if (strcmp(cmd, "stack") == 0) {
385
+ cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
386
+ } else { // "mem"
387
+ int32_t value;
388
+ if (!GetValue(arg1, &value)) {
389
+ PrintF("%s unrecognized\n", arg1);
390
+ continue;
391
+ }
392
+ cur = reinterpret_cast<int32_t*>(value);
393
+ next_arg++;
394
+ }
395
+
396
+ int32_t words;
397
+ if (argc == next_arg) {
398
+ words = 10;
399
+ } else if (argc == next_arg + 1) {
400
+ if (!GetValue(argv[next_arg], &words)) {
401
+ words = 10;
402
+ }
403
+ }
404
+ end = cur + words;
405
+
406
+ while (cur < end) {
407
+ PrintF(" 0x%08x: 0x%08x %10d",
408
+ reinterpret_cast<intptr_t>(cur), *cur, *cur);
409
+ HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
410
+ int value = *cur;
411
+ Heap* current_heap = v8::internal::Isolate::Current()->heap();
412
+ if (current_heap->Contains(obj) || ((value & 1) == 0)) {
413
+ PrintF(" (");
414
+ if ((value & 1) == 0) {
415
+ PrintF("smi %d", value / 2);
416
+ } else {
417
+ obj->ShortPrint();
418
+ }
419
+ PrintF(")");
420
+ }
421
+ PrintF("\n");
422
+ cur++;
423
+ }
424
+ } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
425
+ disasm::NameConverter converter;
426
+ disasm::Disassembler dasm(converter);
427
+ // use a reasonably large buffer
428
+ v8::internal::EmbeddedVector<char, 256> buffer;
429
+
430
+ byte* prev = NULL;
431
+ byte* cur = NULL;
432
+ byte* end = NULL;
433
+
434
+ if (argc == 1) {
435
+ cur = reinterpret_cast<byte*>(sim_->get_pc());
436
+ end = cur + (10 * Instruction::kInstrSize);
437
+ } else if (argc == 2) {
438
+ int regnum = Registers::Number(arg1);
439
+ if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
440
+ // The argument is an address or a register name.
441
+ int32_t value;
442
+ if (GetValue(arg1, &value)) {
443
+ cur = reinterpret_cast<byte*>(value);
444
+ // Disassemble 10 instructions at <arg1>.
445
+ end = cur + (10 * Instruction::kInstrSize);
446
+ }
447
+ } else {
448
+ // The argument is the number of instructions.
449
+ int32_t value;
450
+ if (GetValue(arg1, &value)) {
451
+ cur = reinterpret_cast<byte*>(sim_->get_pc());
452
+ // Disassemble <arg1> instructions.
453
+ end = cur + (value * Instruction::kInstrSize);
454
+ }
455
+ }
456
+ } else {
457
+ int32_t value1;
458
+ int32_t value2;
459
+ if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
460
+ cur = reinterpret_cast<byte*>(value1);
461
+ end = cur + (value2 * Instruction::kInstrSize);
462
+ }
463
+ }
464
+
465
+ while (cur < end) {
466
+ prev = cur;
467
+ cur += dasm.InstructionDecode(buffer, cur);
468
+ PrintF(" 0x%08x %s\n",
469
+ reinterpret_cast<intptr_t>(prev), buffer.start());
470
+ }
471
+ } else if (strcmp(cmd, "gdb") == 0) {
472
+ PrintF("relinquishing control to gdb\n");
473
+ v8::internal::OS::DebugBreak();
474
+ PrintF("regaining control from gdb\n");
475
+ } else if (strcmp(cmd, "break") == 0) {
476
+ if (argc == 2) {
477
+ int32_t value;
478
+ if (GetValue(arg1, &value)) {
479
+ if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
480
+ PrintF("setting breakpoint failed\n");
481
+ }
482
+ } else {
483
+ PrintF("%s unrecognized\n", arg1);
484
+ }
485
+ } else {
486
+ PrintF("break <address>\n");
487
+ }
488
+ } else if (strcmp(cmd, "del") == 0) {
489
+ if (!DeleteBreakpoint(NULL)) {
490
+ PrintF("deleting breakpoint failed\n");
491
+ }
492
+ } else if (strcmp(cmd, "flags") == 0) {
493
+ PrintF("N flag: %d; ", sim_->n_flag_);
494
+ PrintF("Z flag: %d; ", sim_->z_flag_);
495
+ PrintF("C flag: %d; ", sim_->c_flag_);
496
+ PrintF("V flag: %d\n", sim_->v_flag_);
497
+ PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
498
+ PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
499
+ PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
500
+ PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
501
+ PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
502
+ } else if (strcmp(cmd, "stop") == 0) {
503
+ int32_t value;
504
+ intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize;
505
+ Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
506
+ Instruction* msg_address =
507
+ reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
508
+ if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
509
+ // Remove the current stop.
510
+ if (sim_->isStopInstruction(stop_instr)) {
511
+ stop_instr->SetInstructionBits(kNopInstr);
512
+ msg_address->SetInstructionBits(kNopInstr);
513
+ } else {
514
+ PrintF("Not at debugger stop.\n");
515
+ }
516
+ } else if (argc == 3) {
517
+ // Print information about all/the specified breakpoint(s).
518
+ if (strcmp(arg1, "info") == 0) {
519
+ if (strcmp(arg2, "all") == 0) {
520
+ PrintF("Stop information:\n");
521
+ for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
522
+ sim_->PrintStopInfo(i);
523
+ }
524
+ } else if (GetValue(arg2, &value)) {
525
+ sim_->PrintStopInfo(value);
526
+ } else {
527
+ PrintF("Unrecognized argument.\n");
528
+ }
529
+ } else if (strcmp(arg1, "enable") == 0) {
530
+ // Enable all/the specified breakpoint(s).
531
+ if (strcmp(arg2, "all") == 0) {
532
+ for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
533
+ sim_->EnableStop(i);
534
+ }
535
+ } else if (GetValue(arg2, &value)) {
536
+ sim_->EnableStop(value);
537
+ } else {
538
+ PrintF("Unrecognized argument.\n");
539
+ }
540
+ } else if (strcmp(arg1, "disable") == 0) {
541
+ // Disable all/the specified breakpoint(s).
542
+ if (strcmp(arg2, "all") == 0) {
543
+ for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
544
+ sim_->DisableStop(i);
545
+ }
546
+ } else if (GetValue(arg2, &value)) {
547
+ sim_->DisableStop(value);
548
+ } else {
549
+ PrintF("Unrecognized argument.\n");
550
+ }
551
+ }
552
+ } else {
553
+ PrintF("Wrong usage. Use help command for more information.\n");
554
+ }
555
+ } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
556
+ ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
557
+ PrintF("Trace of executed instructions is %s\n",
558
+ ::v8::internal::FLAG_trace_sim ? "on" : "off");
559
+ } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
560
+ PrintF("cont\n");
561
+ PrintF(" continue execution (alias 'c')\n");
562
+ PrintF("stepi\n");
563
+ PrintF(" step one instruction (alias 'si')\n");
564
+ PrintF("print <register>\n");
565
+ PrintF(" print register content (alias 'p')\n");
566
+ PrintF(" use register name 'all' to print all registers\n");
567
+ PrintF(" add argument 'fp' to print register pair double values\n");
568
+ PrintF("printobject <register>\n");
569
+ PrintF(" print an object from a register (alias 'po')\n");
570
+ PrintF("flags\n");
571
+ PrintF(" print flags\n");
572
+ PrintF("stack [<words>]\n");
573
+ PrintF(" dump stack content, default dump 10 words)\n");
574
+ PrintF("mem <address> [<words>]\n");
575
+ PrintF(" dump memory content, default dump 10 words)\n");
576
+ PrintF("disasm [<instructions>]\n");
577
+ PrintF("disasm [<address/register>]\n");
578
+ PrintF("disasm [[<address/register>] <instructions>]\n");
579
+ PrintF(" disassemble code, default is 10 instructions\n");
580
+ PrintF(" from pc (alias 'di')\n");
581
+ PrintF("gdb\n");
582
+ PrintF(" enter gdb\n");
583
+ PrintF("break <address>\n");
584
+ PrintF(" set a break point on the address\n");
585
+ PrintF("del\n");
586
+ PrintF(" delete the breakpoint\n");
587
+ PrintF("trace (alias 't')\n");
588
+ PrintF(" toogle the tracing of all executed statements\n");
589
+ PrintF("stop feature:\n");
590
+ PrintF(" Description:\n");
591
+ PrintF(" Stops are debug instructions inserted by\n");
592
+ PrintF(" the Assembler::stop() function.\n");
593
+ PrintF(" When hitting a stop, the Simulator will\n");
594
+ PrintF(" stop and and give control to the ArmDebugger.\n");
595
+ PrintF(" The first %d stop codes are watched:\n",
596
+ Simulator::kNumOfWatchedStops);
597
+ PrintF(" - They can be enabled / disabled: the Simulator\n");
598
+ PrintF(" will / won't stop when hitting them.\n");
599
+ PrintF(" - The Simulator keeps track of how many times they \n");
600
+ PrintF(" are met. (See the info command.) Going over a\n");
601
+ PrintF(" disabled stop still increases its counter. \n");
602
+ PrintF(" Commands:\n");
603
+ PrintF(" stop info all/<code> : print infos about number <code>\n");
604
+ PrintF(" or all stop(s).\n");
605
+ PrintF(" stop enable/disable all/<code> : enables / disables\n");
606
+ PrintF(" all or number <code> stop(s)\n");
607
+ PrintF(" stop unstop\n");
608
+ PrintF(" ignore the stop instruction at the current location\n");
609
+ PrintF(" from now on\n");
610
+ } else {
611
+ PrintF("Unknown command: %s\n", cmd);
612
+ }
613
+ }
614
+ DeleteArray(line);
615
+ }
616
+
617
+ // Add all the breakpoints back to stop execution and enter the debugger
618
+ // shell when hit.
619
+ RedoBreakpoints();
620
+
621
+ #undef COMMAND_SIZE
622
+ #undef ARG_SIZE
623
+
624
+ #undef STR
625
+ #undef XSTR
626
+ }
627
+
628
+
629
+ static bool ICacheMatch(void* one, void* two) {
630
+ ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
631
+ ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
632
+ return one == two;
633
+ }
634
+
635
+
636
+ static uint32_t ICacheHash(void* key) {
637
+ return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
638
+ }
639
+
640
+
641
+ static bool AllOnOnePage(uintptr_t start, int size) {
642
+ intptr_t start_page = (start & ~CachePage::kPageMask);
643
+ intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
644
+ return start_page == end_page;
645
+ }
646
+
647
+
648
+ void Simulator::FlushICache(v8::internal::HashMap* i_cache,
649
+ void* start_addr,
650
+ size_t size) {
651
+ intptr_t start = reinterpret_cast<intptr_t>(start_addr);
652
+ int intra_line = (start & CachePage::kLineMask);
653
+ start -= intra_line;
654
+ size += intra_line;
655
+ size = ((size - 1) | CachePage::kLineMask) + 1;
656
+ int offset = (start & CachePage::kPageMask);
657
+ while (!AllOnOnePage(start, size - 1)) {
658
+ int bytes_to_flush = CachePage::kPageSize - offset;
659
+ FlushOnePage(i_cache, start, bytes_to_flush);
660
+ start += bytes_to_flush;
661
+ size -= bytes_to_flush;
662
+ ASSERT_EQ(0, start & CachePage::kPageMask);
663
+ offset = 0;
664
+ }
665
+ if (size != 0) {
666
+ FlushOnePage(i_cache, start, size);
667
+ }
668
+ }
669
+
670
+
671
+ CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
672
+ v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
673
+ ICacheHash(page),
674
+ true);
675
+ if (entry->value == NULL) {
676
+ CachePage* new_page = new CachePage();
677
+ entry->value = new_page;
678
+ }
679
+ return reinterpret_cast<CachePage*>(entry->value);
680
+ }
681
+
682
+
683
+ // Flush from start up to and not including start + size.
684
+ void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
685
+ intptr_t start,
686
+ int size) {
687
+ ASSERT(size <= CachePage::kPageSize);
688
+ ASSERT(AllOnOnePage(start, size - 1));
689
+ ASSERT((start & CachePage::kLineMask) == 0);
690
+ ASSERT((size & CachePage::kLineMask) == 0);
691
+ void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
692
+ int offset = (start & CachePage::kPageMask);
693
+ CachePage* cache_page = GetCachePage(i_cache, page);
694
+ char* valid_bytemap = cache_page->ValidityByte(offset);
695
+ memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
696
+ }
697
+
698
+
699
+ void Simulator::CheckICache(v8::internal::HashMap* i_cache,
700
+ Instruction* instr) {
701
+ intptr_t address = reinterpret_cast<intptr_t>(instr);
702
+ void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
703
+ void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
704
+ int offset = (address & CachePage::kPageMask);
705
+ CachePage* cache_page = GetCachePage(i_cache, page);
706
+ char* cache_valid_byte = cache_page->ValidityByte(offset);
707
+ bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
708
+ char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
709
+ if (cache_hit) {
710
+ // Check that the data in memory matches the contents of the I-cache.
711
+ CHECK(memcmp(reinterpret_cast<void*>(instr),
712
+ cache_page->CachedData(offset),
713
+ Instruction::kInstrSize) == 0);
714
+ } else {
715
+ // Cache miss. Load memory into the cache.
716
+ memcpy(cached_line, line, CachePage::kLineLength);
717
+ *cache_valid_byte = CachePage::LINE_VALID;
718
+ }
719
+ }
720
+
721
+
722
+ void Simulator::Initialize(Isolate* isolate) {
723
+ if (isolate->simulator_initialized()) return;
724
+ isolate->set_simulator_initialized(true);
725
+ ::v8::internal::ExternalReference::set_redirector(isolate,
726
+ &RedirectExternalReference);
727
+ }
728
+
729
+
730
+ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
731
+ i_cache_ = isolate_->simulator_i_cache();
732
+ if (i_cache_ == NULL) {
733
+ i_cache_ = new v8::internal::HashMap(&ICacheMatch);
734
+ isolate_->set_simulator_i_cache(i_cache_);
735
+ }
736
+ Initialize(isolate);
737
+ // Setup simulator support first. Some of this information is needed to
738
+ // setup the architecture state.
739
+ size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
740
+ stack_ = reinterpret_cast<char*>(malloc(stack_size));
741
+ pc_modified_ = false;
742
+ icount_ = 0;
743
+ break_pc_ = NULL;
744
+ break_instr_ = 0;
745
+
746
+ // Setup architecture state.
747
+ // All registers are initialized to zero to start with.
748
+ for (int i = 0; i < num_registers; i++) {
749
+ registers_[i] = 0;
750
+ }
751
+ n_flag_ = false;
752
+ z_flag_ = false;
753
+ c_flag_ = false;
754
+ v_flag_ = false;
755
+
756
+ // Initializing VFP registers.
757
+ // All registers are initialized to zero to start with
758
+ // even though s_registers_ & d_registers_ share the same
759
+ // physical registers in the target.
760
+ for (int i = 0; i < num_s_registers; i++) {
761
+ vfp_register[i] = 0;
762
+ }
763
+ n_flag_FPSCR_ = false;
764
+ z_flag_FPSCR_ = false;
765
+ c_flag_FPSCR_ = false;
766
+ v_flag_FPSCR_ = false;
767
+ FPSCR_rounding_mode_ = RZ;
768
+
769
+ inv_op_vfp_flag_ = false;
770
+ div_zero_vfp_flag_ = false;
771
+ overflow_vfp_flag_ = false;
772
+ underflow_vfp_flag_ = false;
773
+ inexact_vfp_flag_ = false;
774
+
775
+ // The sp is initialized to point to the bottom (high address) of the
776
+ // allocated stack area. To be safe in potential stack underflows we leave
777
+ // some buffer below.
778
+ registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
779
+ // The lr and pc are initialized to a known bad value that will cause an
780
+ // access violation if the simulator ever tries to execute it.
781
+ registers_[pc] = bad_lr;
782
+ registers_[lr] = bad_lr;
783
+ InitializeCoverage();
784
+ }
785
+
786
+
787
+ // When the generated code calls an external reference we need to catch that in
788
+ // the simulator. The external reference will be a function compiled for the
789
+ // host architecture. We need to call that function instead of trying to
790
+ // execute it with the simulator. We do that by redirecting the external
791
+ // reference to a svc (Supervisor Call) instruction that is handled by
792
+ // the simulator. We write the original destination of the jump just at a known
793
+ // offset from the svc instruction so the simulator knows what to call.
794
+ class Redirection {
795
+ public:
796
+ Redirection(void* external_function, ExternalReference::Type type)
797
+ : external_function_(external_function),
798
+ swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
799
+ type_(type),
800
+ next_(NULL) {
801
+ Isolate* isolate = Isolate::Current();
802
+ next_ = isolate->simulator_redirection();
803
+ Simulator::current(isolate)->
804
+ FlushICache(isolate->simulator_i_cache(),
805
+ reinterpret_cast<void*>(&swi_instruction_),
806
+ Instruction::kInstrSize);
807
+ isolate->set_simulator_redirection(this);
808
+ }
809
+
810
+ void* address_of_swi_instruction() {
811
+ return reinterpret_cast<void*>(&swi_instruction_);
812
+ }
813
+
814
+ void* external_function() { return external_function_; }
815
+ ExternalReference::Type type() { return type_; }
816
+
817
+ static Redirection* Get(void* external_function,
818
+ ExternalReference::Type type) {
819
+ Isolate* isolate = Isolate::Current();
820
+ Redirection* current = isolate->simulator_redirection();
821
+ for (; current != NULL; current = current->next_) {
822
+ if (current->external_function_ == external_function) return current;
823
+ }
824
+ return new Redirection(external_function, type);
825
+ }
826
+
827
+ static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
828
+ char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
829
+ char* addr_of_redirection =
830
+ addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
831
+ return reinterpret_cast<Redirection*>(addr_of_redirection);
832
+ }
833
+
834
+ private:
835
+ void* external_function_;
836
+ uint32_t swi_instruction_;
837
+ ExternalReference::Type type_;
838
+ Redirection* next_;
839
+ };
840
+
841
+
842
+ void* Simulator::RedirectExternalReference(void* external_function,
843
+ ExternalReference::Type type) {
844
+ Redirection* redirection = Redirection::Get(external_function, type);
845
+ return redirection->address_of_swi_instruction();
846
+ }
847
+
848
+
849
+ // Get the active Simulator for the current thread.
850
+ Simulator* Simulator::current(Isolate* isolate) {
851
+ v8::internal::Isolate::PerIsolateThreadData* isolate_data =
852
+ isolate->FindOrAllocatePerThreadDataForThisThread();
853
+ ASSERT(isolate_data != NULL);
854
+
855
+ Simulator* sim = isolate_data->simulator();
856
+ if (sim == NULL) {
857
+ // TODO(146): delete the simulator object when a thread/isolate goes away.
858
+ sim = new Simulator(isolate);
859
+ isolate_data->set_simulator(sim);
860
+ }
861
+ return sim;
862
+ }
863
+
864
+
865
+ // Sets the register in the architecture state. It will also deal with updating
866
+ // Simulator internal state for special registers such as PC.
867
+ void Simulator::set_register(int reg, int32_t value) {
868
+ ASSERT((reg >= 0) && (reg < num_registers));
869
+ if (reg == pc) {
870
+ pc_modified_ = true;
871
+ }
872
+ registers_[reg] = value;
873
+ }
874
+
875
+
876
+ // Get the register from the architecture state. This function does handle
877
+ // the special case of accessing the PC register.
878
+ int32_t Simulator::get_register(int reg) const {
879
+ ASSERT((reg >= 0) && (reg < num_registers));
880
+ // Stupid code added to avoid bug in GCC.
881
+ // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
882
+ if (reg >= num_registers) return 0;
883
+ // End stupid code.
884
+ return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
885
+ }
886
+
887
+
888
+ double Simulator::get_double_from_register_pair(int reg) {
889
+ ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
890
+
891
+ double dm_val = 0.0;
892
+ // Read the bits from the unsigned integer register_[] array
893
+ // into the double precision floating point value and return it.
894
+ char buffer[2 * sizeof(vfp_register[0])];
895
+ memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
896
+ memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
897
+ return(dm_val);
898
+ }
899
+
900
+
901
+ void Simulator::set_dw_register(int dreg, const int* dbl) {
902
+ ASSERT((dreg >= 0) && (dreg < num_d_registers));
903
+ registers_[dreg] = dbl[0];
904
+ registers_[dreg + 1] = dbl[1];
905
+ }
906
+
907
+
908
+ // Raw access to the PC register.
909
+ void Simulator::set_pc(int32_t value) {
910
+ pc_modified_ = true;
911
+ registers_[pc] = value;
912
+ }
913
+
914
+
915
+ bool Simulator::has_bad_pc() const {
916
+ return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
917
+ }
918
+
919
+
920
+ // Raw access to the PC register without the special adjustment when reading.
921
+ int32_t Simulator::get_pc() const {
922
+ return registers_[pc];
923
+ }
924
+
925
+
926
+ // Getting from and setting into VFP registers.
927
+ void Simulator::set_s_register(int sreg, unsigned int value) {
928
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
929
+ vfp_register[sreg] = value;
930
+ }
931
+
932
+
933
+ unsigned int Simulator::get_s_register(int sreg) const {
934
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
935
+ return vfp_register[sreg];
936
+ }
937
+
938
+
939
+ void Simulator::set_s_register_from_float(int sreg, const float flt) {
940
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
941
+ // Read the bits from the single precision floating point value
942
+ // into the unsigned integer element of vfp_register[] given by index=sreg.
943
+ char buffer[sizeof(vfp_register[0])];
944
+ memcpy(buffer, &flt, sizeof(vfp_register[0]));
945
+ memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0]));
946
+ }
947
+
948
+
949
+ void Simulator::set_s_register_from_sinteger(int sreg, const int sint) {
950
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
951
+ // Read the bits from the integer value into the unsigned integer element of
952
+ // vfp_register[] given by index=sreg.
953
+ char buffer[sizeof(vfp_register[0])];
954
+ memcpy(buffer, &sint, sizeof(vfp_register[0]));
955
+ memcpy(&vfp_register[sreg], buffer, sizeof(vfp_register[0]));
956
+ }
957
+
958
+
959
+ void Simulator::set_d_register_from_double(int dreg, const double& dbl) {
960
+ ASSERT((dreg >= 0) && (dreg < num_d_registers));
961
+ // Read the bits from the double precision floating point value into the two
962
+ // consecutive unsigned integer elements of vfp_register[] given by index
963
+ // 2*sreg and 2*sreg+1.
964
+ char buffer[2 * sizeof(vfp_register[0])];
965
+ memcpy(buffer, &dbl, 2 * sizeof(vfp_register[0]));
966
+ memcpy(&vfp_register[dreg * 2], buffer, 2 * sizeof(vfp_register[0]));
967
+ }
968
+
969
+
970
+ float Simulator::get_float_from_s_register(int sreg) {
971
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
972
+
973
+ float sm_val = 0.0;
974
+ // Read the bits from the unsigned integer vfp_register[] array
975
+ // into the single precision floating point value and return it.
976
+ char buffer[sizeof(vfp_register[0])];
977
+ memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0]));
978
+ memcpy(&sm_val, buffer, sizeof(vfp_register[0]));
979
+ return(sm_val);
980
+ }
981
+
982
+
983
+ int Simulator::get_sinteger_from_s_register(int sreg) {
984
+ ASSERT((sreg >= 0) && (sreg < num_s_registers));
985
+
986
+ int sm_val = 0;
987
+ // Read the bits from the unsigned integer vfp_register[] array
988
+ // into the single precision floating point value and return it.
989
+ char buffer[sizeof(vfp_register[0])];
990
+ memcpy(buffer, &vfp_register[sreg], sizeof(vfp_register[0]));
991
+ memcpy(&sm_val, buffer, sizeof(vfp_register[0]));
992
+ return(sm_val);
993
+ }
994
+
995
+
996
+ double Simulator::get_double_from_d_register(int dreg) {
997
+ ASSERT((dreg >= 0) && (dreg < num_d_registers));
998
+
999
+ double dm_val = 0.0;
1000
+ // Read the bits from the unsigned integer vfp_register[] array
1001
+ // into the double precision floating point value and return it.
1002
+ char buffer[2 * sizeof(vfp_register[0])];
1003
+ memcpy(buffer, &vfp_register[2 * dreg], 2 * sizeof(vfp_register[0]));
1004
+ memcpy(&dm_val, buffer, 2 * sizeof(vfp_register[0]));
1005
+ return(dm_val);
1006
+ }
1007
+
1008
+
1009
+ // For use in calls that take two double values, constructed either
1010
+ // from r0-r3 or d0 and d1.
1011
+ void Simulator::GetFpArgs(double* x, double* y) {
1012
+ if (use_eabi_hardfloat()) {
1013
+ *x = vfp_register[0];
1014
+ *y = vfp_register[1];
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
+ // Registers 0 and 1 -> x.
1020
+ memcpy(buffer, registers_, sizeof(*x));
1021
+ memcpy(x, buffer, sizeof(*x));
1022
+ // Registers 2 and 3 -> y.
1023
+ memcpy(buffer, registers_ + 2, sizeof(*y));
1024
+ memcpy(y, buffer, sizeof(*y));
1025
+ }
1026
+ }
1027
+
1028
+ // For use in calls that take one double value, constructed either
1029
+ // from r0 and r1 or d0.
1030
+ void Simulator::GetFpArgs(double* x) {
1031
+ if (use_eabi_hardfloat()) {
1032
+ *x = vfp_register[0];
1033
+ } else {
1034
+ // We use a char buffer to get around the strict-aliasing rules which
1035
+ // otherwise allow the compiler to optimize away the copy.
1036
+ char buffer[sizeof(*x)];
1037
+ // Registers 0 and 1 -> x.
1038
+ memcpy(buffer, registers_, sizeof(*x));
1039
+ memcpy(x, buffer, sizeof(*x));
1040
+ }
1041
+ }
1042
+
1043
+
1044
+ // For use in calls that take one double value constructed either
1045
+ // from r0 and r1 or d0 and one integer value.
1046
+ void Simulator::GetFpArgs(double* x, int32_t* y) {
1047
+ if (use_eabi_hardfloat()) {
1048
+ *x = vfp_register[0];
1049
+ *y = registers_[1];
1050
+ } else {
1051
+ // We use a char buffer to get around the strict-aliasing rules which
1052
+ // otherwise allow the compiler to optimize away the copy.
1053
+ char buffer[sizeof(*x)];
1054
+ // Registers 0 and 1 -> x.
1055
+ memcpy(buffer, registers_, sizeof(*x));
1056
+ memcpy(x, buffer, sizeof(*x));
1057
+ // Register 2 -> y.
1058
+ memcpy(buffer, registers_ + 2, sizeof(*y));
1059
+ memcpy(y, buffer, sizeof(*y));
1060
+ }
1061
+ }
1062
+
1063
+
1064
+ // The return value is either in r0/r1 or d0.
1065
+ void Simulator::SetFpResult(const double& result) {
1066
+ if (use_eabi_hardfloat()) {
1067
+ char buffer[2 * sizeof(vfp_register[0])];
1068
+ memcpy(buffer, &result, sizeof(buffer));
1069
+ // Copy result to d0.
1070
+ memcpy(vfp_register, buffer, sizeof(buffer));
1071
+ } else {
1072
+ char buffer[2 * sizeof(registers_[0])];
1073
+ memcpy(buffer, &result, sizeof(buffer));
1074
+ // Copy result to r0 and r1.
1075
+ memcpy(registers_, buffer, sizeof(buffer));
1076
+ }
1077
+ }
1078
+
1079
+
1080
+ void Simulator::TrashCallerSaveRegisters() {
1081
+ // We don't trash the registers with the return value.
1082
+ registers_[2] = 0x50Bad4U;
1083
+ registers_[3] = 0x50Bad4U;
1084
+ registers_[12] = 0x50Bad4U;
1085
+ }
1086
+
1087
+ // Some Operating Systems allow unaligned access on ARMv7 targets. We
1088
+ // assume that unaligned accesses are not allowed unless the v8 build system
1089
+ // defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
1090
+ // The following statements below describes the behavior of the ARM CPUs
1091
+ // that don't support unaligned access.
1092
+ // Some ARM platforms raise an interrupt on detecting unaligned access.
1093
+ // On others it does a funky rotation thing. For now we
1094
+ // simply disallow unaligned reads. Note that simulator runs have the runtime
1095
+ // system running directly on the host system and only generated code is
1096
+ // executed in the simulator. Since the host is typically IA32 we will not
1097
+ // get the correct ARM-like behaviour on unaligned accesses for those ARM
1098
+ // targets that don't support unaligned loads and stores.
1099
+
1100
+
1101
+ int Simulator::ReadW(int32_t addr, Instruction* instr) {
1102
+ #if V8_TARGET_CAN_READ_UNALIGNED
1103
+ intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1104
+ return *ptr;
1105
+ #else
1106
+ if ((addr & 3) == 0) {
1107
+ intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1108
+ return *ptr;
1109
+ }
1110
+ PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1111
+ addr,
1112
+ reinterpret_cast<intptr_t>(instr));
1113
+ UNIMPLEMENTED();
1114
+ return 0;
1115
+ #endif
1116
+ }
1117
+
1118
+
1119
+ void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1120
+ #if V8_TARGET_CAN_READ_UNALIGNED
1121
+ intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1122
+ *ptr = value;
1123
+ return;
1124
+ #else
1125
+ if ((addr & 3) == 0) {
1126
+ intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1127
+ *ptr = value;
1128
+ return;
1129
+ }
1130
+ PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1131
+ addr,
1132
+ reinterpret_cast<intptr_t>(instr));
1133
+ UNIMPLEMENTED();
1134
+ #endif
1135
+ }
1136
+
1137
+
1138
+ uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1139
+ #if V8_TARGET_CAN_READ_UNALIGNED
1140
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1141
+ return *ptr;
1142
+ #else
1143
+ if ((addr & 1) == 0) {
1144
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1145
+ return *ptr;
1146
+ }
1147
+ PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1148
+ addr,
1149
+ reinterpret_cast<intptr_t>(instr));
1150
+ UNIMPLEMENTED();
1151
+ return 0;
1152
+ #endif
1153
+ }
1154
+
1155
+
1156
+ int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1157
+ #if V8_TARGET_CAN_READ_UNALIGNED
1158
+ int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1159
+ return *ptr;
1160
+ #else
1161
+ if ((addr & 1) == 0) {
1162
+ int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1163
+ return *ptr;
1164
+ }
1165
+ PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
1166
+ UNIMPLEMENTED();
1167
+ return 0;
1168
+ #endif
1169
+ }
1170
+
1171
+
1172
+ void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1173
+ #if V8_TARGET_CAN_READ_UNALIGNED
1174
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1175
+ *ptr = value;
1176
+ return;
1177
+ #else
1178
+ if ((addr & 1) == 0) {
1179
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1180
+ *ptr = value;
1181
+ return;
1182
+ }
1183
+ PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1184
+ addr,
1185
+ reinterpret_cast<intptr_t>(instr));
1186
+ UNIMPLEMENTED();
1187
+ #endif
1188
+ }
1189
+
1190
+
1191
+ void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1192
+ #if V8_TARGET_CAN_READ_UNALIGNED
1193
+ int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1194
+ *ptr = value;
1195
+ return;
1196
+ #else
1197
+ if ((addr & 1) == 0) {
1198
+ int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1199
+ *ptr = value;
1200
+ return;
1201
+ }
1202
+ PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1203
+ addr,
1204
+ reinterpret_cast<intptr_t>(instr));
1205
+ UNIMPLEMENTED();
1206
+ #endif
1207
+ }
1208
+
1209
+
1210
+ uint8_t Simulator::ReadBU(int32_t addr) {
1211
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1212
+ return *ptr;
1213
+ }
1214
+
1215
+
1216
+ int8_t Simulator::ReadB(int32_t addr) {
1217
+ int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1218
+ return *ptr;
1219
+ }
1220
+
1221
+
1222
+ void Simulator::WriteB(int32_t addr, uint8_t value) {
1223
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1224
+ *ptr = value;
1225
+ }
1226
+
1227
+
1228
+ void Simulator::WriteB(int32_t addr, int8_t value) {
1229
+ int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1230
+ *ptr = value;
1231
+ }
1232
+
1233
+
1234
+ int32_t* Simulator::ReadDW(int32_t addr) {
1235
+ #if V8_TARGET_CAN_READ_UNALIGNED
1236
+ int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1237
+ return ptr;
1238
+ #else
1239
+ if ((addr & 3) == 0) {
1240
+ int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1241
+ return ptr;
1242
+ }
1243
+ PrintF("Unaligned read at 0x%08x\n", addr);
1244
+ UNIMPLEMENTED();
1245
+ return 0;
1246
+ #endif
1247
+ }
1248
+
1249
+
1250
+ void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1251
+ #if V8_TARGET_CAN_READ_UNALIGNED
1252
+ int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1253
+ *ptr++ = value1;
1254
+ *ptr = value2;
1255
+ return;
1256
+ #else
1257
+ if ((addr & 3) == 0) {
1258
+ int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1259
+ *ptr++ = value1;
1260
+ *ptr = value2;
1261
+ return;
1262
+ }
1263
+ PrintF("Unaligned write at 0x%08x\n", addr);
1264
+ UNIMPLEMENTED();
1265
+ #endif
1266
+ }
1267
+
1268
+
1269
+ // Returns the limit of the stack area to enable checking for stack overflows.
1270
+ uintptr_t Simulator::StackLimit() const {
1271
+ // Leave a safety margin of 256 bytes to prevent overrunning the stack when
1272
+ // pushing values.
1273
+ return reinterpret_cast<uintptr_t>(stack_) + 256;
1274
+ }
1275
+
1276
+
1277
+ // Unsupported instructions use Format to print an error and stop execution.
1278
+ void Simulator::Format(Instruction* instr, const char* format) {
1279
+ PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1280
+ reinterpret_cast<intptr_t>(instr), format);
1281
+ UNIMPLEMENTED();
1282
+ }
1283
+
1284
+
1285
+ // Checks if the current instruction should be executed based on its
1286
+ // condition bits.
1287
+ bool Simulator::ConditionallyExecute(Instruction* instr) {
1288
+ switch (instr->ConditionField()) {
1289
+ case eq: return z_flag_;
1290
+ case ne: return !z_flag_;
1291
+ case cs: return c_flag_;
1292
+ case cc: return !c_flag_;
1293
+ case mi: return n_flag_;
1294
+ case pl: return !n_flag_;
1295
+ case vs: return v_flag_;
1296
+ case vc: return !v_flag_;
1297
+ case hi: return c_flag_ && !z_flag_;
1298
+ case ls: return !c_flag_ || z_flag_;
1299
+ case ge: return n_flag_ == v_flag_;
1300
+ case lt: return n_flag_ != v_flag_;
1301
+ case gt: return !z_flag_ && (n_flag_ == v_flag_);
1302
+ case le: return z_flag_ || (n_flag_ != v_flag_);
1303
+ case al: return true;
1304
+ default: UNREACHABLE();
1305
+ }
1306
+ return false;
1307
+ }
1308
+
1309
+
1310
+ // Calculate and set the Negative and Zero flags.
1311
+ void Simulator::SetNZFlags(int32_t val) {
1312
+ n_flag_ = (val < 0);
1313
+ z_flag_ = (val == 0);
1314
+ }
1315
+
1316
+
1317
+ // Set the Carry flag.
1318
+ void Simulator::SetCFlag(bool val) {
1319
+ c_flag_ = val;
1320
+ }
1321
+
1322
+
1323
+ // Set the oVerflow flag.
1324
+ void Simulator::SetVFlag(bool val) {
1325
+ v_flag_ = val;
1326
+ }
1327
+
1328
+
1329
+ // Calculate C flag value for additions.
1330
+ bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1331
+ uint32_t uleft = static_cast<uint32_t>(left);
1332
+ uint32_t uright = static_cast<uint32_t>(right);
1333
+ uint32_t urest = 0xffffffffU - uleft;
1334
+
1335
+ return (uright > urest) ||
1336
+ (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1337
+ }
1338
+
1339
+
1340
+ // Calculate C flag value for subtractions.
1341
+ bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1342
+ uint32_t uleft = static_cast<uint32_t>(left);
1343
+ uint32_t uright = static_cast<uint32_t>(right);
1344
+
1345
+ return (uright > uleft);
1346
+ }
1347
+
1348
+
1349
+ // Calculate V flag value for additions and subtractions.
1350
+ bool Simulator::OverflowFrom(int32_t alu_out,
1351
+ int32_t left, int32_t right, bool addition) {
1352
+ bool overflow;
1353
+ if (addition) {
1354
+ // operands have the same sign
1355
+ overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1356
+ // and operands and result have different sign
1357
+ && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1358
+ } else {
1359
+ // operands have different signs
1360
+ overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1361
+ // and first operand and result have different signs
1362
+ && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1363
+ }
1364
+ return overflow;
1365
+ }
1366
+
1367
+
1368
+ // Support for VFP comparisons.
1369
+ void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
1370
+ if (isnan(val1) || isnan(val2)) {
1371
+ n_flag_FPSCR_ = false;
1372
+ z_flag_FPSCR_ = false;
1373
+ c_flag_FPSCR_ = true;
1374
+ v_flag_FPSCR_ = true;
1375
+ // All non-NaN cases.
1376
+ } else if (val1 == val2) {
1377
+ n_flag_FPSCR_ = false;
1378
+ z_flag_FPSCR_ = true;
1379
+ c_flag_FPSCR_ = true;
1380
+ v_flag_FPSCR_ = false;
1381
+ } else if (val1 < val2) {
1382
+ n_flag_FPSCR_ = true;
1383
+ z_flag_FPSCR_ = false;
1384
+ c_flag_FPSCR_ = false;
1385
+ v_flag_FPSCR_ = false;
1386
+ } else {
1387
+ // Case when (val1 > val2).
1388
+ n_flag_FPSCR_ = false;
1389
+ z_flag_FPSCR_ = false;
1390
+ c_flag_FPSCR_ = true;
1391
+ v_flag_FPSCR_ = false;
1392
+ }
1393
+ }
1394
+
1395
+
1396
+ void Simulator::Copy_FPSCR_to_APSR() {
1397
+ n_flag_ = n_flag_FPSCR_;
1398
+ z_flag_ = z_flag_FPSCR_;
1399
+ c_flag_ = c_flag_FPSCR_;
1400
+ v_flag_ = v_flag_FPSCR_;
1401
+ }
1402
+
1403
+
1404
+ // Addressing Mode 1 - Data-processing operands:
1405
+ // Get the value based on the shifter_operand with register.
1406
+ int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
1407
+ ShiftOp shift = instr->ShiftField();
1408
+ int shift_amount = instr->ShiftAmountValue();
1409
+ int32_t result = get_register(instr->RmValue());
1410
+ if (instr->Bit(4) == 0) {
1411
+ // by immediate
1412
+ if ((shift == ROR) && (shift_amount == 0)) {
1413
+ UNIMPLEMENTED();
1414
+ return result;
1415
+ } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1416
+ shift_amount = 32;
1417
+ }
1418
+ switch (shift) {
1419
+ case ASR: {
1420
+ if (shift_amount == 0) {
1421
+ if (result < 0) {
1422
+ result = 0xffffffff;
1423
+ *carry_out = true;
1424
+ } else {
1425
+ result = 0;
1426
+ *carry_out = false;
1427
+ }
1428
+ } else {
1429
+ result >>= (shift_amount - 1);
1430
+ *carry_out = (result & 1) == 1;
1431
+ result >>= 1;
1432
+ }
1433
+ break;
1434
+ }
1435
+
1436
+ case LSL: {
1437
+ if (shift_amount == 0) {
1438
+ *carry_out = c_flag_;
1439
+ } else {
1440
+ result <<= (shift_amount - 1);
1441
+ *carry_out = (result < 0);
1442
+ result <<= 1;
1443
+ }
1444
+ break;
1445
+ }
1446
+
1447
+ case LSR: {
1448
+ if (shift_amount == 0) {
1449
+ result = 0;
1450
+ *carry_out = c_flag_;
1451
+ } else {
1452
+ uint32_t uresult = static_cast<uint32_t>(result);
1453
+ uresult >>= (shift_amount - 1);
1454
+ *carry_out = (uresult & 1) == 1;
1455
+ uresult >>= 1;
1456
+ result = static_cast<int32_t>(uresult);
1457
+ }
1458
+ break;
1459
+ }
1460
+
1461
+ case ROR: {
1462
+ UNIMPLEMENTED();
1463
+ break;
1464
+ }
1465
+
1466
+ default: {
1467
+ UNREACHABLE();
1468
+ break;
1469
+ }
1470
+ }
1471
+ } else {
1472
+ // by register
1473
+ int rs = instr->RsValue();
1474
+ shift_amount = get_register(rs) &0xff;
1475
+ switch (shift) {
1476
+ case ASR: {
1477
+ if (shift_amount == 0) {
1478
+ *carry_out = c_flag_;
1479
+ } else if (shift_amount < 32) {
1480
+ result >>= (shift_amount - 1);
1481
+ *carry_out = (result & 1) == 1;
1482
+ result >>= 1;
1483
+ } else {
1484
+ ASSERT(shift_amount >= 32);
1485
+ if (result < 0) {
1486
+ *carry_out = true;
1487
+ result = 0xffffffff;
1488
+ } else {
1489
+ *carry_out = false;
1490
+ result = 0;
1491
+ }
1492
+ }
1493
+ break;
1494
+ }
1495
+
1496
+ case LSL: {
1497
+ if (shift_amount == 0) {
1498
+ *carry_out = c_flag_;
1499
+ } else if (shift_amount < 32) {
1500
+ result <<= (shift_amount - 1);
1501
+ *carry_out = (result < 0);
1502
+ result <<= 1;
1503
+ } else if (shift_amount == 32) {
1504
+ *carry_out = (result & 1) == 1;
1505
+ result = 0;
1506
+ } else {
1507
+ ASSERT(shift_amount > 32);
1508
+ *carry_out = false;
1509
+ result = 0;
1510
+ }
1511
+ break;
1512
+ }
1513
+
1514
+ case LSR: {
1515
+ if (shift_amount == 0) {
1516
+ *carry_out = c_flag_;
1517
+ } else if (shift_amount < 32) {
1518
+ uint32_t uresult = static_cast<uint32_t>(result);
1519
+ uresult >>= (shift_amount - 1);
1520
+ *carry_out = (uresult & 1) == 1;
1521
+ uresult >>= 1;
1522
+ result = static_cast<int32_t>(uresult);
1523
+ } else if (shift_amount == 32) {
1524
+ *carry_out = (result < 0);
1525
+ result = 0;
1526
+ } else {
1527
+ *carry_out = false;
1528
+ result = 0;
1529
+ }
1530
+ break;
1531
+ }
1532
+
1533
+ case ROR: {
1534
+ UNIMPLEMENTED();
1535
+ break;
1536
+ }
1537
+
1538
+ default: {
1539
+ UNREACHABLE();
1540
+ break;
1541
+ }
1542
+ }
1543
+ }
1544
+ return result;
1545
+ }
1546
+
1547
+
1548
+ // Addressing Mode 1 - Data-processing operands:
1549
+ // Get the value based on the shifter_operand with immediate.
1550
+ int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
1551
+ int rotate = instr->RotateValue() * 2;
1552
+ int immed8 = instr->Immed8Value();
1553
+ int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1554
+ *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1555
+ return imm;
1556
+ }
1557
+
1558
+
1559
+ static int count_bits(int bit_vector) {
1560
+ int count = 0;
1561
+ while (bit_vector != 0) {
1562
+ if ((bit_vector & 1) != 0) {
1563
+ count++;
1564
+ }
1565
+ bit_vector >>= 1;
1566
+ }
1567
+ return count;
1568
+ }
1569
+
1570
+
1571
+ void Simulator::ProcessPUW(Instruction* instr,
1572
+ int num_regs,
1573
+ int reg_size,
1574
+ intptr_t* start_address,
1575
+ intptr_t* end_address) {
1576
+ int rn = instr->RnValue();
1577
+ int32_t rn_val = get_register(rn);
1578
+ switch (instr->PUField()) {
1579
+ case da_x: {
1580
+ UNIMPLEMENTED();
1581
+ break;
1582
+ }
1583
+ case ia_x: {
1584
+ *start_address = rn_val;
1585
+ *end_address = rn_val + (num_regs * reg_size) - reg_size;
1586
+ rn_val = rn_val + (num_regs * reg_size);
1587
+ break;
1588
+ }
1589
+ case db_x: {
1590
+ *start_address = rn_val - (num_regs * reg_size);
1591
+ *end_address = rn_val - reg_size;
1592
+ rn_val = *start_address;
1593
+ break;
1594
+ }
1595
+ case ib_x: {
1596
+ *start_address = rn_val + reg_size;
1597
+ *end_address = rn_val + (num_regs * reg_size);
1598
+ rn_val = *end_address;
1599
+ break;
1600
+ }
1601
+ default: {
1602
+ UNREACHABLE();
1603
+ break;
1604
+ }
1605
+ }
1606
+ if (instr->HasW()) {
1607
+ set_register(rn, rn_val);
1608
+ }
1609
+ }
1610
+
1611
+ // Addressing Mode 4 - Load and Store Multiple
1612
+ void Simulator::HandleRList(Instruction* instr, bool load) {
1613
+ int rlist = instr->RlistValue();
1614
+ int num_regs = count_bits(rlist);
1615
+
1616
+ intptr_t start_address = 0;
1617
+ intptr_t end_address = 0;
1618
+ ProcessPUW(instr, num_regs, kPointerSize, &start_address, &end_address);
1619
+
1620
+ intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1621
+ int reg = 0;
1622
+ while (rlist != 0) {
1623
+ if ((rlist & 1) != 0) {
1624
+ if (load) {
1625
+ set_register(reg, *address);
1626
+ } else {
1627
+ *address = get_register(reg);
1628
+ }
1629
+ address += 1;
1630
+ }
1631
+ reg++;
1632
+ rlist >>= 1;
1633
+ }
1634
+ ASSERT(end_address == ((intptr_t)address) - 4);
1635
+ }
1636
+
1637
+
1638
+ // Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
1639
+ void Simulator::HandleVList(Instruction* instr) {
1640
+ VFPRegPrecision precision =
1641
+ (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1642
+ int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1643
+
1644
+ bool load = (instr->VLValue() == 0x1);
1645
+
1646
+ int vd;
1647
+ int num_regs;
1648
+ vd = instr->VFPDRegValue(precision);
1649
+ if (precision == kSinglePrecision) {
1650
+ num_regs = instr->Immed8Value();
1651
+ } else {
1652
+ num_regs = instr->Immed8Value() / 2;
1653
+ }
1654
+
1655
+ intptr_t start_address = 0;
1656
+ intptr_t end_address = 0;
1657
+ ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address);
1658
+
1659
+ intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1660
+ for (int reg = vd; reg < vd + num_regs; reg++) {
1661
+ if (precision == kSinglePrecision) {
1662
+ if (load) {
1663
+ set_s_register_from_sinteger(
1664
+ reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1665
+ } else {
1666
+ WriteW(reinterpret_cast<int32_t>(address),
1667
+ get_sinteger_from_s_register(reg), instr);
1668
+ }
1669
+ address += 1;
1670
+ } else {
1671
+ if (load) {
1672
+ set_s_register_from_sinteger(
1673
+ 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1674
+ set_s_register_from_sinteger(
1675
+ 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr));
1676
+ } else {
1677
+ WriteW(reinterpret_cast<int32_t>(address),
1678
+ get_sinteger_from_s_register(2 * reg), instr);
1679
+ WriteW(reinterpret_cast<int32_t>(address + 1),
1680
+ get_sinteger_from_s_register(2 * reg + 1), instr);
1681
+ }
1682
+ address += 2;
1683
+ }
1684
+ }
1685
+ ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1686
+ }
1687
+
1688
+
1689
+ // Calls into the V8 runtime are based on this very simple interface.
1690
+ // Note: To be able to return two values from some calls the code in runtime.cc
1691
+ // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1692
+ // 64-bit value. With the code below we assume that all runtime calls return
1693
+ // 64 bits of result. If they don't, the r1 result register contains a bogus
1694
+ // value, which is fine because it is caller-saved.
1695
+ typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1696
+ int32_t arg1,
1697
+ int32_t arg2,
1698
+ int32_t arg3,
1699
+ int32_t arg4,
1700
+ int32_t arg5);
1701
+ typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
1702
+ int32_t arg1,
1703
+ int32_t arg2,
1704
+ int32_t arg3);
1705
+
1706
+ // This signature supports direct call in to API function native callback
1707
+ // (refer to InvocationCallback in v8.h).
1708
+ typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1709
+
1710
+ // This signature supports direct call to accessor getter callback.
1711
+ typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
1712
+ int32_t arg1);
1713
+
1714
+ // Software interrupt instructions are used by the simulator to call into the
1715
+ // C-based V8 runtime.
1716
+ void Simulator::SoftwareInterrupt(Instruction* instr) {
1717
+ int svc = instr->SvcValue();
1718
+ switch (svc) {
1719
+ case kCallRtRedirected: {
1720
+ // Check if stack is aligned. Error if not aligned is reported below to
1721
+ // include information on the function called.
1722
+ bool stack_aligned =
1723
+ (get_register(sp)
1724
+ & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1725
+ Redirection* redirection = Redirection::FromSwiInstruction(instr);
1726
+ int32_t arg0 = get_register(r0);
1727
+ int32_t arg1 = get_register(r1);
1728
+ int32_t arg2 = get_register(r2);
1729
+ int32_t arg3 = get_register(r3);
1730
+ int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1731
+ int32_t arg4 = stack_pointer[0];
1732
+ int32_t arg5 = stack_pointer[1];
1733
+ bool fp_call =
1734
+ (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1735
+ (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1736
+ (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1737
+ (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1738
+ if (use_eabi_hardfloat()) {
1739
+ // With the hard floating point calling convention, double
1740
+ // arguments are passed in VFP registers. Fetch the arguments
1741
+ // from there and call the builtin using soft floating point
1742
+ // convention.
1743
+ switch (redirection->type()) {
1744
+ case ExternalReference::BUILTIN_FP_FP_CALL:
1745
+ case ExternalReference::BUILTIN_COMPARE_CALL:
1746
+ arg0 = vfp_register[0];
1747
+ arg1 = vfp_register[1];
1748
+ arg2 = vfp_register[2];
1749
+ arg3 = vfp_register[3];
1750
+ break;
1751
+ case ExternalReference::BUILTIN_FP_CALL:
1752
+ arg0 = vfp_register[0];
1753
+ arg1 = vfp_register[1];
1754
+ break;
1755
+ case ExternalReference::BUILTIN_FP_INT_CALL:
1756
+ arg0 = vfp_register[0];
1757
+ arg1 = vfp_register[1];
1758
+ arg2 = get_register(0);
1759
+ break;
1760
+ default:
1761
+ break;
1762
+ }
1763
+ }
1764
+ // This is dodgy but it works because the C entry stubs are never moved.
1765
+ // See comment in codegen-arm.cc and bug 1242173.
1766
+ int32_t saved_lr = get_register(lr);
1767
+ intptr_t external =
1768
+ reinterpret_cast<intptr_t>(redirection->external_function());
1769
+ if (fp_call) {
1770
+ if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1771
+ SimulatorRuntimeFPCall target =
1772
+ reinterpret_cast<SimulatorRuntimeFPCall>(external);
1773
+ double dval0, dval1;
1774
+ int32_t ival;
1775
+ switch (redirection->type()) {
1776
+ case ExternalReference::BUILTIN_FP_FP_CALL:
1777
+ case ExternalReference::BUILTIN_COMPARE_CALL:
1778
+ GetFpArgs(&dval0, &dval1);
1779
+ PrintF("Call to host function at %p with args %f, %f",
1780
+ FUNCTION_ADDR(target), dval0, dval1);
1781
+ break;
1782
+ case ExternalReference::BUILTIN_FP_CALL:
1783
+ GetFpArgs(&dval0);
1784
+ PrintF("Call to host function at %p with arg %f",
1785
+ FUNCTION_ADDR(target), dval0);
1786
+ break;
1787
+ case ExternalReference::BUILTIN_FP_INT_CALL:
1788
+ GetFpArgs(&dval0, &ival);
1789
+ PrintF("Call to host function at %p with args %f, %d",
1790
+ FUNCTION_ADDR(target), dval0, ival);
1791
+ break;
1792
+ default:
1793
+ UNREACHABLE();
1794
+ break;
1795
+ }
1796
+ if (!stack_aligned) {
1797
+ PrintF(" with unaligned stack %08x\n", get_register(sp));
1798
+ }
1799
+ PrintF("\n");
1800
+ }
1801
+ CHECK(stack_aligned);
1802
+ if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
1803
+ SimulatorRuntimeFPCall target =
1804
+ reinterpret_cast<SimulatorRuntimeFPCall>(external);
1805
+ double result = target(arg0, arg1, arg2, arg3);
1806
+ SetFpResult(result);
1807
+ } else {
1808
+ SimulatorRuntimeCall target =
1809
+ reinterpret_cast<SimulatorRuntimeCall>(external);
1810
+ int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1811
+ int32_t lo_res = static_cast<int32_t>(result);
1812
+ int32_t hi_res = static_cast<int32_t>(result >> 32);
1813
+ if (::v8::internal::FLAG_trace_sim) {
1814
+ PrintF("Returned %08x\n", lo_res);
1815
+ }
1816
+ set_register(r0, lo_res);
1817
+ set_register(r1, hi_res);
1818
+ }
1819
+ } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1820
+ SimulatorRuntimeDirectApiCall target =
1821
+ reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1822
+ if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1823
+ PrintF("Call to host function at %p args %08x",
1824
+ FUNCTION_ADDR(target), arg0);
1825
+ if (!stack_aligned) {
1826
+ PrintF(" with unaligned stack %08x\n", get_register(sp));
1827
+ }
1828
+ PrintF("\n");
1829
+ }
1830
+ CHECK(stack_aligned);
1831
+ v8::Handle<v8::Value> result = target(arg0);
1832
+ if (::v8::internal::FLAG_trace_sim) {
1833
+ PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
1834
+ }
1835
+ set_register(r0, (int32_t) *result);
1836
+ } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1837
+ SimulatorRuntimeDirectGetterCall target =
1838
+ reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1839
+ if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1840
+ PrintF("Call to host function at %p args %08x %08x",
1841
+ FUNCTION_ADDR(target), arg0, arg1);
1842
+ if (!stack_aligned) {
1843
+ PrintF(" with unaligned stack %08x\n", get_register(sp));
1844
+ }
1845
+ PrintF("\n");
1846
+ }
1847
+ CHECK(stack_aligned);
1848
+ v8::Handle<v8::Value> result = target(arg0, arg1);
1849
+ if (::v8::internal::FLAG_trace_sim) {
1850
+ PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
1851
+ }
1852
+ set_register(r0, (int32_t) *result);
1853
+ } else {
1854
+ // builtin call.
1855
+ ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1856
+ SimulatorRuntimeCall target =
1857
+ reinterpret_cast<SimulatorRuntimeCall>(external);
1858
+ if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1859
+ PrintF(
1860
+ "Call to host function at %p"
1861
+ "args %08x, %08x, %08x, %08x, %08x, %08x",
1862
+ FUNCTION_ADDR(target),
1863
+ arg0,
1864
+ arg1,
1865
+ arg2,
1866
+ arg3,
1867
+ arg4,
1868
+ arg5);
1869
+ if (!stack_aligned) {
1870
+ PrintF(" with unaligned stack %08x\n", get_register(sp));
1871
+ }
1872
+ PrintF("\n");
1873
+ }
1874
+ CHECK(stack_aligned);
1875
+ int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1876
+ int32_t lo_res = static_cast<int32_t>(result);
1877
+ int32_t hi_res = static_cast<int32_t>(result >> 32);
1878
+ if (::v8::internal::FLAG_trace_sim) {
1879
+ PrintF("Returned %08x\n", lo_res);
1880
+ }
1881
+ set_register(r0, lo_res);
1882
+ set_register(r1, hi_res);
1883
+ }
1884
+ set_register(lr, saved_lr);
1885
+ set_pc(get_register(lr));
1886
+ break;
1887
+ }
1888
+ case kBreakpoint: {
1889
+ ArmDebugger dbg(this);
1890
+ dbg.Debug();
1891
+ break;
1892
+ }
1893
+ // stop uses all codes greater than 1 << 23.
1894
+ default: {
1895
+ if (svc >= (1 << 23)) {
1896
+ uint32_t code = svc & kStopCodeMask;
1897
+ if (isWatchedStop(code)) {
1898
+ IncreaseStopCounter(code);
1899
+ }
1900
+ // Stop if it is enabled, otherwise go on jumping over the stop
1901
+ // and the message address.
1902
+ if (isEnabledStop(code)) {
1903
+ ArmDebugger dbg(this);
1904
+ dbg.Stop(instr);
1905
+ } else {
1906
+ set_pc(get_pc() + 2 * Instruction::kInstrSize);
1907
+ }
1908
+ } else {
1909
+ // This is not a valid svc code.
1910
+ UNREACHABLE();
1911
+ break;
1912
+ }
1913
+ }
1914
+ }
1915
+ }
1916
+
1917
+
1918
+ // Stop helper functions.
1919
+ bool Simulator::isStopInstruction(Instruction* instr) {
1920
+ return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1921
+ }
1922
+
1923
+
1924
+ bool Simulator::isWatchedStop(uint32_t code) {
1925
+ ASSERT(code <= kMaxStopCode);
1926
+ return code < kNumOfWatchedStops;
1927
+ }
1928
+
1929
+
1930
+ bool Simulator::isEnabledStop(uint32_t code) {
1931
+ ASSERT(code <= kMaxStopCode);
1932
+ // Unwatched stops are always enabled.
1933
+ return !isWatchedStop(code) ||
1934
+ !(watched_stops[code].count & kStopDisabledBit);
1935
+ }
1936
+
1937
+
1938
+ void Simulator::EnableStop(uint32_t code) {
1939
+ ASSERT(isWatchedStop(code));
1940
+ if (!isEnabledStop(code)) {
1941
+ watched_stops[code].count &= ~kStopDisabledBit;
1942
+ }
1943
+ }
1944
+
1945
+
1946
+ void Simulator::DisableStop(uint32_t code) {
1947
+ ASSERT(isWatchedStop(code));
1948
+ if (isEnabledStop(code)) {
1949
+ watched_stops[code].count |= kStopDisabledBit;
1950
+ }
1951
+ }
1952
+
1953
+
1954
+ void Simulator::IncreaseStopCounter(uint32_t code) {
1955
+ ASSERT(code <= kMaxStopCode);
1956
+ ASSERT(isWatchedStop(code));
1957
+ if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
1958
+ PrintF("Stop counter for code %i has overflowed.\n"
1959
+ "Enabling this code and reseting the counter to 0.\n", code);
1960
+ watched_stops[code].count = 0;
1961
+ EnableStop(code);
1962
+ } else {
1963
+ watched_stops[code].count++;
1964
+ }
1965
+ }
1966
+
1967
+
1968
+ // Print a stop status.
1969
+ void Simulator::PrintStopInfo(uint32_t code) {
1970
+ ASSERT(code <= kMaxStopCode);
1971
+ if (!isWatchedStop(code)) {
1972
+ PrintF("Stop not watched.");
1973
+ } else {
1974
+ const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1975
+ int32_t count = watched_stops[code].count & ~kStopDisabledBit;
1976
+ // Don't print the state of unused breakpoints.
1977
+ if (count != 0) {
1978
+ if (watched_stops[code].desc) {
1979
+ PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1980
+ code, code, state, count, watched_stops[code].desc);
1981
+ } else {
1982
+ PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
1983
+ code, code, state, count);
1984
+ }
1985
+ }
1986
+ }
1987
+ }
1988
+
1989
+
1990
+ // Handle execution based on instruction types.
1991
+
1992
+ // Instruction types 0 and 1 are both rolled into one function because they
1993
+ // only differ in the handling of the shifter_operand.
1994
+ void Simulator::DecodeType01(Instruction* instr) {
1995
+ int type = instr->TypeValue();
1996
+ if ((type == 0) && instr->IsSpecialType0()) {
1997
+ // multiply instruction or extra loads and stores
1998
+ if (instr->Bits(7, 4) == 9) {
1999
+ if (instr->Bit(24) == 0) {
2000
+ // Raw field decoding here. Multiply instructions have their Rd in
2001
+ // funny places.
2002
+ int rn = instr->RnValue();
2003
+ int rm = instr->RmValue();
2004
+ int rs = instr->RsValue();
2005
+ int32_t rs_val = get_register(rs);
2006
+ int32_t rm_val = get_register(rm);
2007
+ if (instr->Bit(23) == 0) {
2008
+ if (instr->Bit(21) == 0) {
2009
+ // The MUL instruction description (A 4.1.33) refers to Rd as being
2010
+ // the destination for the operation, but it confusingly uses the
2011
+ // Rn field to encode it.
2012
+ // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
2013
+ int rd = rn; // Remap the rn field to the Rd register.
2014
+ int32_t alu_out = rm_val * rs_val;
2015
+ set_register(rd, alu_out);
2016
+ if (instr->HasS()) {
2017
+ SetNZFlags(alu_out);
2018
+ }
2019
+ } else {
2020
+ // The MLA instruction description (A 4.1.28) refers to the order
2021
+ // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
2022
+ // Rn field to encode the Rd register and the Rd field to encode
2023
+ // the Rn register.
2024
+ Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
2025
+ }
2026
+ } else {
2027
+ // The signed/long multiply instructions use the terms RdHi and RdLo
2028
+ // when referring to the target registers. They are mapped to the Rn
2029
+ // and Rd fields as follows:
2030
+ // RdLo == Rd
2031
+ // RdHi == Rn (This is confusingly stored in variable rd here
2032
+ // because the mul instruction from above uses the
2033
+ // Rn field to encode the Rd register. Good luck figuring
2034
+ // this out without reading the ARM instruction manual
2035
+ // at a very detailed level.)
2036
+ // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
2037
+ int rd_hi = rn; // Remap the rn field to the RdHi register.
2038
+ int rd_lo = instr->RdValue();
2039
+ int32_t hi_res = 0;
2040
+ int32_t lo_res = 0;
2041
+ if (instr->Bit(22) == 1) {
2042
+ int64_t left_op = static_cast<int32_t>(rm_val);
2043
+ int64_t right_op = static_cast<int32_t>(rs_val);
2044
+ uint64_t result = left_op * right_op;
2045
+ hi_res = static_cast<int32_t>(result >> 32);
2046
+ lo_res = static_cast<int32_t>(result & 0xffffffff);
2047
+ } else {
2048
+ // unsigned multiply
2049
+ uint64_t left_op = static_cast<uint32_t>(rm_val);
2050
+ uint64_t right_op = static_cast<uint32_t>(rs_val);
2051
+ uint64_t result = left_op * right_op;
2052
+ hi_res = static_cast<int32_t>(result >> 32);
2053
+ lo_res = static_cast<int32_t>(result & 0xffffffff);
2054
+ }
2055
+ set_register(rd_lo, lo_res);
2056
+ set_register(rd_hi, hi_res);
2057
+ if (instr->HasS()) {
2058
+ UNIMPLEMENTED();
2059
+ }
2060
+ }
2061
+ } else {
2062
+ UNIMPLEMENTED(); // Not used by V8.
2063
+ }
2064
+ } else {
2065
+ // extra load/store instructions
2066
+ int rd = instr->RdValue();
2067
+ int rn = instr->RnValue();
2068
+ int32_t rn_val = get_register(rn);
2069
+ int32_t addr = 0;
2070
+ if (instr->Bit(22) == 0) {
2071
+ int rm = instr->RmValue();
2072
+ int32_t rm_val = get_register(rm);
2073
+ switch (instr->PUField()) {
2074
+ case da_x: {
2075
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
2076
+ ASSERT(!instr->HasW());
2077
+ addr = rn_val;
2078
+ rn_val -= rm_val;
2079
+ set_register(rn, rn_val);
2080
+ break;
2081
+ }
2082
+ case ia_x: {
2083
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
2084
+ ASSERT(!instr->HasW());
2085
+ addr = rn_val;
2086
+ rn_val += rm_val;
2087
+ set_register(rn, rn_val);
2088
+ break;
2089
+ }
2090
+ case db_x: {
2091
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
2092
+ rn_val -= rm_val;
2093
+ addr = rn_val;
2094
+ if (instr->HasW()) {
2095
+ set_register(rn, rn_val);
2096
+ }
2097
+ break;
2098
+ }
2099
+ case ib_x: {
2100
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
2101
+ rn_val += rm_val;
2102
+ addr = rn_val;
2103
+ if (instr->HasW()) {
2104
+ set_register(rn, rn_val);
2105
+ }
2106
+ break;
2107
+ }
2108
+ default: {
2109
+ // The PU field is a 2-bit field.
2110
+ UNREACHABLE();
2111
+ break;
2112
+ }
2113
+ }
2114
+ } else {
2115
+ int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2116
+ switch (instr->PUField()) {
2117
+ case da_x: {
2118
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
2119
+ ASSERT(!instr->HasW());
2120
+ addr = rn_val;
2121
+ rn_val -= imm_val;
2122
+ set_register(rn, rn_val);
2123
+ break;
2124
+ }
2125
+ case ia_x: {
2126
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
2127
+ ASSERT(!instr->HasW());
2128
+ addr = rn_val;
2129
+ rn_val += imm_val;
2130
+ set_register(rn, rn_val);
2131
+ break;
2132
+ }
2133
+ case db_x: {
2134
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
2135
+ rn_val -= imm_val;
2136
+ addr = rn_val;
2137
+ if (instr->HasW()) {
2138
+ set_register(rn, rn_val);
2139
+ }
2140
+ break;
2141
+ }
2142
+ case ib_x: {
2143
+ // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
2144
+ rn_val += imm_val;
2145
+ addr = rn_val;
2146
+ if (instr->HasW()) {
2147
+ set_register(rn, rn_val);
2148
+ }
2149
+ break;
2150
+ }
2151
+ default: {
2152
+ // The PU field is a 2-bit field.
2153
+ UNREACHABLE();
2154
+ break;
2155
+ }
2156
+ }
2157
+ }
2158
+ if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2159
+ ASSERT((rd % 2) == 0);
2160
+ if (instr->HasH()) {
2161
+ // The strd instruction.
2162
+ int32_t value1 = get_register(rd);
2163
+ int32_t value2 = get_register(rd+1);
2164
+ WriteDW(addr, value1, value2);
2165
+ } else {
2166
+ // The ldrd instruction.
2167
+ int* rn_data = ReadDW(addr);
2168
+ set_dw_register(rd, rn_data);
2169
+ }
2170
+ } else if (instr->HasH()) {
2171
+ if (instr->HasSign()) {
2172
+ if (instr->HasL()) {
2173
+ int16_t val = ReadH(addr, instr);
2174
+ set_register(rd, val);
2175
+ } else {
2176
+ int16_t val = get_register(rd);
2177
+ WriteH(addr, val, instr);
2178
+ }
2179
+ } else {
2180
+ if (instr->HasL()) {
2181
+ uint16_t val = ReadHU(addr, instr);
2182
+ set_register(rd, val);
2183
+ } else {
2184
+ uint16_t val = get_register(rd);
2185
+ WriteH(addr, val, instr);
2186
+ }
2187
+ }
2188
+ } else {
2189
+ // signed byte loads
2190
+ ASSERT(instr->HasSign());
2191
+ ASSERT(instr->HasL());
2192
+ int8_t val = ReadB(addr);
2193
+ set_register(rd, val);
2194
+ }
2195
+ return;
2196
+ }
2197
+ } else if ((type == 0) && instr->IsMiscType0()) {
2198
+ if (instr->Bits(22, 21) == 1) {
2199
+ int rm = instr->RmValue();
2200
+ switch (instr->BitField(7, 4)) {
2201
+ case BX:
2202
+ set_pc(get_register(rm));
2203
+ break;
2204
+ case BLX: {
2205
+ uint32_t old_pc = get_pc();
2206
+ set_pc(get_register(rm));
2207
+ set_register(lr, old_pc + Instruction::kInstrSize);
2208
+ break;
2209
+ }
2210
+ case BKPT: {
2211
+ ArmDebugger dbg(this);
2212
+ PrintF("Simulator hit BKPT.\n");
2213
+ dbg.Debug();
2214
+ break;
2215
+ }
2216
+ default:
2217
+ UNIMPLEMENTED();
2218
+ }
2219
+ } else if (instr->Bits(22, 21) == 3) {
2220
+ int rm = instr->RmValue();
2221
+ int rd = instr->RdValue();
2222
+ switch (instr->BitField(7, 4)) {
2223
+ case CLZ: {
2224
+ uint32_t bits = get_register(rm);
2225
+ int leading_zeros = 0;
2226
+ if (bits == 0) {
2227
+ leading_zeros = 32;
2228
+ } else {
2229
+ while ((bits & 0x80000000u) == 0) {
2230
+ bits <<= 1;
2231
+ leading_zeros++;
2232
+ }
2233
+ }
2234
+ set_register(rd, leading_zeros);
2235
+ break;
2236
+ }
2237
+ default:
2238
+ UNIMPLEMENTED();
2239
+ }
2240
+ } else {
2241
+ PrintF("%08x\n", instr->InstructionBits());
2242
+ UNIMPLEMENTED();
2243
+ }
2244
+ } else {
2245
+ int rd = instr->RdValue();
2246
+ int rn = instr->RnValue();
2247
+ int32_t rn_val = get_register(rn);
2248
+ int32_t shifter_operand = 0;
2249
+ bool shifter_carry_out = 0;
2250
+ if (type == 0) {
2251
+ shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2252
+ } else {
2253
+ ASSERT(instr->TypeValue() == 1);
2254
+ shifter_operand = GetImm(instr, &shifter_carry_out);
2255
+ }
2256
+ int32_t alu_out;
2257
+
2258
+ switch (instr->OpcodeField()) {
2259
+ case AND: {
2260
+ // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2261
+ // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2262
+ alu_out = rn_val & shifter_operand;
2263
+ set_register(rd, alu_out);
2264
+ if (instr->HasS()) {
2265
+ SetNZFlags(alu_out);
2266
+ SetCFlag(shifter_carry_out);
2267
+ }
2268
+ break;
2269
+ }
2270
+
2271
+ case EOR: {
2272
+ // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
2273
+ // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
2274
+ alu_out = rn_val ^ shifter_operand;
2275
+ set_register(rd, alu_out);
2276
+ if (instr->HasS()) {
2277
+ SetNZFlags(alu_out);
2278
+ SetCFlag(shifter_carry_out);
2279
+ }
2280
+ break;
2281
+ }
2282
+
2283
+ case SUB: {
2284
+ // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2285
+ // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2286
+ alu_out = rn_val - shifter_operand;
2287
+ set_register(rd, alu_out);
2288
+ if (instr->HasS()) {
2289
+ SetNZFlags(alu_out);
2290
+ SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2291
+ SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2292
+ }
2293
+ break;
2294
+ }
2295
+
2296
+ case RSB: {
2297
+ // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2298
+ // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2299
+ alu_out = shifter_operand - rn_val;
2300
+ set_register(rd, alu_out);
2301
+ if (instr->HasS()) {
2302
+ SetNZFlags(alu_out);
2303
+ SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2304
+ SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
2305
+ }
2306
+ break;
2307
+ }
2308
+
2309
+ case ADD: {
2310
+ // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2311
+ // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2312
+ alu_out = rn_val + shifter_operand;
2313
+ set_register(rd, alu_out);
2314
+ if (instr->HasS()) {
2315
+ SetNZFlags(alu_out);
2316
+ SetCFlag(CarryFrom(rn_val, shifter_operand));
2317
+ SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2318
+ }
2319
+ break;
2320
+ }
2321
+
2322
+ case ADC: {
2323
+ // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2324
+ // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2325
+ alu_out = rn_val + shifter_operand + GetCarry();
2326
+ set_register(rd, alu_out);
2327
+ if (instr->HasS()) {
2328
+ SetNZFlags(alu_out);
2329
+ SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2330
+ SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2331
+ }
2332
+ break;
2333
+ }
2334
+
2335
+ case SBC: {
2336
+ Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2337
+ Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2338
+ break;
2339
+ }
2340
+
2341
+ case RSC: {
2342
+ Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2343
+ Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2344
+ break;
2345
+ }
2346
+
2347
+ case TST: {
2348
+ if (instr->HasS()) {
2349
+ // Format(instr, "tst'cond 'rn, 'shift_rm");
2350
+ // Format(instr, "tst'cond 'rn, 'imm");
2351
+ alu_out = rn_val & shifter_operand;
2352
+ SetNZFlags(alu_out);
2353
+ SetCFlag(shifter_carry_out);
2354
+ } else {
2355
+ // Format(instr, "movw'cond 'rd, 'imm").
2356
+ alu_out = instr->ImmedMovwMovtValue();
2357
+ set_register(rd, alu_out);
2358
+ }
2359
+ break;
2360
+ }
2361
+
2362
+ case TEQ: {
2363
+ if (instr->HasS()) {
2364
+ // Format(instr, "teq'cond 'rn, 'shift_rm");
2365
+ // Format(instr, "teq'cond 'rn, 'imm");
2366
+ alu_out = rn_val ^ shifter_operand;
2367
+ SetNZFlags(alu_out);
2368
+ SetCFlag(shifter_carry_out);
2369
+ } else {
2370
+ // Other instructions matching this pattern are handled in the
2371
+ // miscellaneous instructions part above.
2372
+ UNREACHABLE();
2373
+ }
2374
+ break;
2375
+ }
2376
+
2377
+ case CMP: {
2378
+ if (instr->HasS()) {
2379
+ // Format(instr, "cmp'cond 'rn, 'shift_rm");
2380
+ // Format(instr, "cmp'cond 'rn, 'imm");
2381
+ alu_out = rn_val - shifter_operand;
2382
+ SetNZFlags(alu_out);
2383
+ SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2384
+ SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2385
+ } else {
2386
+ // Format(instr, "movt'cond 'rd, 'imm").
2387
+ alu_out = (get_register(rd) & 0xffff) |
2388
+ (instr->ImmedMovwMovtValue() << 16);
2389
+ set_register(rd, alu_out);
2390
+ }
2391
+ break;
2392
+ }
2393
+
2394
+ case CMN: {
2395
+ if (instr->HasS()) {
2396
+ // Format(instr, "cmn'cond 'rn, 'shift_rm");
2397
+ // Format(instr, "cmn'cond 'rn, 'imm");
2398
+ alu_out = rn_val + shifter_operand;
2399
+ SetNZFlags(alu_out);
2400
+ SetCFlag(!CarryFrom(rn_val, shifter_operand));
2401
+ SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2402
+ } else {
2403
+ // Other instructions matching this pattern are handled in the
2404
+ // miscellaneous instructions part above.
2405
+ UNREACHABLE();
2406
+ }
2407
+ break;
2408
+ }
2409
+
2410
+ case ORR: {
2411
+ // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2412
+ // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2413
+ alu_out = rn_val | shifter_operand;
2414
+ set_register(rd, alu_out);
2415
+ if (instr->HasS()) {
2416
+ SetNZFlags(alu_out);
2417
+ SetCFlag(shifter_carry_out);
2418
+ }
2419
+ break;
2420
+ }
2421
+
2422
+ case MOV: {
2423
+ // Format(instr, "mov'cond's 'rd, 'shift_rm");
2424
+ // Format(instr, "mov'cond's 'rd, 'imm");
2425
+ alu_out = shifter_operand;
2426
+ set_register(rd, alu_out);
2427
+ if (instr->HasS()) {
2428
+ SetNZFlags(alu_out);
2429
+ SetCFlag(shifter_carry_out);
2430
+ }
2431
+ break;
2432
+ }
2433
+
2434
+ case BIC: {
2435
+ // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
2436
+ // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
2437
+ alu_out = rn_val & ~shifter_operand;
2438
+ set_register(rd, alu_out);
2439
+ if (instr->HasS()) {
2440
+ SetNZFlags(alu_out);
2441
+ SetCFlag(shifter_carry_out);
2442
+ }
2443
+ break;
2444
+ }
2445
+
2446
+ case MVN: {
2447
+ // Format(instr, "mvn'cond's 'rd, 'shift_rm");
2448
+ // Format(instr, "mvn'cond's 'rd, 'imm");
2449
+ alu_out = ~shifter_operand;
2450
+ set_register(rd, alu_out);
2451
+ if (instr->HasS()) {
2452
+ SetNZFlags(alu_out);
2453
+ SetCFlag(shifter_carry_out);
2454
+ }
2455
+ break;
2456
+ }
2457
+
2458
+ default: {
2459
+ UNREACHABLE();
2460
+ break;
2461
+ }
2462
+ }
2463
+ }
2464
+ }
2465
+
2466
+
2467
+ void Simulator::DecodeType2(Instruction* instr) {
2468
+ int rd = instr->RdValue();
2469
+ int rn = instr->RnValue();
2470
+ int32_t rn_val = get_register(rn);
2471
+ int32_t im_val = instr->Offset12Value();
2472
+ int32_t addr = 0;
2473
+ switch (instr->PUField()) {
2474
+ case da_x: {
2475
+ // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
2476
+ ASSERT(!instr->HasW());
2477
+ addr = rn_val;
2478
+ rn_val -= im_val;
2479
+ set_register(rn, rn_val);
2480
+ break;
2481
+ }
2482
+ case ia_x: {
2483
+ // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
2484
+ ASSERT(!instr->HasW());
2485
+ addr = rn_val;
2486
+ rn_val += im_val;
2487
+ set_register(rn, rn_val);
2488
+ break;
2489
+ }
2490
+ case db_x: {
2491
+ // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
2492
+ rn_val -= im_val;
2493
+ addr = rn_val;
2494
+ if (instr->HasW()) {
2495
+ set_register(rn, rn_val);
2496
+ }
2497
+ break;
2498
+ }
2499
+ case ib_x: {
2500
+ // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
2501
+ rn_val += im_val;
2502
+ addr = rn_val;
2503
+ if (instr->HasW()) {
2504
+ set_register(rn, rn_val);
2505
+ }
2506
+ break;
2507
+ }
2508
+ default: {
2509
+ UNREACHABLE();
2510
+ break;
2511
+ }
2512
+ }
2513
+ if (instr->HasB()) {
2514
+ if (instr->HasL()) {
2515
+ byte val = ReadBU(addr);
2516
+ set_register(rd, val);
2517
+ } else {
2518
+ byte val = get_register(rd);
2519
+ WriteB(addr, val);
2520
+ }
2521
+ } else {
2522
+ if (instr->HasL()) {
2523
+ set_register(rd, ReadW(addr, instr));
2524
+ } else {
2525
+ WriteW(addr, get_register(rd), instr);
2526
+ }
2527
+ }
2528
+ }
2529
+
2530
+
2531
+ void Simulator::DecodeType3(Instruction* instr) {
2532
+ int rd = instr->RdValue();
2533
+ int rn = instr->RnValue();
2534
+ int32_t rn_val = get_register(rn);
2535
+ bool shifter_carry_out = 0;
2536
+ int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2537
+ int32_t addr = 0;
2538
+ switch (instr->PUField()) {
2539
+ case da_x: {
2540
+ ASSERT(!instr->HasW());
2541
+ Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
2542
+ UNIMPLEMENTED();
2543
+ break;
2544
+ }
2545
+ case ia_x: {
2546
+ if (instr->HasW()) {
2547
+ ASSERT(instr->Bits(5, 4) == 0x1);
2548
+
2549
+ if (instr->Bit(22) == 0x1) { // USAT.
2550
+ int32_t sat_pos = instr->Bits(20, 16);
2551
+ int32_t sat_val = (1 << sat_pos) - 1;
2552
+ int32_t shift = instr->Bits(11, 7);
2553
+ int32_t shift_type = instr->Bit(6);
2554
+ int32_t rm_val = get_register(instr->RmValue());
2555
+ if (shift_type == 0) { // LSL
2556
+ rm_val <<= shift;
2557
+ } else { // ASR
2558
+ rm_val >>= shift;
2559
+ }
2560
+ // If saturation occurs, the Q flag should be set in the CPSR.
2561
+ // There is no Q flag yet, and no instruction (MRS) to read the
2562
+ // CPSR directly.
2563
+ if (rm_val > sat_val) {
2564
+ rm_val = sat_val;
2565
+ } else if (rm_val < 0) {
2566
+ rm_val = 0;
2567
+ }
2568
+ set_register(rd, rm_val);
2569
+ } else { // SSAT.
2570
+ UNIMPLEMENTED();
2571
+ }
2572
+ return;
2573
+ } else {
2574
+ Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
2575
+ UNIMPLEMENTED();
2576
+ }
2577
+ break;
2578
+ }
2579
+ case db_x: {
2580
+ // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
2581
+ addr = rn_val - shifter_operand;
2582
+ if (instr->HasW()) {
2583
+ set_register(rn, addr);
2584
+ }
2585
+ break;
2586
+ }
2587
+ case ib_x: {
2588
+ if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2589
+ uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
2590
+ uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2591
+ uint32_t msbit = widthminus1 + lsbit;
2592
+ if (msbit <= 31) {
2593
+ if (instr->Bit(22)) {
2594
+ // ubfx - unsigned bitfield extract.
2595
+ uint32_t rm_val =
2596
+ static_cast<uint32_t>(get_register(instr->RmValue()));
2597
+ uint32_t extr_val = rm_val << (31 - msbit);
2598
+ extr_val = extr_val >> (31 - widthminus1);
2599
+ set_register(instr->RdValue(), extr_val);
2600
+ } else {
2601
+ // sbfx - signed bitfield extract.
2602
+ int32_t rm_val = get_register(instr->RmValue());
2603
+ int32_t extr_val = rm_val << (31 - msbit);
2604
+ extr_val = extr_val >> (31 - widthminus1);
2605
+ set_register(instr->RdValue(), extr_val);
2606
+ }
2607
+ } else {
2608
+ UNREACHABLE();
2609
+ }
2610
+ return;
2611
+ } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2612
+ uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2613
+ uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
2614
+ if (msbit >= lsbit) {
2615
+ // bfc or bfi - bitfield clear/insert.
2616
+ uint32_t rd_val =
2617
+ static_cast<uint32_t>(get_register(instr->RdValue()));
2618
+ uint32_t bitcount = msbit - lsbit + 1;
2619
+ uint32_t mask = (1 << bitcount) - 1;
2620
+ rd_val &= ~(mask << lsbit);
2621
+ if (instr->RmValue() != 15) {
2622
+ // bfi - bitfield insert.
2623
+ uint32_t rm_val =
2624
+ static_cast<uint32_t>(get_register(instr->RmValue()));
2625
+ rm_val &= mask;
2626
+ rd_val |= rm_val << lsbit;
2627
+ }
2628
+ set_register(instr->RdValue(), rd_val);
2629
+ } else {
2630
+ UNREACHABLE();
2631
+ }
2632
+ return;
2633
+ } else {
2634
+ // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
2635
+ addr = rn_val + shifter_operand;
2636
+ if (instr->HasW()) {
2637
+ set_register(rn, addr);
2638
+ }
2639
+ }
2640
+ break;
2641
+ }
2642
+ default: {
2643
+ UNREACHABLE();
2644
+ break;
2645
+ }
2646
+ }
2647
+ if (instr->HasB()) {
2648
+ if (instr->HasL()) {
2649
+ uint8_t byte = ReadB(addr);
2650
+ set_register(rd, byte);
2651
+ } else {
2652
+ uint8_t byte = get_register(rd);
2653
+ WriteB(addr, byte);
2654
+ }
2655
+ } else {
2656
+ if (instr->HasL()) {
2657
+ set_register(rd, ReadW(addr, instr));
2658
+ } else {
2659
+ WriteW(addr, get_register(rd), instr);
2660
+ }
2661
+ }
2662
+ }
2663
+
2664
+
2665
+ void Simulator::DecodeType4(Instruction* instr) {
2666
+ ASSERT(instr->Bit(22) == 0); // only allowed to be set in privileged mode
2667
+ if (instr->HasL()) {
2668
+ // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
2669
+ HandleRList(instr, true);
2670
+ } else {
2671
+ // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
2672
+ HandleRList(instr, false);
2673
+ }
2674
+ }
2675
+
2676
+
2677
+ void Simulator::DecodeType5(Instruction* instr) {
2678
+ // Format(instr, "b'l'cond 'target");
2679
+ int off = (instr->SImmed24Value() << 2);
2680
+ intptr_t pc_address = get_pc();
2681
+ if (instr->HasLink()) {
2682
+ set_register(lr, pc_address + Instruction::kInstrSize);
2683
+ }
2684
+ int pc_reg = get_register(pc);
2685
+ set_pc(pc_reg + off);
2686
+ }
2687
+
2688
+
2689
+ void Simulator::DecodeType6(Instruction* instr) {
2690
+ DecodeType6CoprocessorIns(instr);
2691
+ }
2692
+
2693
+
2694
+ void Simulator::DecodeType7(Instruction* instr) {
2695
+ if (instr->Bit(24) == 1) {
2696
+ SoftwareInterrupt(instr);
2697
+ } else {
2698
+ DecodeTypeVFP(instr);
2699
+ }
2700
+ }
2701
+
2702
+
2703
+ // void Simulator::DecodeTypeVFP(Instruction* instr)
2704
+ // The Following ARMv7 VFPv instructions are currently supported.
2705
+ // vmov :Sn = Rt
2706
+ // vmov :Rt = Sn
2707
+ // vcvt: Dd = Sm
2708
+ // vcvt: Sd = Dm
2709
+ // Dd = vabs(Dm)
2710
+ // Dd = vneg(Dm)
2711
+ // Dd = vadd(Dn, Dm)
2712
+ // Dd = vsub(Dn, Dm)
2713
+ // Dd = vmul(Dn, Dm)
2714
+ // Dd = vdiv(Dn, Dm)
2715
+ // vcmp(Dd, Dm)
2716
+ // vmrs
2717
+ // Dd = vsqrt(Dm)
2718
+ void Simulator::DecodeTypeVFP(Instruction* instr) {
2719
+ ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2720
+ ASSERT(instr->Bits(11, 9) == 0x5);
2721
+
2722
+ // Obtain double precision register codes.
2723
+ int vm = instr->VFPMRegValue(kDoublePrecision);
2724
+ int vd = instr->VFPDRegValue(kDoublePrecision);
2725
+ int vn = instr->VFPNRegValue(kDoublePrecision);
2726
+
2727
+ if (instr->Bit(4) == 0) {
2728
+ if (instr->Opc1Value() == 0x7) {
2729
+ // Other data processing instructions
2730
+ if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2731
+ // vmov register to register.
2732
+ if (instr->SzValue() == 0x1) {
2733
+ int m = instr->VFPMRegValue(kDoublePrecision);
2734
+ int d = instr->VFPDRegValue(kDoublePrecision);
2735
+ set_d_register_from_double(d, get_double_from_d_register(m));
2736
+ } else {
2737
+ int m = instr->VFPMRegValue(kSinglePrecision);
2738
+ int d = instr->VFPDRegValue(kSinglePrecision);
2739
+ set_s_register_from_float(d, get_float_from_s_register(m));
2740
+ }
2741
+ } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2742
+ // vabs
2743
+ double dm_value = get_double_from_d_register(vm);
2744
+ double dd_value = fabs(dm_value);
2745
+ set_d_register_from_double(vd, dd_value);
2746
+ } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2747
+ // vneg
2748
+ double dm_value = get_double_from_d_register(vm);
2749
+ double dd_value = -dm_value;
2750
+ set_d_register_from_double(vd, dd_value);
2751
+ } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2752
+ DecodeVCVTBetweenDoubleAndSingle(instr);
2753
+ } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2754
+ DecodeVCVTBetweenFloatingPointAndInteger(instr);
2755
+ } else if (((instr->Opc2Value() >> 1) == 0x6) &&
2756
+ (instr->Opc3Value() & 0x1)) {
2757
+ DecodeVCVTBetweenFloatingPointAndInteger(instr);
2758
+ } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2759
+ (instr->Opc3Value() & 0x1)) {
2760
+ DecodeVCMP(instr);
2761
+ } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2762
+ // vsqrt
2763
+ double dm_value = get_double_from_d_register(vm);
2764
+ double dd_value = sqrt(dm_value);
2765
+ set_d_register_from_double(vd, dd_value);
2766
+ } else if (instr->Opc3Value() == 0x0) {
2767
+ // vmov immediate.
2768
+ if (instr->SzValue() == 0x1) {
2769
+ set_d_register_from_double(vd, instr->DoubleImmedVmov());
2770
+ } else {
2771
+ UNREACHABLE(); // Not used by v8.
2772
+ }
2773
+ } else {
2774
+ UNREACHABLE(); // Not used by V8.
2775
+ }
2776
+ } else if (instr->Opc1Value() == 0x3) {
2777
+ if (instr->SzValue() != 0x1) {
2778
+ UNREACHABLE(); // Not used by V8.
2779
+ }
2780
+
2781
+ if (instr->Opc3Value() & 0x1) {
2782
+ // vsub
2783
+ double dn_value = get_double_from_d_register(vn);
2784
+ double dm_value = get_double_from_d_register(vm);
2785
+ double dd_value = dn_value - dm_value;
2786
+ set_d_register_from_double(vd, dd_value);
2787
+ } else {
2788
+ // vadd
2789
+ double dn_value = get_double_from_d_register(vn);
2790
+ double dm_value = get_double_from_d_register(vm);
2791
+ double dd_value = dn_value + dm_value;
2792
+ set_d_register_from_double(vd, dd_value);
2793
+ }
2794
+ } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2795
+ // vmul
2796
+ if (instr->SzValue() != 0x1) {
2797
+ UNREACHABLE(); // Not used by V8.
2798
+ }
2799
+
2800
+ double dn_value = get_double_from_d_register(vn);
2801
+ double dm_value = get_double_from_d_register(vm);
2802
+ double dd_value = dn_value * dm_value;
2803
+ set_d_register_from_double(vd, dd_value);
2804
+ } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
2805
+ // vdiv
2806
+ if (instr->SzValue() != 0x1) {
2807
+ UNREACHABLE(); // Not used by V8.
2808
+ }
2809
+
2810
+ double dn_value = get_double_from_d_register(vn);
2811
+ double dm_value = get_double_from_d_register(vm);
2812
+ double dd_value = dn_value / dm_value;
2813
+ div_zero_vfp_flag_ = (dm_value == 0);
2814
+ set_d_register_from_double(vd, dd_value);
2815
+ } else {
2816
+ UNIMPLEMENTED(); // Not used by V8.
2817
+ }
2818
+ } else {
2819
+ if ((instr->VCValue() == 0x0) &&
2820
+ (instr->VAValue() == 0x0)) {
2821
+ DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
2822
+ } else if ((instr->VLValue() == 0x1) &&
2823
+ (instr->VCValue() == 0x0) &&
2824
+ (instr->VAValue() == 0x7) &&
2825
+ (instr->Bits(19, 16) == 0x1)) {
2826
+ // vmrs
2827
+ uint32_t rt = instr->RtValue();
2828
+ if (rt == 0xF) {
2829
+ Copy_FPSCR_to_APSR();
2830
+ } else {
2831
+ // Emulate FPSCR from the Simulator flags.
2832
+ uint32_t fpscr = (n_flag_FPSCR_ << 31) |
2833
+ (z_flag_FPSCR_ << 30) |
2834
+ (c_flag_FPSCR_ << 29) |
2835
+ (v_flag_FPSCR_ << 28) |
2836
+ (inexact_vfp_flag_ << 4) |
2837
+ (underflow_vfp_flag_ << 3) |
2838
+ (overflow_vfp_flag_ << 2) |
2839
+ (div_zero_vfp_flag_ << 1) |
2840
+ (inv_op_vfp_flag_ << 0) |
2841
+ (FPSCR_rounding_mode_);
2842
+ set_register(rt, fpscr);
2843
+ }
2844
+ } else if ((instr->VLValue() == 0x0) &&
2845
+ (instr->VCValue() == 0x0) &&
2846
+ (instr->VAValue() == 0x7) &&
2847
+ (instr->Bits(19, 16) == 0x1)) {
2848
+ // vmsr
2849
+ uint32_t rt = instr->RtValue();
2850
+ if (rt == pc) {
2851
+ UNREACHABLE();
2852
+ } else {
2853
+ uint32_t rt_value = get_register(rt);
2854
+ n_flag_FPSCR_ = (rt_value >> 31) & 1;
2855
+ z_flag_FPSCR_ = (rt_value >> 30) & 1;
2856
+ c_flag_FPSCR_ = (rt_value >> 29) & 1;
2857
+ v_flag_FPSCR_ = (rt_value >> 28) & 1;
2858
+ inexact_vfp_flag_ = (rt_value >> 4) & 1;
2859
+ underflow_vfp_flag_ = (rt_value >> 3) & 1;
2860
+ overflow_vfp_flag_ = (rt_value >> 2) & 1;
2861
+ div_zero_vfp_flag_ = (rt_value >> 1) & 1;
2862
+ inv_op_vfp_flag_ = (rt_value >> 0) & 1;
2863
+ FPSCR_rounding_mode_ =
2864
+ static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
2865
+ }
2866
+ } else {
2867
+ UNIMPLEMENTED(); // Not used by V8.
2868
+ }
2869
+ }
2870
+ }
2871
+
2872
+
2873
+ void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
2874
+ Instruction* instr) {
2875
+ ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
2876
+ (instr->VAValue() == 0x0));
2877
+
2878
+ int t = instr->RtValue();
2879
+ int n = instr->VFPNRegValue(kSinglePrecision);
2880
+ bool to_arm_register = (instr->VLValue() == 0x1);
2881
+
2882
+ if (to_arm_register) {
2883
+ int32_t int_value = get_sinteger_from_s_register(n);
2884
+ set_register(t, int_value);
2885
+ } else {
2886
+ int32_t rs_val = get_register(t);
2887
+ set_s_register_from_sinteger(n, rs_val);
2888
+ }
2889
+ }
2890
+
2891
+
2892
+ void Simulator::DecodeVCMP(Instruction* instr) {
2893
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
2894
+ ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2895
+ (instr->Opc3Value() & 0x1));
2896
+ // Comparison.
2897
+
2898
+ VFPRegPrecision precision = kSinglePrecision;
2899
+ if (instr->SzValue() == 1) {
2900
+ precision = kDoublePrecision;
2901
+ }
2902
+
2903
+ int d = instr->VFPDRegValue(precision);
2904
+ int m = 0;
2905
+ if (instr->Opc2Value() == 0x4) {
2906
+ m = instr->VFPMRegValue(precision);
2907
+ }
2908
+
2909
+ if (precision == kDoublePrecision) {
2910
+ double dd_value = get_double_from_d_register(d);
2911
+ double dm_value = 0.0;
2912
+ if (instr->Opc2Value() == 0x4) {
2913
+ dm_value = get_double_from_d_register(m);
2914
+ }
2915
+
2916
+ // Raise exceptions for quiet NaNs if necessary.
2917
+ if (instr->Bit(7) == 1) {
2918
+ if (isnan(dd_value)) {
2919
+ inv_op_vfp_flag_ = true;
2920
+ }
2921
+ }
2922
+
2923
+ Compute_FPSCR_Flags(dd_value, dm_value);
2924
+ } else {
2925
+ UNIMPLEMENTED(); // Not used by V8.
2926
+ }
2927
+ }
2928
+
2929
+
2930
+ void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
2931
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
2932
+ ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
2933
+
2934
+ VFPRegPrecision dst_precision = kDoublePrecision;
2935
+ VFPRegPrecision src_precision = kSinglePrecision;
2936
+ if (instr->SzValue() == 1) {
2937
+ dst_precision = kSinglePrecision;
2938
+ src_precision = kDoublePrecision;
2939
+ }
2940
+
2941
+ int dst = instr->VFPDRegValue(dst_precision);
2942
+ int src = instr->VFPMRegValue(src_precision);
2943
+
2944
+ if (dst_precision == kSinglePrecision) {
2945
+ double val = get_double_from_d_register(src);
2946
+ set_s_register_from_float(dst, static_cast<float>(val));
2947
+ } else {
2948
+ float val = get_float_from_s_register(src);
2949
+ set_d_register_from_double(dst, static_cast<double>(val));
2950
+ }
2951
+ }
2952
+
2953
+ bool get_inv_op_vfp_flag(VFPRoundingMode mode,
2954
+ double val,
2955
+ bool unsigned_) {
2956
+ ASSERT((mode == RN) || (mode == RM) || (mode == RZ));
2957
+ double max_uint = static_cast<double>(0xffffffffu);
2958
+ double max_int = static_cast<double>(kMaxInt);
2959
+ double min_int = static_cast<double>(kMinInt);
2960
+
2961
+ // Check for NaN.
2962
+ if (val != val) {
2963
+ return true;
2964
+ }
2965
+
2966
+ // Check for overflow. This code works because 32bit integers can be
2967
+ // exactly represented by ieee-754 64bit floating-point values.
2968
+ switch (mode) {
2969
+ case RN:
2970
+ return unsigned_ ? (val >= (max_uint + 0.5)) ||
2971
+ (val < -0.5)
2972
+ : (val >= (max_int + 0.5)) ||
2973
+ (val < (min_int - 0.5));
2974
+
2975
+ case RM:
2976
+ return unsigned_ ? (val >= (max_uint + 1.0)) ||
2977
+ (val < 0)
2978
+ : (val >= (max_int + 1.0)) ||
2979
+ (val < min_int);
2980
+
2981
+ case RZ:
2982
+ return unsigned_ ? (val >= (max_uint + 1.0)) ||
2983
+ (val <= -1)
2984
+ : (val >= (max_int + 1.0)) ||
2985
+ (val <= (min_int - 1.0));
2986
+ default:
2987
+ UNREACHABLE();
2988
+ return true;
2989
+ }
2990
+ }
2991
+
2992
+
2993
+ // We call this function only if we had a vfp invalid exception.
2994
+ // It returns the correct saturated value.
2995
+ int VFPConversionSaturate(double val, bool unsigned_res) {
2996
+ if (val != val) {
2997
+ return 0;
2998
+ } else {
2999
+ if (unsigned_res) {
3000
+ return (val < 0) ? 0 : 0xffffffffu;
3001
+ } else {
3002
+ return (val < 0) ? kMinInt : kMaxInt;
3003
+ }
3004
+ }
3005
+ }
3006
+
3007
+
3008
+ void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3009
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3010
+ (instr->Bits(27, 23) == 0x1D));
3011
+ ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3012
+ (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3013
+
3014
+ // Conversion between floating-point and integer.
3015
+ bool to_integer = (instr->Bit(18) == 1);
3016
+
3017
+ VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3018
+ : kSinglePrecision;
3019
+
3020
+ if (to_integer) {
3021
+ // We are playing with code close to the C++ standard's limits below,
3022
+ // hence the very simple code and heavy checks.
3023
+ //
3024
+ // Note:
3025
+ // C++ defines default type casting from floating point to integer as
3026
+ // (close to) rounding toward zero ("fractional part discarded").
3027
+
3028
+ int dst = instr->VFPDRegValue(kSinglePrecision);
3029
+ int src = instr->VFPMRegValue(src_precision);
3030
+
3031
+ // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
3032
+ // mode or the default Round to Zero mode.
3033
+ VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3034
+ : RZ;
3035
+ ASSERT((mode == RM) || (mode == RZ) || (mode == RN));
3036
+
3037
+ bool unsigned_integer = (instr->Bit(16) == 0);
3038
+ bool double_precision = (src_precision == kDoublePrecision);
3039
+
3040
+ double val = double_precision ? get_double_from_d_register(src)
3041
+ : get_float_from_s_register(src);
3042
+
3043
+ int temp = unsigned_integer ? static_cast<uint32_t>(val)
3044
+ : static_cast<int32_t>(val);
3045
+
3046
+ inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3047
+
3048
+ double abs_diff =
3049
+ unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
3050
+ : fabs(val - temp);
3051
+
3052
+ inexact_vfp_flag_ = (abs_diff != 0);
3053
+
3054
+ if (inv_op_vfp_flag_) {
3055
+ temp = VFPConversionSaturate(val, unsigned_integer);
3056
+ } else {
3057
+ switch (mode) {
3058
+ case RN: {
3059
+ int val_sign = (val > 0) ? 1 : -1;
3060
+ if (abs_diff > 0.5) {
3061
+ temp += val_sign;
3062
+ } else if (abs_diff == 0.5) {
3063
+ // Round to even if exactly halfway.
3064
+ temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3065
+ }
3066
+ break;
3067
+ }
3068
+
3069
+ case RM:
3070
+ temp = temp > val ? temp - 1 : temp;
3071
+ break;
3072
+
3073
+ case RZ:
3074
+ // Nothing to do.
3075
+ break;
3076
+
3077
+ default:
3078
+ UNREACHABLE();
3079
+ }
3080
+ }
3081
+
3082
+ // Update the destination register.
3083
+ set_s_register_from_sinteger(dst, temp);
3084
+
3085
+ } else {
3086
+ bool unsigned_integer = (instr->Bit(7) == 0);
3087
+
3088
+ int dst = instr->VFPDRegValue(src_precision);
3089
+ int src = instr->VFPMRegValue(kSinglePrecision);
3090
+
3091
+ int val = get_sinteger_from_s_register(src);
3092
+
3093
+ if (src_precision == kDoublePrecision) {
3094
+ if (unsigned_integer) {
3095
+ set_d_register_from_double(dst,
3096
+ static_cast<double>((uint32_t)val));
3097
+ } else {
3098
+ set_d_register_from_double(dst, static_cast<double>(val));
3099
+ }
3100
+ } else {
3101
+ if (unsigned_integer) {
3102
+ set_s_register_from_float(dst,
3103
+ static_cast<float>((uint32_t)val));
3104
+ } else {
3105
+ set_s_register_from_float(dst, static_cast<float>(val));
3106
+ }
3107
+ }
3108
+ }
3109
+ }
3110
+
3111
+
3112
+ // void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
3113
+ // Decode Type 6 coprocessor instructions.
3114
+ // Dm = vmov(Rt, Rt2)
3115
+ // <Rt, Rt2> = vmov(Dm)
3116
+ // Ddst = MEM(Rbase + 4*offset).
3117
+ // MEM(Rbase + 4*offset) = Dsrc.
3118
+ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3119
+ ASSERT((instr->TypeValue() == 6));
3120
+
3121
+ if (instr->CoprocessorValue() == 0xA) {
3122
+ switch (instr->OpcodeValue()) {
3123
+ case 0x8:
3124
+ case 0xA:
3125
+ case 0xC:
3126
+ case 0xE: { // Load and store single precision float to memory.
3127
+ int rn = instr->RnValue();
3128
+ int vd = instr->VFPDRegValue(kSinglePrecision);
3129
+ int offset = instr->Immed8Value();
3130
+ if (!instr->HasU()) {
3131
+ offset = -offset;
3132
+ }
3133
+
3134
+ int32_t address = get_register(rn) + 4 * offset;
3135
+ if (instr->HasL()) {
3136
+ // Load double from memory: vldr.
3137
+ set_s_register_from_sinteger(vd, ReadW(address, instr));
3138
+ } else {
3139
+ // Store double to memory: vstr.
3140
+ WriteW(address, get_sinteger_from_s_register(vd), instr);
3141
+ }
3142
+ break;
3143
+ }
3144
+ case 0x4:
3145
+ case 0x5:
3146
+ case 0x6:
3147
+ case 0x7:
3148
+ case 0x9:
3149
+ case 0xB:
3150
+ // Load/store multiple single from memory: vldm/vstm.
3151
+ HandleVList(instr);
3152
+ break;
3153
+ default:
3154
+ UNIMPLEMENTED(); // Not used by V8.
3155
+ }
3156
+ } else if (instr->CoprocessorValue() == 0xB) {
3157
+ switch (instr->OpcodeValue()) {
3158
+ case 0x2:
3159
+ // Load and store double to two GP registers
3160
+ if (instr->Bits(7, 4) != 0x1) {
3161
+ UNIMPLEMENTED(); // Not used by V8.
3162
+ } else {
3163
+ int rt = instr->RtValue();
3164
+ int rn = instr->RnValue();
3165
+ int vm = instr->VmValue();
3166
+ if (instr->HasL()) {
3167
+ int32_t rt_int_value = get_sinteger_from_s_register(2*vm);
3168
+ int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1);
3169
+
3170
+ set_register(rt, rt_int_value);
3171
+ set_register(rn, rn_int_value);
3172
+ } else {
3173
+ int32_t rs_val = get_register(rt);
3174
+ int32_t rn_val = get_register(rn);
3175
+
3176
+ set_s_register_from_sinteger(2*vm, rs_val);
3177
+ set_s_register_from_sinteger((2*vm+1), rn_val);
3178
+ }
3179
+ }
3180
+ break;
3181
+ case 0x8:
3182
+ case 0xC: { // Load and store double to memory.
3183
+ int rn = instr->RnValue();
3184
+ int vd = instr->VdValue();
3185
+ int offset = instr->Immed8Value();
3186
+ if (!instr->HasU()) {
3187
+ offset = -offset;
3188
+ }
3189
+ int32_t address = get_register(rn) + 4 * offset;
3190
+ if (instr->HasL()) {
3191
+ // Load double from memory: vldr.
3192
+ set_s_register_from_sinteger(2*vd, ReadW(address, instr));
3193
+ set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr));
3194
+ } else {
3195
+ // Store double to memory: vstr.
3196
+ WriteW(address, get_sinteger_from_s_register(2*vd), instr);
3197
+ WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr);
3198
+ }
3199
+ break;
3200
+ }
3201
+ case 0x4:
3202
+ case 0x5:
3203
+ case 0x9:
3204
+ // Load/store multiple double from memory: vldm/vstm.
3205
+ HandleVList(instr);
3206
+ break;
3207
+ default:
3208
+ UNIMPLEMENTED(); // Not used by V8.
3209
+ }
3210
+ } else {
3211
+ UNIMPLEMENTED(); // Not used by V8.
3212
+ }
3213
+ }
3214
+
3215
+
3216
+ // Executes the current instruction.
3217
+ void Simulator::InstructionDecode(Instruction* instr) {
3218
+ if (v8::internal::FLAG_check_icache) {
3219
+ CheckICache(isolate_->simulator_i_cache(), instr);
3220
+ }
3221
+ pc_modified_ = false;
3222
+ if (::v8::internal::FLAG_trace_sim) {
3223
+ disasm::NameConverter converter;
3224
+ disasm::Disassembler dasm(converter);
3225
+ // use a reasonably large buffer
3226
+ v8::internal::EmbeddedVector<char, 256> buffer;
3227
+ dasm.InstructionDecode(buffer,
3228
+ reinterpret_cast<byte*>(instr));
3229
+ PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
3230
+ }
3231
+ if (instr->ConditionField() == kSpecialCondition) {
3232
+ UNIMPLEMENTED();
3233
+ } else if (ConditionallyExecute(instr)) {
3234
+ switch (instr->TypeValue()) {
3235
+ case 0:
3236
+ case 1: {
3237
+ DecodeType01(instr);
3238
+ break;
3239
+ }
3240
+ case 2: {
3241
+ DecodeType2(instr);
3242
+ break;
3243
+ }
3244
+ case 3: {
3245
+ DecodeType3(instr);
3246
+ break;
3247
+ }
3248
+ case 4: {
3249
+ DecodeType4(instr);
3250
+ break;
3251
+ }
3252
+ case 5: {
3253
+ DecodeType5(instr);
3254
+ break;
3255
+ }
3256
+ case 6: {
3257
+ DecodeType6(instr);
3258
+ break;
3259
+ }
3260
+ case 7: {
3261
+ DecodeType7(instr);
3262
+ break;
3263
+ }
3264
+ default: {
3265
+ UNIMPLEMENTED();
3266
+ break;
3267
+ }
3268
+ }
3269
+ // If the instruction is a non taken conditional stop, we need to skip the
3270
+ // inlined message address.
3271
+ } else if (instr->IsStop()) {
3272
+ set_pc(get_pc() + 2 * Instruction::kInstrSize);
3273
+ }
3274
+ if (!pc_modified_) {
3275
+ set_register(pc, reinterpret_cast<int32_t>(instr)
3276
+ + Instruction::kInstrSize);
3277
+ }
3278
+ }
3279
+
3280
+
3281
+ void Simulator::Execute() {
3282
+ // Get the PC to simulate. Cannot use the accessor here as we need the
3283
+ // raw PC value and not the one used as input to arithmetic instructions.
3284
+ int program_counter = get_pc();
3285
+
3286
+ if (::v8::internal::FLAG_stop_sim_at == 0) {
3287
+ // Fast version of the dispatch loop without checking whether the simulator
3288
+ // should be stopping at a particular executed instruction.
3289
+ while (program_counter != end_sim_pc) {
3290
+ Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3291
+ icount_++;
3292
+ InstructionDecode(instr);
3293
+ program_counter = get_pc();
3294
+ }
3295
+ } else {
3296
+ // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3297
+ // we reach the particular instuction count.
3298
+ while (program_counter != end_sim_pc) {
3299
+ Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3300
+ icount_++;
3301
+ if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3302
+ ArmDebugger dbg(this);
3303
+ dbg.Debug();
3304
+ } else {
3305
+ InstructionDecode(instr);
3306
+ }
3307
+ program_counter = get_pc();
3308
+ }
3309
+ }
3310
+ }
3311
+
3312
+
3313
+ int32_t Simulator::Call(byte* entry, int argument_count, ...) {
3314
+ va_list parameters;
3315
+ va_start(parameters, argument_count);
3316
+ // Setup arguments
3317
+
3318
+ // First four arguments passed in registers.
3319
+ ASSERT(argument_count >= 4);
3320
+ set_register(r0, va_arg(parameters, int32_t));
3321
+ set_register(r1, va_arg(parameters, int32_t));
3322
+ set_register(r2, va_arg(parameters, int32_t));
3323
+ set_register(r3, va_arg(parameters, int32_t));
3324
+
3325
+ // Remaining arguments passed on stack.
3326
+ int original_stack = get_register(sp);
3327
+ // Compute position of stack on entry to generated code.
3328
+ int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
3329
+ if (OS::ActivationFrameAlignment() != 0) {
3330
+ entry_stack &= -OS::ActivationFrameAlignment();
3331
+ }
3332
+ // Store remaining arguments on stack, from low to high memory.
3333
+ intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
3334
+ for (int i = 4; i < argument_count; i++) {
3335
+ stack_argument[i - 4] = va_arg(parameters, int32_t);
3336
+ }
3337
+ va_end(parameters);
3338
+ set_register(sp, entry_stack);
3339
+
3340
+ // Prepare to execute the code at entry
3341
+ set_register(pc, reinterpret_cast<int32_t>(entry));
3342
+ // Put down marker for end of simulation. The simulator will stop simulation
3343
+ // when the PC reaches this value. By saving the "end simulation" value into
3344
+ // the LR the simulation stops when returning to this call point.
3345
+ set_register(lr, end_sim_pc);
3346
+
3347
+ // Remember the values of callee-saved registers.
3348
+ // The code below assumes that r9 is not used as sb (static base) in
3349
+ // simulator code and therefore is regarded as a callee-saved register.
3350
+ int32_t r4_val = get_register(r4);
3351
+ int32_t r5_val = get_register(r5);
3352
+ int32_t r6_val = get_register(r6);
3353
+ int32_t r7_val = get_register(r7);
3354
+ int32_t r8_val = get_register(r8);
3355
+ int32_t r9_val = get_register(r9);
3356
+ int32_t r10_val = get_register(r10);
3357
+ int32_t r11_val = get_register(r11);
3358
+
3359
+ // Setup the callee-saved registers with a known value. To be able to check
3360
+ // that they are preserved properly across JS execution.
3361
+ int32_t callee_saved_value = icount_;
3362
+ set_register(r4, callee_saved_value);
3363
+ set_register(r5, callee_saved_value);
3364
+ set_register(r6, callee_saved_value);
3365
+ set_register(r7, callee_saved_value);
3366
+ set_register(r8, callee_saved_value);
3367
+ set_register(r9, callee_saved_value);
3368
+ set_register(r10, callee_saved_value);
3369
+ set_register(r11, callee_saved_value);
3370
+
3371
+ // Start the simulation
3372
+ Execute();
3373
+
3374
+ // Check that the callee-saved registers have been preserved.
3375
+ CHECK_EQ(callee_saved_value, get_register(r4));
3376
+ CHECK_EQ(callee_saved_value, get_register(r5));
3377
+ CHECK_EQ(callee_saved_value, get_register(r6));
3378
+ CHECK_EQ(callee_saved_value, get_register(r7));
3379
+ CHECK_EQ(callee_saved_value, get_register(r8));
3380
+ CHECK_EQ(callee_saved_value, get_register(r9));
3381
+ CHECK_EQ(callee_saved_value, get_register(r10));
3382
+ CHECK_EQ(callee_saved_value, get_register(r11));
3383
+
3384
+ // Restore callee-saved registers with the original value.
3385
+ set_register(r4, r4_val);
3386
+ set_register(r5, r5_val);
3387
+ set_register(r6, r6_val);
3388
+ set_register(r7, r7_val);
3389
+ set_register(r8, r8_val);
3390
+ set_register(r9, r9_val);
3391
+ set_register(r10, r10_val);
3392
+ set_register(r11, r11_val);
3393
+
3394
+ // Pop stack passed arguments.
3395
+ CHECK_EQ(entry_stack, get_register(sp));
3396
+ set_register(sp, original_stack);
3397
+
3398
+ int32_t result = get_register(r0);
3399
+ return result;
3400
+ }
3401
+
3402
+
3403
+ uintptr_t Simulator::PushAddress(uintptr_t address) {
3404
+ int new_sp = get_register(sp) - sizeof(uintptr_t);
3405
+ uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
3406
+ *stack_slot = address;
3407
+ set_register(sp, new_sp);
3408
+ return new_sp;
3409
+ }
3410
+
3411
+
3412
+ uintptr_t Simulator::PopAddress() {
3413
+ int current_sp = get_register(sp);
3414
+ uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
3415
+ uintptr_t address = *stack_slot;
3416
+ set_register(sp, current_sp + sizeof(uintptr_t));
3417
+ return address;
3418
+ }
3419
+
3420
+ } } // namespace v8::internal
3421
+
3422
+ #endif // USE_SIMULATOR
3423
+
3424
+ #endif // V8_TARGET_ARCH_ARM