Description: Backport powerpc/ppc64/ppc64el support to 3.14
Author: Andrew Low <Andrew_Low@ca.ibm.com>
Reviewed-By: Adam Conrad <adconrad@ubuntu.com>
Last-Update: 2014-02-12

 To reproduce this patch:

 git clone https://github.com/andrewlow/v8ppc.git && cd v8ppc
 git diff 6b10fef46edfb4dc2a7aed389d75574c40a14243 7d1b8b5d040a7d622bbde464ea29f6a7e89c90b6

 Edit to remove hunk in src/checks.h that overlaps with 0013_gcc_48_compat.patch

diff --git a/.gitignore b/.gitignore
index 0bf9313..74057ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@
 *.sln
 *.so
 *.suo
+*.swp
 *.user
 *.vcproj
 *.xcodeproj
diff --git a/AUTHORS b/AUTHORS
index 9c43bb5..ae029fe 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,6 +7,7 @@ Google Inc.
 Sigma Designs Inc.
 ARM Ltd.
 Hewlett-Packard Development Company, LP
+IBM Corporation
 Igalia, S.L.
 Joyent, Inc.
 
@@ -15,11 +16,13 @@ Alexander Botero-Lowry <alexbl@FreeBSD.org>
 Alexander Karpinsky <homm86@gmail.com>
 Alexandre Vassalotti <avassalotti@gmail.com>
 Andreas Anyuru <andreas.anyuru@gmail.com>
+Andrew Low <andrew_low@ca.ibm.com>
 Bert Belder <bertbelder@gmail.com>
 Burcu Dogan <burcujdogan@gmail.com>
 Craig Schlenter <craig.schlenter@gmail.com>
 Daniel Andersson <kodandersson@gmail.com>
 Daniel James <dnljms@gmail.com>
+David Eelsohn <dje.gcc@gmail.com>
 Derek J Conrod <dconrod@codeaurora.org>
 Dineel D Sule <dsule@codeaurora.org>
 Erich Ocean <erich.ocean@me.com>
@@ -37,6 +40,7 @@ Kun Zhang <zhangk@codeaurora.org>
 Martyn Capewell <martyn.capewell@arm.com>
 Mathias Bynens <mathias@qiwi.be>
 Matt Hanselman <mjhanselman@gmail.com>
+Matthew Brandyberry <mbrandy@us.ibm.com>
 Maxim Mossienko <maxim.mossienko@gmail.com>
 Michael Lutz <michi@icosahedron.de>
 Michael Smith <mike@w3.org>
diff --git a/Makefile b/Makefile
index b65ea4c..95631dd 100644
--- a/Makefile
+++ b/Makefile
@@ -73,6 +73,10 @@ endif
 ifeq ($(extrachecks), off)
   GYPFLAGS += -Dv8_enable_extra_checks=0
 endif
+# extrachecks=off
+ifeq ($(extrappcchecks), on)
+  GYPFLAGS += -Dv8_enable_extra_ppcchecks=1
+endif
 # gdbjit=on
 ifeq ($(gdbjit), on)
   GYPFLAGS += -Dv8_enable_gdbjit=1
@@ -115,6 +119,10 @@ endif
 ifeq ($(hardfp), on)
   GYPFLAGS += -Dv8_use_arm_eabi_hardfloat=true
 endif
+# nativesim=true
+ifeq ($(nativesim), true)
+  GYPFLAGS += -Dv8_native_sim=true
+endif
 
 # ----------------- available targets: --------------------
 # - "dependencies": pulls in external dependencies (currently: GYP)
@@ -133,8 +141,8 @@ endif
 
 # Architectures and modes to be compiled. Consider these to be internal
 # variables, don't override them (use the targets instead).
-ARCHES = ia32 x64 arm mipsel
-DEFAULT_ARCHES = ia32 x64 arm
+ARCHES = ia32 x64 arm ppc mipsel ppc64
+DEFAULT_ARCHES = ia32 x64 arm ppc ppc64
 MODES = release debug
 ANDROID_ARCHES = android_ia32 android_arm
 
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5cdb418
--- /dev/null
+++ b/README.md
@@ -0,0 +1,10 @@
+v8ppc
+=====
+
+Port of Google V8 javascript engine to PowerPC - PowerLinux and AIX.
+
+This branch of the code (libv8-3.14) is intended to match the 3.14.5.8 
+level of V8 that is used by the libv8 library built as part of Ubuntu
+
+http://packages.ubuntu.com/source/trusty/libv8-3.14
+
diff --git a/aix_gyp.patch b/aix_gyp.patch
new file mode 100644
index 0000000..810132d
--- /dev/null
+++ b/aix_gyp.patch
@@ -0,0 +1,62 @@
+--- build/gyp/pylib/gyp/common.py
++++ build/gyp/pylib/gyp/common.py
+@@ -378,6 +378,8 @@
+      return 'solaris'
+    if sys.platform.startswith('freebsd'):
+      return 'freebsd'
++   if sys.platform.startswith('aix'):
++     return 'aix'
+  
+    return 'linux'
+  
+--- build/gyp/pylib/gyp/generator/make.py
++++ build/gyp/pylib/gyp/generator/make.py
+@@ -200,6 +200,21 @@
+  """
+  
+  
++ LINK_COMMANDS_AIX = """\
++ quiet_cmd_alink = AR($(TOOLSET)) $@
++ cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
++ 
++ quiet_cmd_link = LINK($(TOOLSET)) $@
++ cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS)
++ 
++ quiet_cmd_solink = SOLINK($(TOOLSET)) $@
++ cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
++ 
++ quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
++ cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
++ """
++ 
++ 
+  # Header of toplevel Makefile.
+  # This should go into the build tree, but it's easier to keep it here for now.
+  SHARED_HEADER = ("""\
+
+--- build/gyp/pylib/gyp/generator/make.py
++++ build/gyp/pylib/gyp/generator/make.py
+@@ -1933,6 +1948,10 @@
+                                                           cc_command=cc_host):
+      arflags_host = 'crsT'
+  
++   if flavor == 'aix':
++     arflags_target = '-Xany ' + arflags_target
++     arflags_host = '-Xany ' + arflags_host
++ 
+    return { 'ARFLAGS.target': arflags_target,
+             'ARFLAGS.host': arflags_host }
+  
+--- build/gyp/pylib/gyp/generator/make.py
++++ build/gyp/pylib/gyp/generator/make.py
+@@ -2026,6 +2045,10 @@
+    elif flavor == 'freebsd':
+      header_params.update({
+          'flock': 'lockf',
++     })
++   elif flavor == 'aix':
++     header_params.update({
++         'link_commands': LINK_COMMANDS_AIX,
+      })
+  
+    header_params.update(RunSystemTests(flavor))
diff --git a/build/common.gypi b/build/common.gypi
index 78888b8..4f046c0 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -70,9 +70,13 @@
 
     'v8_enable_disassembler%': 0,
 
+    'v8_native_sim%': 'false',
+
     # Enable extra checks in API functions and other strategic places.
     'v8_enable_extra_checks%': 1,
 
+    'v8_enable_extra_ppcchecks%': 0,
+
     'v8_enable_gdbjit%': 0,
 
     'v8_object_print%': 0,
@@ -117,6 +121,9 @@
       ['v8_enable_extra_checks==1', {
         'defines': ['ENABLE_EXTRA_CHECKS',],
       }],
+      ['v8_enable_extra_ppcchecks==1', {
+        'defines': ['ENABLE_EXTRA_PPCCHECKS',],
+      }],
       ['v8_enable_gdbjit==1', {
         'defines': ['ENABLE_GDB_JIT_INTERFACE',],
       }],
@@ -129,6 +136,12 @@
       ['v8_interpreted_regexp==1', {
         'defines': ['V8_INTERPRETED_REGEXP',],
       }],
+      ['v8_native_sim=="true"', {
+        'defines': [
+          'NATIVE_SIMULATION',
+          'USE_SIMULATOR',
+        ],
+      }],
       ['v8_target_arch=="arm"', {
         'defines': [
           'V8_TARGET_ARCH_ARM',
@@ -171,6 +184,17 @@
           }],
         ],
       }],  # v8_target_arch=="arm"
+      ['v8_target_arch=="ppc"', {
+        'defines': [
+          'V8_TARGET_ARCH_PPC',
+        ],
+      }],  # v8_target_arch=="ppc"
+      ['v8_target_arch=="ppc64"', {
+        'defines': [
+          'V8_TARGET_ARCH_PPC',
+          'V8_TARGET_ARCH_PPC64',
+        ],
+      }],  # v8_target_arch=="ppc64"
       ['v8_target_arch=="ia32"', {
         'defines': [
           'V8_TARGET_ARCH_IA32',
@@ -277,7 +301,7 @@
         },
       }],
       ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
-         or OS=="netbsd"', {
+         or OS=="netbsd" or OS=="aix"', {
         'conditions': [
           [ 'v8_no_strict_aliasing==1', {
             'cflags': [ '-fno-strict-aliasing' ],
@@ -290,7 +314,7 @@
       ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
          or OS=="netbsd" or OS=="mac" or OS=="android") and \
         (v8_target_arch=="arm" or v8_target_arch=="ia32" or \
-         v8_target_arch=="mipsel")', {
+         v8_target_arch=="mipsel" or v8_target_arch=="ppc")', {
         # Check whether the host compiler and target compiler support the
         # '-m32' option and set it if so.
         'target_conditions': [
@@ -327,6 +351,20 @@
       ['OS=="netbsd"', {
         'cflags': [ '-I/usr/pkg/include' ],
       }],
+      ['OS=="aix"', {
+        # AIX is missing /usr/include/endian.h
+        'defines': [
+          '__LITTLE_ENDIAN=1234',
+          '__BIG_ENDIAN=4321',
+          '__BYTE_ORDER=__BIG_ENDIAN',
+          '__FLOAT_WORD_ORDER=__BIG_ENDIAN'],
+        'conditions': [
+          [ 'v8_target_arch=="ppc64"', {
+            'cflags': [ '-maix64' ],
+            'ldflags': [ '-maix64' ],
+          }],
+        ],
+      }],
     ],  # conditions
     'configurations': {
       'Debug': {
@@ -354,10 +392,14 @@
           },
         },
         'conditions': [
-          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', {
+          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \
+            or OS=="aix"', {
             'cflags': [ '-Wall', '<(werror)', '-W', '-Wno-unused-parameter',
                         '-Wnon-virtual-dtor', '-Woverloaded-virtual' ],
           }],
+          ['OS=="aix"', {
+            'ldflags': [ '-Wl,-bbigtoc' ],
+          }],
           ['OS=="android"', {
             'variables': {
               'android_full_debug%': 1,
@@ -377,7 +419,7 @@
       'Release': {
         'conditions': [
           ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \
-            or OS=="android"', {
+            or OS=="android" or OS=="aix"', {
             'cflags!': [
               '-O2',
               '-Os',
diff --git a/build/standalone.gypi b/build/standalone.gypi
index 7145a16..8389ef4 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -31,7 +31,6 @@
   'variables': {
     'library%': 'static_library',
     'component%': 'static_library',
-    'visibility%': 'hidden',
     'msvs_multi_core_compile%': '1',
     'mac_deployment_target%': '10.5',
     'variables': {
@@ -39,7 +38,7 @@
         'variables': {
           'conditions': [
             ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or \
-               OS=="netbsd" or OS=="mac"', {
+               OS=="netbsd" or OS=="mac" or OS=="aix"', {
               # This handles the Unix platforms we generally deal with.
               # Anything else gets passed through, which probably won't work
               # very well; such hosts should pass an explicit target_arch
@@ -49,7 +48,7 @@
                   s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/;s/mips.*/mipsel/")',
             }, {
               # OS!="linux" and OS!="freebsd" and OS!="openbsd" and
-              # OS!="netbsd" and OS!="mac"
+              # OS!="netbsd" and OS!="mac" and OS!="aix"
               'host_arch%': 'ia32',
             }],
           ],
@@ -74,6 +73,12 @@
       }, {
         'want_separate_host_toolset': 0,
       }],
+      #
+      ['OS=="aix"', {
+        'visibility%': '',
+      }, {
+        'visibility%': 'hidden',
+      }],
     ],
     # Default ARM variable settings.
     'armv7%': 1,
@@ -85,12 +90,17 @@
     'configurations': {
       'Debug': {
         'cflags': [ '-g', '-O0' ],
+        'conditions': [
+          [ 'OS=="aix"', {
+            'cflags': [ '-gxcoff' ],
+          }],
+        ],
       },
     },
   },
   'conditions': [
     ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
-       or OS=="netbsd"', {
+       or OS=="netbsd" or OS=="aix"', {
       'target_defaults': {
         'cflags': [ '-Wall', '<(werror)', '-W', '-Wno-unused-parameter',
                     '-Wnon-virtual-dtor', '-pthread', '-fno-rtti',
@@ -100,6 +110,9 @@
           [ 'OS=="linux"', {
             'cflags': [ '-ansi' ],
           }],
+          [ 'host_arch=="ppc64"', {
+            'cflags': [ '-mminimal-toc' ],
+          }],
           [ 'visibility=="hidden"', {
             'cflags': [ '-fvisibility=hidden' ],
           }],
diff --git a/src/assembler.cc b/src/assembler.cc
index d81d4ae..10ef522 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -61,6 +61,8 @@
 #include "x64/assembler-x64-inl.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/assembler-arm-inl.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/assembler-ppc-inl.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/assembler-mips-inl.h"
 #else
@@ -75,6 +77,8 @@
 #include "x64/regexp-macro-assembler-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/regexp-macro-assembler-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/regexp-macro-assembler-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/regexp-macro-assembler-mips.h"
 #else  // Unknown architecture.
@@ -1064,6 +1068,8 @@ ExternalReference ExternalReference::re_check_stack_guard_state(
   function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
 #elif V8_TARGET_ARCH_ARM
   function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
+#elif V8_TARGET_ARCH_PPC
+  function = FUNCTION_ADDR(RegExpMacroAssemblerPPC::CheckStackGuardState);
 #elif V8_TARGET_ARCH_MIPS
   function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
 #else
@@ -1224,6 +1230,21 @@ double power_double_double(double x, double y) {
     int y_int = static_cast<int>(y);
     if (y == y_int) return ldexp(1.0, y_int);
   }
+#elif defined(_AIX)
+  // AIX has a custom implementation for pow.  This handles certain
+  // special cases that are different.
+  if ((x == 0.0 || isinf(x)) && y != 0.0 && isfinite(y)) {
+    double f;
+    double result = ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
+    /* retain sign if odd integer exponent */
+    return ((modf(y, &f) == 0.0) && (static_cast<int64_t>(y) & 1)) ?
+      copysign(result, x) : result;
+  }
+
+  if (x == 2.0) {
+    int y_int = static_cast<int>(y);
+    if (y == y_int) return ldexp(1.0, y_int);
+  }
 #endif
 
   // The checks for special cases can be dropped in ia32 because it has already
diff --git a/src/assembler.h b/src/assembler.h
index a0e55cc..f72c8d3 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -829,31 +829,33 @@ class PreservePositionScope BASE_EMBEDDED {
 // -----------------------------------------------------------------------------
 // Utility functions
 
-inline bool is_intn(int x, int n)  {
-  return -(1 << (n-1)) <= x && x < (1 << (n-1));
+inline bool is_intn(intptr_t x, int n)  {
+  return -(1L << (n-1)) <= x && x < (1L << (n-1));
 }
 
-inline bool is_int8(int x)  { return is_intn(x, 8); }
-inline bool is_int16(int x)  { return is_intn(x, 16); }
-inline bool is_int18(int x)  { return is_intn(x, 18); }
-inline bool is_int24(int x)  { return is_intn(x, 24); }
+inline bool is_int8(intptr_t x)  { return is_intn(x, 8); }
+inline bool is_int16(intptr_t x)  { return is_intn(x, 16); }
+inline bool is_int18(intptr_t x)  { return is_intn(x, 18); }
+inline bool is_int24(intptr_t x)  { return is_intn(x, 24); }
+inline bool is_int26(intptr_t x)  { return is_intn(x, 26); }
 
-inline bool is_uintn(int x, int n) {
-  return (x & -(1 << n)) == 0;
+
+inline bool is_uintn(intptr_t x, int n) {
+  return (x & -(1L << n)) == 0;
 }
 
-inline bool is_uint2(int x)  { return is_uintn(x, 2); }
-inline bool is_uint3(int x)  { return is_uintn(x, 3); }
-inline bool is_uint4(int x)  { return is_uintn(x, 4); }
-inline bool is_uint5(int x)  { return is_uintn(x, 5); }
-inline bool is_uint6(int x)  { return is_uintn(x, 6); }
-inline bool is_uint8(int x)  { return is_uintn(x, 8); }
-inline bool is_uint10(int x)  { return is_uintn(x, 10); }
-inline bool is_uint12(int x)  { return is_uintn(x, 12); }
-inline bool is_uint16(int x)  { return is_uintn(x, 16); }
-inline bool is_uint24(int x)  { return is_uintn(x, 24); }
-inline bool is_uint26(int x)  { return is_uintn(x, 26); }
-inline bool is_uint28(int x)  { return is_uintn(x, 28); }
+inline bool is_uint2(intptr_t x)  { return is_uintn(x, 2); }
+inline bool is_uint3(intptr_t x)  { return is_uintn(x, 3); }
+inline bool is_uint4(intptr_t x)  { return is_uintn(x, 4); }
+inline bool is_uint5(intptr_t x)  { return is_uintn(x, 5); }
+inline bool is_uint6(intptr_t x)  { return is_uintn(x, 6); }
+inline bool is_uint8(intptr_t x)  { return is_uintn(x, 8); }
+inline bool is_uint10(intptr_t x)  { return is_uintn(x, 10); }
+inline bool is_uint12(intptr_t x)  { return is_uintn(x, 12); }
+inline bool is_uint16(intptr_t x)  { return is_uintn(x, 16); }
+inline bool is_uint24(intptr_t x)  { return is_uintn(x, 24); }
+inline bool is_uint26(intptr_t x)  { return is_uintn(x, 26); }
+inline bool is_uint28(intptr_t x)  { return is_uintn(x, 28); }
 
 inline int NumberOfBitsSet(uint32_t x) {
   unsigned int num_bits_set;
diff --git a/src/atomicops.h b/src/atomicops.h
index 1f0c44a..8c92f07 100644
--- a/src/atomicops.h
+++ b/src/atomicops.h
@@ -69,7 +69,8 @@ typedef intptr_t Atomic64;
 
 // Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
 // Atomic64 routines below, depending on your architecture.
-#if defined(__OpenBSD__) && defined(__i386__)
+#if !defined(V8_HOST_ARCH_64_BIT) && \
+  ((defined(__OpenBSD__) && defined(__i386__)) || defined(_AIX))
 typedef Atomic32 AtomicWord;
 #else
 typedef intptr_t AtomicWord;
@@ -162,6 +163,8 @@ Atomic64 Release_Load(volatile const Atomic64* ptr);
 #include "atomicops_internals_x86_gcc.h"
 #elif defined(__GNUC__) && defined(V8_HOST_ARCH_ARM)
 #include "atomicops_internals_arm_gcc.h"
+#elif defined(__GNUC__) && defined(V8_HOST_ARCH_PPC)
+#include "atomicops_internals_ppc_gcc.h"
 #elif defined(__GNUC__) && defined(V8_HOST_ARCH_MIPS)
 #include "atomicops_internals_mips_gcc.h"
 #else
diff --git a/src/atomicops_internals_ppc_gcc.h b/src/atomicops_internals_ppc_gcc.h
new file mode 100644
index 0000000..b4543f4
--- /dev/null
+++ b/src/atomicops_internals_ppc_gcc.h
@@ -0,0 +1,167 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+//
+
+#ifndef V8_ATOMICOPS_INTERNALS_PPC_H_
+#define V8_ATOMICOPS_INTERNALS_PPC_H_
+
+namespace v8 {
+namespace internal {
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  return(__sync_val_compare_and_swap( ptr, old_value, new_value));
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  do {
+    old_value = *ptr;
+  } while (__sync_bool_compare_and_swap(ptr, old_value, new_value));
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  for (;;) {
+    Atomic32 old_value = *ptr;
+    Atomic32 new_value = old_value + increment;
+    if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
+      return new_value;
+      // The exchange took place as expected.
+    }
+    // Otherwise, *ptr changed mid-loop and we need to retry.
+  }
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void MemoryBarrier() {
+  __asm__ __volatile__("sync" : : : "memory");
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#ifdef V8_TARGET_ARCH_PPC64
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  return(__sync_val_compare_and_swap( ptr, old_value, new_value));
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+#endif
+
+} }  // namespace v8::internal
+
+#endif  // V8_ATOMICOPS_INTERNALS_PPC_GCC_H_
diff --git a/src/builtins.cc b/src/builtins.cc
index df70cd4..de0bb41 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -1617,10 +1617,15 @@ void Builtins::SetUp(bool create_heap_objects) {
 
   const BuiltinDesc* functions = builtin_function_table.functions();
 
+#if V8_TARGET_ARCH_PPC64
+  const int kBufferSize = 9 * KB;
+#else
+  const int kBufferSize = 8 * KB;
+#endif
   // For now we generate builtin adaptor code into a stack-allocated
   // buffer, before copying it into individual code objects. Be careful
   // with alignment, some platforms don't like unaligned code.
-  union { int force_alignment; byte buffer[8*KB]; } u;
+  union { int force_alignment; byte buffer[kBufferSize]; } u;
 
   // Traverse the list of builtins and generate an adaptor in a
   // separate code object for each one.
diff --git a/src/checks.h b/src/checks.h
index d0a0c2b..15abc89 100644
--- a/src/checks.h
+++ b/src/checks.h
@@ -292,4 +292,18 @@ extern bool FLAG_enable_slow_asserts;
 #define EXTRA_CHECK(condition) ((void) 0)
 #endif
 
+// PENGUIN: Extra checks for PPC PORT
+//   - PPCPORT_UNIMPLEMENTED: for unimplemented features
+//   - PPCPORT_CHECK: for development phase
+//   - PPCPORT_UNSAFE_IMPLEMENTATION: unsafe implementation
+#ifdef ENABLE_EXTRA_PPCCHECKS
+#define PPCPORT_CHECK(condition) CHECK(condition)
+#define PPCPORT_UNIMPLEMENTED() UNIMPLEMENTED()
+#define PPCPORT_UNSAFE_IMPLEMENTATION() ((void)0)
+#else
+#define PPCPORT_CHECK(condition) ((void) 0)
+#define PPCPORT_UNIMPLEMENTED() ((void) 0)
+#define PPCPORT_UNSAFE_IMPLEMENTATION() ((void)0)
+#endif
+
 #endif  // V8_CHECKS_H_
diff --git a/src/code-stubs.h b/src/code-stubs.h
index a843841..7ac3cae 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -88,6 +88,18 @@ namespace internal {
 #define CODE_STUB_LIST_ARM(V)
 #endif
 
+// List of code stubs only used on PPC platforms.
+#ifdef V8_TARGET_ARCH_PPC
+#define CODE_STUB_LIST_PPC(V)  \
+  V(GetProperty)               \
+  V(SetProperty)               \
+  V(InvokeBuiltin)             \
+  V(RegExpCEntry)              \
+  V(DirectCEntry)
+#else
+#define CODE_STUB_LIST_PPC(V)
+#endif
+
 // List of code stubs only used on MIPS platforms.
 #ifdef V8_TARGET_ARCH_MIPS
 #define CODE_STUB_LIST_MIPS(V)  \
@@ -101,6 +113,7 @@ namespace internal {
 #define CODE_STUB_LIST(V)            \
   CODE_STUB_LIST_ALL_PLATFORMS(V)    \
   CODE_STUB_LIST_ARM(V)              \
+  CODE_STUB_LIST_PPC(V)              \
   CODE_STUB_LIST_MIPS(V)
 
 // Mode to overwrite BinaryExpression values.
@@ -254,6 +267,8 @@ class RuntimeCallHelper {
 #include "x64/code-stubs-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/code-stubs-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/code-stubs-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/code-stubs-mips.h"
 #else
diff --git a/src/codegen.cc b/src/codegen.cc
index 0163580..52cf992 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -200,7 +200,7 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
 int CEntryStub::MinorKey() {
   int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0;
   ASSERT(result_size_ == 1 || result_size_ == 2);
-#ifdef _WIN64
+#if defined(_WIN64) || defined(V8_TARGET_ARCH_PPC64)
   return result | ((result_size_ == 1) ? 0 : 2);
 #else
   return result;
diff --git a/src/codegen.h b/src/codegen.h
index 08a777f..6eef38b 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -75,6 +75,8 @@ enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
 #include "x64/codegen-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/codegen-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/codegen-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/codegen-mips.h"
 #else
diff --git a/src/conversions-inl.h b/src/conversions-inl.h
index e272fe6..2872ee9 100644
--- a/src/conversions-inl.h
+++ b/src/conversions-inl.h
@@ -75,7 +75,11 @@ inline unsigned int FastD2UI(double x) {
   if (x < k2Pow52) {
     x += k2Pow52;
     uint32_t result;
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
     Address mantissa_ptr = reinterpret_cast<Address>(&x);
+#else
+    Address mantissa_ptr = reinterpret_cast<Address>(&x) + kIntSize;
+#endif
     // Copy least significant 32 bits of mantissa.
     memcpy(&result, mantissa_ptr, sizeof(result));
     return negative ? ~result + 1 : result;
diff --git a/src/d8.gyp b/src/d8.gyp
index a8361e6..4fe8671 100644
--- a/src/d8.gyp
+++ b/src/d8.gyp
@@ -62,7 +62,8 @@
               'sources': [ 'd8-readline.cc' ],
             }],
             ['(OS=="linux" or OS=="mac" or OS=="freebsd" or OS=="netbsd" \
-               or OS=="openbsd" or OS=="solaris" or OS=="android")', {
+               or OS=="openbsd" or OS=="solaris" or OS=="android" \
+               or OS=="aix")', {
               'sources': [ 'd8-posix.cc', ]
             }],
             [ 'OS=="win"', {
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index f67f986..2a7227a 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -697,7 +697,11 @@ class SlotRef BASE_EMBEDDED {
         return Handle<Object>(Memory::Object_at(addr_));
 
       case INT32: {
+#if defined(V8_TARGET_ARCH_PPC64) && __BYTE_ORDER == __BIG_ENDIAN
+        int value = Memory::int32_at(addr_ + kIntSize);
+#else
         int value = Memory::int32_at(addr_);
+#endif
         if (Smi::IsValid(value)) {
           return Handle<Object>(Smi::FromInt(value));
         } else {
@@ -706,7 +710,11 @@ class SlotRef BASE_EMBEDDED {
       }
 
       case UINT32: {
+#if defined(V8_TARGET_ARCH_PPC64) && __BYTE_ORDER == __BIG_ENDIAN
+        uint32_t value = Memory::uint32_at(addr_ + kIntSize);
+#else
         uint32_t value = Memory::uint32_at(addr_);
+#endif
         if (value <= static_cast<uint32_t>(Smi::kMaxValue)) {
           return Handle<Object>(Smi::FromInt(static_cast<int>(value)));
         } else {
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 9f8b9a8..9cd94f5 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -158,7 +158,11 @@ static int DecodeIt(FILE* f,
                      "%08" V8PRIxPTR "      jump table entry %4" V8PRIdPTR,
                      ptr,
                      ptr - begin);
+#if V8_TARGET_ARCH_PPC64
+        pc += 8;
+#else
         pc += 4;
+#endif
       } else {
         decode_buffer[0] = '\0';
         pc += d.InstructionDecode(decode_buffer, pc);
diff --git a/src/execution.h b/src/execution.h
index 9f5d9ff..5bdc135 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -258,7 +258,7 @@ class StackGuard {
   void EnableInterrupts();
   void DisableInterrupts();
 
-#ifdef V8_TARGET_ARCH_X64
+#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_PPC64)
   static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
   static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
 #else
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 4c7c090..764915e 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -442,6 +442,7 @@ DEFINE_bool(trace_parse, false, "trace parsing and preparsing")
 
 // simulator-arm.cc and simulator-mips.cc
 DEFINE_bool(trace_sim, false, "Trace simulator execution")
+DEFINE_bool(trace_sim_stubs, false, "Trace simulator execution w/ stub markers")
 DEFINE_bool(check_icache, false,
             "Check icache flushes in ARM and MIPS simulator")
 DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions")
@@ -449,6 +450,8 @@ DEFINE_int(sim_stack_alignment, 8,
            "Stack alingment in bytes in simulator (4 or 8, 8 is default)")
 
 // isolate.cc
+DEFINE_bool(abort_on_uncaught_exception, false,
+            "abort program (dump core) when an uncaught exception is thrown")
 DEFINE_bool(trace_exception, false,
             "print stack trace when throwing exceptions")
 DEFINE_bool(preallocate_message_memory, false,
diff --git a/src/frames-inl.h b/src/frames-inl.h
index 27a526c..f6cc9e7 100644
--- a/src/frames-inl.h
+++ b/src/frames-inl.h
@@ -38,6 +38,8 @@
 #include "x64/frames-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/frames-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/frames-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/frames-mips.h"
 #else
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 89b51f9..eff4b29 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -125,6 +125,8 @@ class FullCodeGenerator: public AstVisitor {
   static const int kBackEdgeDistanceUnit = 162;
 #elif V8_TARGET_ARCH_ARM
   static const int kBackEdgeDistanceUnit = 142;
+#elif V8_TARGET_ARCH_PPC
+  static const int kBackEdgeDistanceUnit = 142;
 #elif V8_TARGET_ARCH_MIPS
   static const int kBackEdgeDistanceUnit = 142;
 #else
@@ -333,12 +335,18 @@ class FullCodeGenerator: public AstVisitor {
              Label* if_true,
              Label* if_false,
              Label* fall_through);
-#else  // All non-mips arch.
+#elif defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64)
+  void Split(Condition cc,
+             Label* if_true,
+             Label* if_false,
+             Label* fall_through,
+             CRegister cr = cr7);
+#else  // All other arch.
   void Split(Condition cc,
              Label* if_true,
              Label* if_false,
              Label* fall_through);
-#endif  // V8_TARGET_ARCH_MIPS
+#endif
 
   // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into
   // a register.  Emits a context chain walk if if necessary (so does
diff --git a/src/globals.h b/src/globals.h
index babffbf..8529daf 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -56,6 +56,11 @@
 #define V8_INFINITY HUGE_VAL
 #endif
 
+#ifdef _AIX
+#undef V8_INFINITY
+#define V8_INFINITY (__builtin_inff())
+#endif
+
 
 #include "../include/v8stdint.h"
 
@@ -86,6 +91,13 @@ namespace internal {
 #elif defined(__MIPSEL__)
 #define V8_HOST_ARCH_MIPS 1
 #define V8_HOST_ARCH_32_BIT 1
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define V8_HOST_ARCH_PPC 1
+#if defined(__PPC64__) || defined(_ARCH_PPC64)
+#define V8_HOST_ARCH_64_BIT 1
+#else
+#define V8_HOST_ARCH_32_BIT 1
+#endif
 #else
 #error Host architecture was not detected as supported by v8
 #endif
@@ -94,7 +106,8 @@ namespace internal {
 // in the same way as the host architecture, that is, target the native
 // environment as presented by the compiler.
 #if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_IA32) && \
-    !defined(V8_TARGET_ARCH_ARM) && !defined(V8_TARGET_ARCH_MIPS)
+    !defined(V8_TARGET_ARCH_ARM) && !defined(V8_TARGET_ARCH_MIPS) && \
+    !defined(V8_TARGET_ARCH_PPC)
 #if defined(_M_X64) || defined(__x86_64__)
 #define V8_TARGET_ARCH_X64 1
 #elif defined(_M_IX86) || defined(__i386__)
@@ -116,8 +129,9 @@ namespace internal {
 #error Target architecture x64 is only supported on x64 host
 #endif
 #if (defined(V8_TARGET_ARCH_ARM) && \
-    !(defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_ARM)))
-#error Target architecture arm is only supported on arm and ia32 host
+    !(defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_ARM) || \
+      defined(V8_HOST_ARCH_PPC)))
+#error Target architecture arm is only supported on arm, ppc and ia32 host
 #endif
 #if (defined(V8_TARGET_ARCH_MIPS) && \
     !(defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_MIPS)))
@@ -131,6 +145,9 @@ namespace internal {
 #if (defined(V8_TARGET_ARCH_ARM) && !defined(V8_HOST_ARCH_ARM))
 #define USE_SIMULATOR 1
 #endif
+#if (defined(V8_TARGET_ARCH_PPC) && !defined(V8_HOST_ARCH_PPC))
+#define USE_SIMULATOR 1
+#endif
 #if (defined(V8_TARGET_ARCH_MIPS) && !defined(V8_HOST_ARCH_MIPS))
 #define USE_SIMULATOR 1
 #endif
@@ -190,6 +207,16 @@ typedef byte* Address;
 #define V8PRIdPTR V8_PTR_PREFIX "d"
 #define V8PRIuPTR V8_PTR_PREFIX "u"
 
+// Fix for AIX define intptr_t as "long int":
+#ifdef _AIX
+#undef V8_PTR_PREFIX
+#define V8_PTR_PREFIX "l"
+#undef V8PRIdPTR
+#define V8PRIdPTR "ld"
+#undef V8PRIxPTR
+#define V8PRIxPTR "lx"
+#endif
+
 // Fix for Mac OS X defining uintptr_t as "unsigned long":
 #if defined(__APPLE__) && defined(__MACH__)
 #undef V8PRIxPTR
diff --git a/src/heap.cc b/src/heap.cc
index e3fcb93..e5ca930 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -50,6 +50,10 @@
 #include "v8threads.h"
 #include "v8utils.h"
 #include "vm-state-inl.h"
+#if V8_TARGET_ARCH_PPC && !V8_INTERPRETED_REGEXP
+#include "regexp-macro-assembler.h"
+#include "ppc/regexp-macro-assembler-ppc.h"
+#endif
 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
 #include "regexp-macro-assembler.h"
 #include "arm/regexp-macro-assembler-arm.h"
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 79550f3..408c1e6 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -36,6 +36,8 @@
 #include "x64/lithium-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/lithium-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/lithium-mips.h"
 #else
@@ -966,8 +968,8 @@ HValue* HUnaryMathOperation::Canonicalize() {
     // introduced.
     if (value()->representation().IsInteger32()) return value();
 
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) || \
-        defined(V8_TARGET_ARCH_X64)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) ||      \
+  defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_PPC)
     if (value()->IsDiv() && (value()->UseCount() == 1)) {
       // TODO(2038): Implement this optimization for non ARM architectures.
       HDiv* hdiv = HDiv::cast(value());
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 8393e51..4000922 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -43,6 +43,8 @@
 #include "x64/lithium-codegen-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-codegen-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/lithium-codegen-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/lithium-codegen-mips.h"
 #else
diff --git a/src/isolate.cc b/src/isolate.cc
index 75e15a4..495d928 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -116,6 +116,8 @@ void ThreadLocalTop::Initialize() {
 #ifdef USE_SIMULATOR
 #ifdef V8_TARGET_ARCH_ARM
   simulator_ = Simulator::current(isolate_);
+#elif V8_TARGET_ARCH_PPC
+  simulator_ = Simulator::current(isolate_);
 #elif V8_TARGET_ARCH_MIPS
   simulator_ = Simulator::current(isolate_);
 #endif
@@ -1080,6 +1082,7 @@ bool Isolate::IsErrorObject(Handle<Object> obj) {
   return false;
 }
 
+static int fatal_exception_depth = 0;
 
 void Isolate::DoThrow(Object* exception, MessageLocation* location) {
   ASSERT(!has_pending_exception());
@@ -1150,6 +1153,20 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
         thread_local_top()->pending_message_start_pos_ = location->start_pos();
         thread_local_top()->pending_message_end_pos_ = location->end_pos();
       }
+
+      // If the abort-on-uncaught-exception flag is specified, abort on any
+      // exception not caught by JavaScript, even when an external handler is
+      // present.  This flag is intended for use by JavaScript developers, so
+      // print a user-friendly stack trace (not an internal one).
+      if (fatal_exception_depth == 0 &&
+          FLAG_abort_on_uncaught_exception &&
+          (report_exception || can_be_caught_externally)) {
+        fatal_exception_depth++;
+        fprintf(stderr, "%s\n\nFROM\n",
+          *MessageHandler::GetLocalizedMessage(message_obj));
+        PrintCurrentStackTrace(stderr);
+        OS::Abort();
+      }
     } else if (location != NULL && !location->script().is_null()) {
       // We are bootstrapping and caught an error where the location is set
       // and we have a script for the location.
@@ -1398,6 +1415,8 @@ char* Isolate::RestoreThread(char* from) {
 #ifdef USE_SIMULATOR
 #ifdef V8_TARGET_ARCH_ARM
   thread_local_top()->simulator_ = Simulator::current(this);
+#elif V8_TARGET_ARCH_PPC
+  thread_local_top()->simulator_ = Simulator::current(this);
 #elif V8_TARGET_ARCH_MIPS
   thread_local_top()->simulator_ = Simulator::current(this);
 #endif
@@ -1534,6 +1553,7 @@ Isolate::Isolate()
   thread_manager_->isolate_ = this;
 
 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+    defined(V8_TARGET_ARCH_PPC) && !defined(__PPC__) || \
     defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
   simulator_initialized_ = false;
   simulator_i_cache_ = NULL;
@@ -1851,7 +1871,8 @@ bool Isolate::Init(Deserializer* des) {
 
   // Initialize other runtime facilities
 #if defined(USE_SIMULATOR)
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) \
+  || defined(V8_TARGET_ARCH_PPC)
   Simulator::Initialize(this);
 #endif
 #endif
diff --git a/src/isolate.h b/src/isolate.h
index b90191d..773fcaf 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -94,7 +94,9 @@ class Debugger;
 class DebuggerAgent;
 #endif
 
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+#if defined(NATIVE_SIMULATION) || \
+    !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__PPC__) && defined(V8_TARGET_ARCH_PPC) || \
     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
 class Redirection;
 class Simulator;
@@ -256,7 +258,8 @@ class ThreadLocalTop BASE_EMBEDDED {
   Address handler_;   // try-blocks are chained through the stack
 
 #ifdef USE_SIMULATOR
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_PPC) || \
+    defined(V8_TARGET_ARCH_MIPS)
   Simulator* simulator_;
 #endif
 #endif  // USE_SIMULATOR
@@ -374,7 +377,9 @@ class Isolate {
           thread_id_(thread_id),
           stack_limit_(0),
           thread_state_(NULL),
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+#if defined(NATIVE_SIMULATION) || \
+    !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__PPC__) && defined(V8_TARGET_ARCH_PPC) || \
     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
           simulator_(NULL),
 #endif
@@ -387,7 +392,9 @@ class Isolate {
     ThreadState* thread_state() const { return thread_state_; }
     void set_thread_state(ThreadState* value) { thread_state_ = value; }
 
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+#if defined(NATIVE_SIMULATION) || \
+    !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__PPC__) && defined(V8_TARGET_ARCH_PPC) || \
     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
     Simulator* simulator() const { return simulator_; }
     void set_simulator(Simulator* simulator) {
@@ -405,7 +412,9 @@ class Isolate {
     uintptr_t stack_limit_;
     ThreadState* thread_state_;
 
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+#if defined(NATIVE_SIMULATION) || \
+    !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
+    !defined(__PPC__) && defined(V8_TARGET_ARCH_PPC) || \
     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
     Simulator* simulator_;
 #endif
@@ -969,7 +978,9 @@ class Isolate {
   int* code_kind_statistics() { return code_kind_statistics_; }
 #endif
 
-#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+#if defined(NATIVE_SIMULATION) || \
+    defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+    defined(V8_TARGET_ARCH_PPC) && !defined(__PPC__) || \
     defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
   bool simulator_initialized() { return simulator_initialized_; }
   void set_simulator_initialized(bool initialized) {
@@ -1249,7 +1260,9 @@ class Isolate {
   // Time stamp at initialization.
   double time_millis_at_init_;
 
-#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+#if defined(NATIVE_SIMULATION) || \
+    defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
+    defined(V8_TARGET_ARCH_PPC) && !defined(__PPC__) || \
     defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
   bool simulator_initialized_;
   HashMap* simulator_i_cache_;
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index e59170d..47caf4e 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -50,6 +50,8 @@
 #include "x64/regexp-macro-assembler-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/regexp-macro-assembler-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/regexp-macro-assembler-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/regexp-macro-assembler-mips.h"
 #else
@@ -6131,6 +6133,9 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
 #elif V8_TARGET_ARCH_ARM
   RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2,
                                           zone);
+#elif V8_TARGET_ARCH_PPC
+  RegExpMacroAssemblerPPC macro_assembler(mode, (data->capture_count + 1) * 2,
+                                          zone);
 #elif V8_TARGET_ARCH_MIPS
   RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2,
                                            zone);
diff --git a/src/jsregexp.h b/src/jsregexp.h
index 96825ce..f69a458 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -1352,6 +1352,13 @@ class BoyerMooreLookahead : public ZoneObject {
 // to match foo is generated only once (the traces have a common prefix).  The
 // code to store the capture is deferred and generated (twice) after the places
 // where baz has been matched.
+
+#ifdef _AIX
+#undef UNKNOWN
+#undef FALSE
+#undef TRUE
+#endif
+
 class Trace {
  public:
   // A value for a property that is either known to be true, know to be false,
diff --git a/src/lithium-allocator-inl.h b/src/lithium-allocator-inl.h
index 8f660ce..d47e66e 100644
--- a/src/lithium-allocator-inl.h
+++ b/src/lithium-allocator-inl.h
@@ -36,6 +36,8 @@
 #include "x64/lithium-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/lithium-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/lithium-mips.h"
 #else
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index 91a9811..07ebb75 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -37,6 +37,8 @@
 #include "x64/lithium-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/lithium-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/lithium-mips.h"
 #else
diff --git a/src/lithium.cc b/src/lithium.cc
index eb2198d..e7596fa 100644
--- a/src/lithium.cc
+++ b/src/lithium.cc
@@ -38,6 +38,9 @@
 #elif V8_TARGET_ARCH_ARM
 #include "arm/lithium-arm.h"
 #include "arm/lithium-codegen-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/lithium-ppc.h"
+#include "ppc/lithium-codegen-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/lithium-mips.h"
 #include "mips/lithium-codegen-mips.h"
diff --git a/src/log.cc b/src/log.cc
index b049ffe..2f42ae1 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1526,6 +1526,8 @@ void Logger::LogCodeInfo() {
   const char arch[] = "x64";
 #elif V8_TARGET_ARCH_ARM
   const char arch[] = "arm";
+#elif V8_TARGET_ARCH_PPC
+  const char arch[] = "ppc";
 #elif V8_TARGET_ARCH_MIPS
   const char arch[] = "mips";
 #else
diff --git a/src/macro-assembler.h b/src/macro-assembler.h
index 11e2217..f01a5ce 100644
--- a/src/macro-assembler.h
+++ b/src/macro-assembler.h
@@ -58,6 +58,13 @@ const int kInvalidProtoDepth = -1;
 #include "arm/assembler-arm-inl.h"
 #include "code.h"  // must be after assembler_*.h
 #include "arm/macro-assembler-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/constants-ppc.h"
+#include "assembler.h"
+#include "ppc/assembler-ppc.h"
+#include "ppc/assembler-ppc-inl.h"
+#include "code.h"  // must be after assembler_*.h
+#include "ppc/macro-assembler-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/constants-mips.h"
 #include "assembler.h"
diff --git a/src/objects-inl.h b/src/objects-inl.h
index ea5a93f..958d815 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1061,7 +1061,7 @@ bool Smi::IsValid(intptr_t value) {
   bool in_range = (value >= kMinValue) && (value <= kMaxValue);
 #endif
 
-#ifdef V8_TARGET_ARCH_X64
+#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_PPC64)
   // To be representable as a long smi, the value must be a 32-bit integer.
   bool result = (value == static_cast<int32_t>(value));
 #else
@@ -2409,10 +2409,7 @@ uint32_t String::hash_field() {
 
 
 void String::set_hash_field(uint32_t value) {
-  WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
-#if V8_HOST_ARCH_64_BIT
-  WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
-#endif
+  WRITE_INTPTR_FIELD(this, kHashFieldSlot, value);
 }
 
 
@@ -3976,25 +3973,33 @@ SMI_ACCESSORS(SharedFunctionInfo,
               kStressDeoptCounterOffset)
 #else
 
-#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
-  STATIC_ASSERT(holder::offset % kPointerSize == 0);              \
-  int holder::name() {                                            \
-    int value = READ_INT_FIELD(this, offset);                     \
-    ASSERT(kHeapObjectTag == 1);                                  \
-    ASSERT((value & kHeapObjectTag) == 0);                        \
-    return value >> 1;                                            \
-  }                                                               \
-  void holder::set_##name(int value) {                            \
-    ASSERT(kHeapObjectTag == 1);                                  \
-    ASSERT((value & 0xC0000000) == 0xC0000000 ||                  \
-           (value & 0xC0000000) == 0x000000000);                  \
-    WRITE_INT_FIELD(this,                                         \
-                    offset,                                       \
-                    (value << 1) & ~kHeapObjectTag);              \
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define PSEUDO_SMI_LO_ALIGN 0
+#define PSEUDO_SMI_HI_ALIGN kIntSize
+#else
+#define PSEUDO_SMI_LO_ALIGN kIntSize
+#define PSEUDO_SMI_HI_ALIGN 0
+#endif
+
+#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)                   \
+  STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_LO_ALIGN);  \
+  int holder::name() {                                                  \
+    int value = READ_INT_FIELD(this, offset);                           \
+    ASSERT(kHeapObjectTag == 1);                                        \
+    ASSERT((value & kHeapObjectTag) == 0);                              \
+    return value >> 1;                                                  \
+  }                                                                     \
+  void holder::set_##name(int value) {                                  \
+    ASSERT(kHeapObjectTag == 1);                                        \
+    ASSERT((value & 0xC0000000) == 0xC0000000 ||                        \
+           (value & 0xC0000000) == 0x000000000);                        \
+    WRITE_INT_FIELD(this,                                               \
+                    offset,                                             \
+                    (value << 1) & ~kHeapObjectTag);                    \
   }
 
-#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset)             \
-  STATIC_ASSERT(holder::offset % kPointerSize == kIntSize);       \
+#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset)                   \
+  STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_HI_ALIGN);  \
   INT_ACCESSORS(holder, name, offset)
 
 
diff --git a/src/objects.cc b/src/objects.cc
index 37f8361..6f93592 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -7007,8 +7007,8 @@ static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
   // then we have to check that the strings are aligned before
   // comparing them blockwise.
   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
-  uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
-  uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
+  uintptr_t pa_addr = reinterpret_cast<uintptr_t>(pa);
+  uintptr_t pb_addr = reinterpret_cast<uintptr_t>(pb);
   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
 #endif
     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
diff --git a/src/objects.h b/src/objects.h
index 755dd42..c84c440 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -37,6 +37,8 @@
 #include "unicode-inl.h"
 #if V8_TARGET_ARCH_ARM
 #include "arm/constants-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/constants-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/constants-mips.h"
 #endif
@@ -1344,8 +1346,13 @@ class HeapNumber: public HeapObject {
   // is a mixture of sign, exponent and mantissa.  Our current platforms are all
   // little endian apart from non-EABI arm which is little endian with big
   // endian floating point word ordering!
+#if __BYTE_ORDER == __LITTLE_ENDIAN
   static const int kMantissaOffset = kValueOffset;
   static const int kExponentOffset = kValueOffset + 4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  static const int kMantissaOffset = kValueOffset + 4;
+  static const int kExponentOffset = kValueOffset;
+#endif
 
   static const int kSize = kValueOffset + kDoubleSize;
   static const uint32_t kSignMask = 0x80000000u;
@@ -5844,10 +5851,11 @@ class SharedFunctionInfo: public HeapObject {
   // garbage collections.
   // To avoid wasting space on 64-bit architectures we use
   // the following trick: we group integer fields into pairs
-  // First integer in each pair is shifted left by 1.
+  // The least significant integer in each pair is shifted left by 1.
   // By doing this we guarantee that LSB of each kPointerSize aligned
   // word is not set and thus this word cannot be treated as pointer
   // to HeapObject during old space traversal.
+#if __BYTE_ORDER == __LITTLE_ENDIAN
   static const int kLengthOffset =
       kAstNodeCountOffset + kPointerSize;
   static const int kFormalParameterCountOffset =
@@ -5875,6 +5883,38 @@ class SharedFunctionInfo: public HeapObject {
 
   static const int kCountersOffset = kOptCountOffset + kIntSize;
   static const int kStressDeoptCounterOffset = kCountersOffset + kIntSize;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  static const int kFormalParameterCountOffset =
+      kAstNodeCountOffset + kPointerSize;
+  static const int kLengthOffset =
+      kFormalParameterCountOffset + kIntSize;
+
+  static const int kNumLiteralsOffset =
+      kLengthOffset + kIntSize;
+  static const int kExpectedNofPropertiesOffset =
+      kNumLiteralsOffset + kIntSize;
+
+  static const int kStartPositionAndTypeOffset =
+      kExpectedNofPropertiesOffset + kIntSize;
+  static const int kEndPositionOffset =
+      kStartPositionAndTypeOffset + kIntSize;
+
+  static const int kCompilerHintsOffset =
+      kEndPositionOffset + kIntSize;
+  static const int kFunctionTokenPositionOffset =
+      kCompilerHintsOffset + kIntSize;
+
+  static const int kOptCountOffset =
+      kFunctionTokenPositionOffset + kIntSize;
+  static const int kThisPropertyAssignmentsCountOffset =
+      kOptCountOffset + kIntSize;
+
+  static const int kStressDeoptCounterOffset =
+      kThisPropertyAssignmentsCountOffset + kIntSize;
+  static const int kCountersOffset = kStressDeoptCounterOffset + kIntSize;
+#else
+#error Unknown byte ordering
+#endif
 
   // Total size.
   static const int kSize = kStressDeoptCounterOffset + kIntSize;
@@ -7314,8 +7354,13 @@ class String: public HeapObject {
 
   // Layout description.
   static const int kLengthOffset = HeapObject::kHeaderSize;
-  static const int kHashFieldOffset = kLengthOffset + kPointerSize;
-  static const int kSize = kHashFieldOffset + kPointerSize;
+  static const int kHashFieldSlot = kLengthOffset + kPointerSize;
+#if __BYTE_ORDER == __LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
+  static const int kHashFieldOffset = kHashFieldSlot;
+#else
+  static const int kHashFieldOffset = kHashFieldSlot + kIntSize;
+#endif
+  static const int kSize = kHashFieldSlot + kPointerSize;
 
   // Maximum number of characters to consider when trying to convert a string
   // value into an array index.
diff --git a/src/platform-aix.cc b/src/platform-aix.cc
new file mode 100644
index 0000000..c739695
--- /dev/null
+++ b/src/platform-aix.cc
@@ -0,0 +1,894 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Platform specific code for AIX goes here. For the POSIX comaptible parts
+// the implementation is in platform-posix.cc.
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <stdlib.h>
+
+#include <sys/types.h>  // mmap & munmap
+#include <sys/mman.h>   // mmap & munmap
+#include <sys/stat.h>   // open
+#include <fcntl.h>      // open
+#include <unistd.h>     // getpagesize
+#include <strings.h>    // index
+#include <errno.h>
+#include <stdarg.h>
+#include <limits.h>
+
+#undef MAP_TYPE
+
+#include "v8.h"
+#include "v8threads.h"
+
+#include "platform-posix.h"
+#include "platform.h"
+#include "vm-state-inl.h"
+
+
+namespace v8 {
+namespace internal {
+
+// 0 is never a valid thread id on AIX since tids and pids share a
+// name space and pid 0 is used to kill the group (see man 2 kill).
+static const pthread_t kNoThread = (pthread_t) 0;
+
+
+double ceiling(double x) {
+    // Correct as on OS X
+    if (-1.0 < x && x < 0.0) {
+        return -0.0;
+    } else {
+        return ceil(x);
+    }
+}
+
+
+static Mutex* limit_mutex = NULL;
+
+
+void OS::PostSetUp() {
+  POSIXPostSetUp();
+}
+
+
+void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
+  __asm__ __volatile__("" : : : "memory");
+  *ptr = value;
+}
+
+
+uint64_t OS::CpuFeaturesImpliedByPlatform() {
+  return 0;  // AIX runs on anything.
+}
+
+
+int OS::ActivationFrameAlignment() {
+  // 8 byte alignment on AIX
+  return 8;
+}
+
+
+const char* OS::LocalTimezone(double time) {
+  if (isnan(time)) return "";
+  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
+  struct tm* t = localtime(&tv);
+  if (NULL == t) return "";
+  return tzname[0];  // The location of the timezone string on AIX.
+}
+
+
+double OS::LocalTimeOffset() {
+  // On AIX, struct tm does not contain a tm_gmtoff field.
+  time_t utc = time(NULL);
+  ASSERT(utc != -1);
+  struct tm* loc = localtime(&utc);
+  ASSERT(loc != NULL);
+  return static_cast<double>((mktime(loc) - utc) * msPerSecond);
+}
+
+
+// We keep the lowest and highest addresses mapped as a quick way of
+// determining that pointers are outside the heap (used mostly in assertions
+// and verification).  The estimate is conservative, i.e., not all addresses in
+// 'allocated' space are actually allocated to our heap.  The range is
+// [lowest, highest), inclusive on the low and and exclusive on the high end.
+static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
+static void* highest_ever_allocated = reinterpret_cast<void*>(0);
+
+
+static void UpdateAllocatedSpaceLimits(void* address, int size) {
+  ASSERT(limit_mutex != NULL);
+  ScopedLock lock(limit_mutex);
+
+  lowest_ever_allocated = Min(lowest_ever_allocated, address);
+  highest_ever_allocated =
+      Max(highest_ever_allocated,
+          reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
+}
+
+
+bool OS::IsOutsideAllocatedSpace(void* address) {
+  return address < lowest_ever_allocated || address >= highest_ever_allocated;
+}
+
+
+size_t OS::AllocateAlignment() {
+  return getpagesize();
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool executable) {
+  const size_t msize = RoundUp(requested, getpagesize());
+  int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0);
+  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+  if (mbase == MAP_FAILED) {
+    LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
+    return NULL;
+  }
+  *allocated = msize;
+  UpdateAllocatedSpaceLimits(mbase, msize);
+  return mbase;
+}
+
+
+void OS::Free(void* buf, const size_t length) {
+  // TODO(1240712): munmap has a return value which is ignored here.
+  int result = munmap(buf, length);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+void OS::Sleep(int milliseconds) {
+  unsigned int ms = static_cast<unsigned int>(milliseconds);
+  usleep(1000 * ms);
+}
+
+
+void OS::Abort() {
+  // Redirect to std abort to signal abnormal program termination.
+  abort();
+}
+
+
+void OS::DebugBreak() {
+#if (defined(__arm__) || defined(__thumb__))
+# if defined(CAN_USE_ARMV5_INSTRUCTIONS)
+  asm("bkpt 0");
+# endif
+#elif defined(_ARCH_PPC)
+  asm("trap");
+#else
+  asm("int $3");
+#endif
+}
+
+
+class PosixMemoryMappedFile : public OS::MemoryMappedFile {
+ public:
+  PosixMemoryMappedFile(FILE* file, void* memory, int size)
+    : file_(file), memory_(memory), size_(size) { }
+  virtual ~PosixMemoryMappedFile();
+  virtual void* memory() { return memory_; }
+  virtual int size() { return size_; }
+ private:
+  FILE* file_;
+  void* memory_;
+  int size_;
+};
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+  FILE* file = fopen(name, "r+");
+  if (file == NULL) return NULL;
+
+  fseek(file, 0, SEEK_END);
+  int size = ftell(file);
+
+  void* memory =
+      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+  return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  FILE* file = fopen(name, "w+");
+  if (file == NULL) return NULL;
+  int result = fwrite(initial, size, 1, file);
+  if (result < 1) {
+    fclose(file);
+    return NULL;
+  }
+  void* memory =
+      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+  return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
+PosixMemoryMappedFile::~PosixMemoryMappedFile() {
+  if (memory_) munmap(memory_, size_);
+  fclose(file_);
+}
+
+
+static unsigned StringToLong(char* buffer) {
+  return static_cast<unsigned>(strtol(buffer, NULL, 16));  // NOLINT
+}
+
+
+void OS::LogSharedLibraryAddresses() {
+  static const int MAP_LENGTH = 1024;
+  int fd = open("/proc/self/maps", O_RDONLY);
+  if (fd < 0) return;
+  while (true) {
+    char addr_buffer[11];
+    addr_buffer[0] = '0';
+    addr_buffer[1] = 'x';
+    addr_buffer[10] = 0;
+    int result = read(fd, addr_buffer + 2, 8);
+    if (result < 8) break;
+    unsigned start = StringToLong(addr_buffer);
+    result = read(fd, addr_buffer + 2, 1);
+    if (result < 1) break;
+    if (addr_buffer[2] != '-') break;
+    result = read(fd, addr_buffer + 2, 8);
+    if (result < 8) break;
+    unsigned end = StringToLong(addr_buffer);
+    char buffer[MAP_LENGTH];
+    int bytes_read = -1;
+    do {
+      bytes_read++;
+      if (bytes_read >= MAP_LENGTH - 1)
+        break;
+      result = read(fd, buffer + bytes_read, 1);
+      if (result < 1) break;
+    } while (buffer[bytes_read] != '\n');
+    buffer[bytes_read] = 0;
+    // Ignore mappings that are not executable.
+    if (buffer[3] != 'x') continue;
+    char* start_of_path = index(buffer, '/');
+    // There may be no filename in this line.  Skip to next.
+    if (start_of_path == NULL) continue;
+    buffer[bytes_read] = 0;
+    LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end));
+  }
+  close(fd);
+}
+
+
+void OS::SignalCodeMovingGC() {
+}
+
+
+int OS::StackWalk(Vector<OS::StackFrame> frames) {
+  return 0;
+}
+
+
+// Constants used for mmap.
+static const int kMmapFd = -1;
+static const int kMmapFdOffset = 0;
+
+VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
+
+VirtualMemory::VirtualMemory(size_t size) {
+  address_ = ReserveRegion(size);
+  size_ = size;
+}
+
+
+VirtualMemory::VirtualMemory(size_t size, size_t alignment)
+    : address_(NULL), size_(0) {
+  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
+  size_t request_size = RoundUp(size + alignment,
+                                static_cast<intptr_t>(OS::AllocateAlignment()));
+  void* reservation = mmap(OS::GetRandomMmapAddr(),
+                           request_size,
+                           PROT_NONE,
+                           MAP_PRIVATE | MAP_ANONYMOUS,
+                           kMmapFd,
+                           kMmapFdOffset);
+  if (reservation == MAP_FAILED) return;
+
+  Address base = static_cast<Address>(reservation);
+  Address aligned_base = RoundUp(base, alignment);
+  ASSERT_LE(base, aligned_base);
+
+  // Unmap extra memory reserved before and after the desired block.
+  if (aligned_base != base) {
+    size_t prefix_size = static_cast<size_t>(aligned_base - base);
+    OS::Free(base, prefix_size);
+    request_size -= prefix_size;
+  }
+
+  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
+  ASSERT_LE(aligned_size, request_size);
+
+  if (aligned_size != request_size) {
+    size_t suffix_size = request_size - aligned_size;
+    OS::Free(aligned_base + aligned_size, suffix_size);
+    request_size -= suffix_size;
+  }
+
+  ASSERT(aligned_size == request_size);
+
+  address_ = static_cast<void*>(aligned_base);
+  size_ = aligned_size;
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  if (IsReserved()) {
+    bool result = ReleaseRegion(address(), size());
+    ASSERT(result);
+    USE(result);
+  }
+}
+
+
+bool VirtualMemory::IsReserved() {
+  return address_ != NULL;
+}
+
+
+void VirtualMemory::Reset() {
+  address_ = NULL;
+  size_ = 0;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+  return CommitRegion(address, size, is_executable);
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  return UncommitRegion(address, size);
+}
+
+
+bool VirtualMemory::Guard(void* address) {
+  OS::Guard(address, OS::CommitPageSize());
+  return true;
+}
+
+
+void* VirtualMemory::ReserveRegion(size_t size) {
+  void* result = mmap(OS::GetRandomMmapAddr(),
+                      size,
+                      PROT_NONE,
+                      MAP_PRIVATE | MAP_ANONYMOUS,
+                      kMmapFd,
+                      kMmapFdOffset);
+
+  if (result == MAP_FAILED) return NULL;
+
+  return result;
+}
+
+
+bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
+  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+  if (mprotect(base, size, prot) == -1) return false;
+
+  UpdateAllocatedSpaceLimits(base, size);
+  return true;
+}
+
+
+bool VirtualMemory::UncommitRegion(void* base, size_t size) {
+  return mprotect(base, size, PROT_NONE) != -1;
+}
+
+
+bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
+  return munmap(base, size) == 0;
+}
+
+
+class Thread::PlatformData : public Malloced {
+ public:
+  pthread_t thread_;  // Thread handle for pthread.
+};
+
+
+Thread::Thread(const Options& options)
+    : data_(new PlatformData),
+      stack_size_(options.stack_size()) {
+  set_name(options.name());
+}
+
+
+Thread::~Thread() {
+  delete data_;
+}
+
+
+static void* ThreadEntry(void* arg) {
+  Thread* thread = reinterpret_cast<Thread*>(arg);
+  // This is also initialized by the first argument to pthread_create() but we
+  // don't know which thread will run first (the original thread or the new
+  // one) so we initialize it here too.
+  thread->data()->thread_ = pthread_self();
+  ASSERT(thread->data()->thread_ != kNoThread);
+  thread->Run();
+  return NULL;
+}
+
+
+void Thread::set_name(const char* name) {
+  strncpy(name_, name, sizeof(name_));
+  name_[sizeof(name_) - 1] = '\0';
+}
+
+
+void Thread::Start() {
+  pthread_attr_t attr;
+  size_t stack_size = stack_size_;
+
+  if (stack_size == 0) {
+    // Default is 96KB -- bump up to 2MB
+    stack_size = 2 * MB;
+  }
+  pthread_attr_init(&attr);
+  pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size));
+  pthread_create(&data_->thread_, &attr, ThreadEntry, this);
+  ASSERT(data_->thread_ != kNoThread);
+}
+
+
+void Thread::Join() {
+  pthread_join(data_->thread_, NULL);
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  pthread_key_t key;
+  int result = pthread_key_create(&key, NULL);
+  USE(result);
+  ASSERT(result == 0);
+  return static_cast<LocalStorageKey>(key);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  int result = pthread_key_delete(pthread_key);
+  USE(result);
+  ASSERT(result == 0);
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  return pthread_getspecific(pthread_key);
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
+  pthread_setspecific(pthread_key, value);
+}
+
+
+void Thread::YieldCPU() {
+  sched_yield();
+}
+
+
+class AIXMutex : public Mutex {
+ public:
+  AIXMutex() {
+    pthread_mutexattr_t attrs;
+    int result = pthread_mutexattr_init(&attrs);
+    ASSERT(result == 0);
+    result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
+    ASSERT(result == 0);
+    result = pthread_mutex_init(&mutex_, &attrs);
+    ASSERT(result == 0);
+    USE(result);
+  }
+
+  virtual ~AIXMutex() { pthread_mutex_destroy(&mutex_); }
+
+  virtual int Lock() {
+    int result = pthread_mutex_lock(&mutex_);
+    return result;
+  }
+
+  virtual int Unlock() {
+    int result = pthread_mutex_unlock(&mutex_);
+    return result;
+  }
+
+  virtual bool TryLock() {
+    int result = pthread_mutex_trylock(&mutex_);
+    // Return false if the lock is busy and locking failed.
+    if (result == EBUSY) {
+      return false;
+    }
+    ASSERT(result == 0);  // Verify no other errors.
+    return true;
+  }
+
+ private:
+  pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
+};
+
+
+Mutex* OS::CreateMutex() {
+  return new AIXMutex();
+}
+
+
+class AIXSemaphore : public Semaphore {
+ public:
+  explicit AIXSemaphore(int count) {  sem_init(&sem_, 0, count); }
+  virtual ~AIXSemaphore() { sem_destroy(&sem_); }
+
+  virtual void Wait();
+  virtual bool Wait(int timeout);
+  virtual void Signal() { sem_post(&sem_); }
+ private:
+  sem_t sem_;
+};
+
+
+void AIXSemaphore::Wait() {
+  while (true) {
+    int result = sem_wait(&sem_);
+    if (result == 0) return;  // Successfully got semaphore.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+#ifndef TIMEVAL_TO_TIMESPEC
+#define TIMEVAL_TO_TIMESPEC(tv, ts) do {                            \
+    (ts)->tv_sec = (tv)->tv_sec;                                    \
+    (ts)->tv_nsec = (tv)->tv_usec * 1000;                           \
+} while (false)
+#endif
+
+
+#ifndef timeradd
+#define timeradd(a, b, result) \
+  do { \
+    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
+    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
+    if ((result)->tv_usec >= 1000000) { \
+      ++(result)->tv_sec; \
+      (result)->tv_usec -= 1000000; \
+    } \
+  } while (0)
+#endif
+
+
+bool AIXSemaphore::Wait(int timeout) {
+  const long kOneSecondMicros = 1000000;  // NOLINT
+
+  // Split timeout into second and nanosecond parts.
+  struct timeval delta;
+  delta.tv_usec = timeout % kOneSecondMicros;
+  delta.tv_sec = timeout / kOneSecondMicros;
+
+  struct timeval current_time;
+  // Get the current time.
+  if (gettimeofday(&current_time, NULL) == -1) {
+    return false;
+  }
+
+  // Calculate time for end of timeout.
+  struct timeval end_time;
+  timeradd(&current_time, &delta, &end_time);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC(&end_time, &ts);
+  while (true) {
+    int result = sem_timedwait(&sem_, &ts);
+    if (result == 0) return true;  // Successfully got semaphore.
+    if (result == -1 && errno == ETIMEDOUT) return false;  // Timeout.
+    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
+  }
+}
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  return new AIXSemaphore(count);
+}
+
+
+static pthread_t GetThreadID() {
+  pthread_t thread_id = pthread_self();
+  return thread_id;
+}
+
+
+class Sampler::PlatformData : public Malloced {
+ public:
+  PlatformData() : vm_tid_(GetThreadID()) {}
+
+  pthread_t vm_tid() const { return vm_tid_; }
+
+ private:
+  pthread_t vm_tid_;
+};
+
+
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+  USE(info);
+  if (signal != SIGPROF) return;
+  Isolate* isolate = Isolate::UncheckedCurrent();
+  if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
+    // We require a fully initialized and entered isolate.
+    return;
+  }
+  if (v8::Locker::IsActive() &&
+      !isolate->thread_manager()->IsLockedByCurrentThread()) {
+    return;
+  }
+
+  Sampler* sampler = isolate->logger()->sampler();
+  if (sampler == NULL || !sampler->IsActive()) return;
+
+  TickSample sample_obj;
+  TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+  if (sample == NULL) sample = &sample_obj;
+
+  // Extracting the sample from the context is extremely machine dependent.
+  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+  mcontext_t& mcontext = ucontext->uc_mcontext;
+  sample->state = isolate->current_vm_state();
+#if V8_HOST_ARCH_IA32
+  sample->pc = reinterpret_cast<Address>(mcontext.mc_eip);
+  sample->sp = reinterpret_cast<Address>(mcontext.mc_esp);
+  sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp);
+#elif V8_HOST_ARCH_X64
+  sample->pc = reinterpret_cast<Address>(mcontext.mc_rip);
+  sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp);
+  sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp);
+#elif V8_HOST_ARCH_ARM
+  sample->pc = reinterpret_cast<Address>(mcontext.mc_r15);
+  sample->sp = reinterpret_cast<Address>(mcontext.mc_r13);
+  sample->fp = reinterpret_cast<Address>(mcontext.mc_r11);
+#elif V8_HOST_ARCH_PPC
+  sample->pc = reinterpret_cast<Address>(mcontext.jmp_context.iar);
+  sample->sp = reinterpret_cast<Address>(mcontext.jmp_context.gpr[1]);
+  sample->fp = reinterpret_cast<Address>(mcontext.jmp_context.gpr[1]);
+#endif
+  sampler->SampleStack(sample);
+  sampler->Tick(sample);
+}
+
+
+class SignalSender : public Thread {
+ public:
+  enum SleepInterval {
+    HALF_INTERVAL,
+    FULL_INTERVAL
+  };
+
+  static const int kSignalSenderStackSize = 64 * KB;
+
+  explicit SignalSender(int interval)
+      : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
+        interval_(interval) {}
+
+  static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
+  static void TearDown() { delete mutex_; }
+
+  static void AddActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::AddActiveSampler(sampler);
+    if (instance_ == NULL) {
+      // Install a signal handler.
+      struct sigaction sa;
+      sa.sa_sigaction = ProfilerSignalHandler;
+      sigemptyset(&sa.sa_mask);
+      sa.sa_flags = SA_RESTART | SA_SIGINFO;
+      signal_handler_installed_ =
+          (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
+
+      // Start a thread that sends SIGPROF signal to VM threads.
+      instance_ = new SignalSender(sampler->interval());
+      instance_->Start();
+    } else {
+      ASSERT(instance_->interval_ == sampler->interval());
+    }
+  }
+
+  static void RemoveActiveSampler(Sampler* sampler) {
+    ScopedLock lock(mutex_);
+    SamplerRegistry::RemoveActiveSampler(sampler);
+    if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
+      RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+      delete instance_;
+      instance_ = NULL;
+
+      // Restore the old signal handler.
+      if (signal_handler_installed_) {
+        sigaction(SIGPROF, &old_signal_handler_, 0);
+        signal_handler_installed_ = false;
+      }
+    }
+  }
+
+  // Implement Thread::Run().
+  virtual void Run() {
+    SamplerRegistry::State state;
+    while ((state = SamplerRegistry::GetState()) !=
+           SamplerRegistry::HAS_NO_SAMPLERS) {
+      bool cpu_profiling_enabled =
+          (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
+      bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
+      // When CPU profiling is enabled both JavaScript and C++ code is
+      // profiled. We must not suspend.
+      if (!cpu_profiling_enabled) {
+        if (rate_limiter_.SuspendIfNecessary()) continue;
+      }
+      if (cpu_profiling_enabled && runtime_profiler_enabled) {
+        if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
+          return;
+        }
+        Sleep(HALF_INTERVAL);
+        if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
+          return;
+        }
+        Sleep(HALF_INTERVAL);
+      } else {
+        if (cpu_profiling_enabled) {
+          if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
+                                                      this)) {
+            return;
+          }
+        }
+        if (runtime_profiler_enabled) {
+          if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
+                                                      NULL)) {
+            return;
+          }
+        }
+        Sleep(FULL_INTERVAL);
+      }
+    }
+  }
+
+  static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
+    if (!sampler->IsProfiling()) return;
+    SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
+    sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
+  }
+
+  static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
+    if (!sampler->isolate()->IsInitialized()) return;
+    sampler->isolate()->runtime_profiler()->NotifyTick();
+  }
+
+  void SendProfilingSignal(pthread_t tid) {
+    if (!signal_handler_installed_) return;
+    pthread_kill(tid, SIGPROF);
+  }
+
+  void Sleep(SleepInterval full_or_half) {
+    // Convert ms to us and subtract 100 us to compensate delays
+    // occuring during signal delivery.
+    useconds_t interval = interval_ * 1000 - 100;
+    if (full_or_half == HALF_INTERVAL) interval /= 2;
+    int result = usleep(interval);
+#ifdef DEBUG
+    if (result != 0 && errno != EINTR) {
+      fprintf(stderr,
+              "SignalSender usleep error; interval = %u, errno = %d\n",
+              interval,
+              errno);
+      ASSERT(result == 0 || errno == EINTR);
+    }
+#endif
+    USE(result);
+  }
+
+  const int interval_;
+  RuntimeProfilerRateLimiter rate_limiter_;
+
+  // Protects the process wide state below.
+  static Mutex* mutex_;
+  static SignalSender* instance_;
+  static bool signal_handler_installed_;
+  static struct sigaction old_signal_handler_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SignalSender);
+};
+
+Mutex* SignalSender::mutex_ = NULL;
+SignalSender* SignalSender::instance_ = NULL;
+struct sigaction SignalSender::old_signal_handler_;
+bool SignalSender::signal_handler_installed_ = false;
+
+
+void OS::SetUp() {
+  // Seed the random number generator.
+  // Convert the current time to a 64-bit integer first, before converting it
+  // to an unsigned. Going directly can cause an overflow and the seed to be
+  // set to all ones. The seed will be identical for different instances that
+  // call this setup code within the same millisecond.
+  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
+  srandom(static_cast<unsigned int>(seed));
+  limit_mutex = CreateMutex();
+  SignalSender::SetUp();
+}
+
+
+void OS::TearDown() {
+  SignalSender::TearDown();
+  delete limit_mutex;
+}
+
+
+Sampler::Sampler(Isolate* isolate, int interval)
+    : isolate_(isolate),
+      interval_(interval),
+      profiling_(false),
+      active_(false),
+      samples_taken_(0) {
+  data_ = new PlatformData;
+}
+
+
+Sampler::~Sampler() {
+  ASSERT(!IsActive());
+  delete data_;
+}
+
+
+void Sampler::Start() {
+  ASSERT(!IsActive());
+  SetActive(true);
+  SignalSender::AddActiveSampler(this);
+}
+
+
+void Sampler::Stop() {
+  ASSERT(IsActive());
+  SignalSender::RemoveActiveSampler(this);
+  SetActive(false);
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 511759c..f8d04f5 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -698,6 +698,10 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   sample->pc = reinterpret_cast<Address>(mcontext.mc_r15);
   sample->sp = reinterpret_cast<Address>(mcontext.mc_r13);
   sample->fp = reinterpret_cast<Address>(mcontext.mc_r11);
+#elif V8_HOST_ARCH_PPC
+  sample->pc = reinterpret_cast<Address>(mcontext.mc_r15);
+  sample->sp = reinterpret_cast<Address>(mcontext.mc_r13);
+  sample->fp = reinterpret_cast<Address>(mcontext.mc_r11);
 #endif
   sampler->SampleStack(sample);
   sampler->Tick(sample);
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index beb2cce..31cd279 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -291,6 +291,8 @@ int OS::ActivationFrameAlignment() {
   return 8;
 #elif V8_TARGET_ARCH_MIPS
   return 8;
+#elif V8_TARGET_ARCH_PPC
+  return 8;
 #endif
   // With gcc 4.4 the tree vectorization optimizer can generate code
   // that requires 16 byte alignment such as movdqa on x86.
@@ -300,6 +302,7 @@ int OS::ActivationFrameAlignment() {
 
 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
 #if (defined(V8_TARGET_ARCH_ARM) && defined(__arm__)) || \
+    (defined(V8_TARGET_ARCH_PPC) && defined(__PPC__)) || \
     (defined(V8_TARGET_ARCH_MIPS) && defined(__mips__))
   // Only use on ARM or MIPS hardware.
   MemoryBarrier();
@@ -409,6 +412,9 @@ void OS::DebugBreak() {
 # endif
 #elif defined(__mips__)
   asm("break");
+#elif defined(__PPC__)
+  asm("twge 2,2");
+//  asm("nop");  // roohack - nothing for now;
 #else
   asm("int $3");
 #endif
@@ -813,7 +819,11 @@ void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
 
 
 void Thread::YieldCPU() {
+#ifdef V8_TARGET_ARCH_PPC
+  i::OS::Sleep(0);
+#else
   sched_yield();
+#endif
 }
 
 
@@ -1039,7 +1049,9 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
 
   // Extracting the sample from the context is extremely machine dependent.
   ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+#ifndef V8_HOST_ARCH_PPC
   mcontext_t& mcontext = ucontext->uc_mcontext;
+#endif
   sample->state = isolate->current_vm_state();
 #if V8_HOST_ARCH_IA32
   sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
@@ -1067,6 +1079,12 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   sample->pc = reinterpret_cast<Address>(mcontext.pc);
   sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
   sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
+#elif V8_HOST_ARCH_PPC
+  sample->pc = reinterpret_cast<Address>(ucontext->uc_mcontext.regs->nip);
+  sample->sp =
+    reinterpret_cast<Address>(ucontext->uc_mcontext.regs->gpr[PT_R1]);
+  sample->fp =
+    reinterpret_cast<Address>(ucontext->uc_mcontext.regs->gpr[PT_R31]);
 #endif  // V8_HOST_ARCH_*
   sampler->SampleStack(sample);
   sampler->Tick(sample);
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index 3bc8373..a193cb2 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -53,6 +53,10 @@
 #include <android/log.h>
 #endif
 
+#if defined(_AIX)
+#include <fenv.h>
+#endif
+
 #include "v8.h"
 
 #include "codegen.h"
@@ -112,9 +116,15 @@ void* OS::GetRandomMmapAddr() {
     // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
     // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
     // 10.6 and 10.7.
+    // The range 0x30000000 - 0xD0000000 is available on AIX;
+    // choose the upper range.
     raw_addr &= 0x3ffff000;
+#ifdef _AIX
+    raw_addr += 0x90000000;
+#else
     raw_addr += 0x20000000;
 #endif
+#endif
     return reinterpret_cast<void*>(raw_addr);
   }
   return NULL;
@@ -125,7 +135,17 @@ void* OS::GetRandomMmapAddr() {
 // Math functions
 
 double modulo(double x, double y) {
+#if defined(_AIX)
+  // AIX raises an underflow exception for (Number.MIN_VALUE % Number.MAX_VALUE)
+  double result;
+  int exception;
+  feclearexcept(FE_ALL_EXCEPT);
+  result = fmod(x, y);
+  exception = fetestexcept(FE_UNDERFLOW);
+  return (exception ? x : result);
+#else
   return fmod(x, y);
+#endif
 }
 
 
@@ -147,6 +167,11 @@ UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
 #undef MATH_FUNCTION
 
 
+#ifdef _AIX
+#undef NAN
+#define NAN (__builtin_nanf(""))
+#endif
+
 double OS::nan_value() {
   // NAN from math.h is defined in C99 and not in POSIX.
   return NAN;
diff --git a/src/platform.h b/src/platform.h
index de896ac..ffadecc 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -107,7 +107,8 @@ namespace internal {
 
 // Use AtomicWord for a machine-sized pointer. It is assumed that
 // reads and writes of naturally aligned values of this type are atomic.
-#if defined(__OpenBSD__) && defined(__i386__)
+#if !defined(V8_HOST_ARCH_64_BIT) && \
+  ((defined(__OpenBSD__) && defined(__i386__)) || defined(_AIX))
 typedef Atomic32 AtomicWord;
 #else
 typedef intptr_t AtomicWord;
diff --git a/src/ppc/assembler-ppc-inl.h b/src/ppc/assembler-ppc-inl.h
new file mode 100644
index 0000000..ea80c03
--- /dev/null
+++ b/src/ppc/assembler-ppc-inl.h
@@ -0,0 +1,457 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistribution in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of Sun Microsystems or the names of contributors may
+// be used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The original source code covered by the above license above has been modified
+// significantly by Google Inc.
+// Copyright 2012 the V8 project authors. All rights reserved.
+
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+
+#ifndef V8_PPC_ASSEMBLER_PPC_INL_H_
+#define V8_PPC_ASSEMBLER_PPC_INL_H_
+
+#include "ppc/assembler-ppc.h"
+
+#include "cpu.h"
+#include "debug.h"
+
+
+namespace v8 {
+namespace internal {
+
+
+int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) {
+  int index = reg.code() - 1;  // d0 is skipped
+  ASSERT(index < kNumAllocatableRegisters);
+  ASSERT(!reg.is(kDoubleRegZero));
+  ASSERT(!reg.is(kScratchDoubleReg));
+  return index;
+}
+
+void RelocInfo::apply(intptr_t delta) {
+  if (RelocInfo::IsInternalReference(rmode_)) {
+    // absolute code pointer inside code object moves with the code object.
+    intptr_t* p = reinterpret_cast<intptr_t*>(pc_);
+    *p += delta;  // relocate entry
+    CPU::FlushICache(p, sizeof(uintptr_t));
+  }
+  // We do not use pc relative addressing on PPC, so there is
+  // nothing else to do.
+}
+
+
+Address RelocInfo::target_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  return Assembler::target_address_at(pc_);
+}
+
+
+Address RelocInfo::target_address_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
+                              || rmode_ == EMBEDDED_OBJECT
+                              || rmode_ == EXTERNAL_REFERENCE);
+
+  // Read the address of the word containing the target_address in an
+  // instruction stream.
+  // The only architecture-independent user of this function is the serializer.
+  // The serializer uses it to find out how many raw bytes of instruction to
+  // output before the next target.
+  // For an instruction like LIS/ADDIC where the target bits are mixed into the
+  // instruction bits, the size of the target will be zero, indicating that the
+  // serializer should not step forward in memory after a target is resolved
+  // and written. In this case the target_address_address function should
+  // return the end of the instructions to be patched, allowing the
+  // deserializer to deserialize the instructions as raw bytes and put them in
+  // place, ready to be patched with the target.
+
+  return reinterpret_cast<Address>(
+    pc_ + (Assembler::kInstructionsForPtrConstant *
+           Assembler::kInstrSize));
+}
+
+
+int RelocInfo::target_address_size() {
+  return Assembler::kSpecialTargetSize;
+}
+
+
+void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+  Assembler::set_target_address_at(pc_, target);
+  if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) {
+    Object* target_code = Code::GetCodeFromTargetAddress(target);
+    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
+        host(), this, HeapObject::cast(target_code));
+  }
+}
+
+
+Address Assembler::target_address_from_return_address(Address pc) {
+  return pc - kCallTargetAddressOffset;
+}
+
+
+Object* RelocInfo::target_object() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
+}
+
+
+Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return Handle<Object>(reinterpret_cast<Object**>(
+      Assembler::target_address_at(pc_)));
+}
+
+
+Object** RelocInfo::target_object_address() {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  reconstructed_obj_ptr_ =
+      reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
+  return &reconstructed_obj_ptr_;
+}
+
+
+void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target));
+  if (mode == UPDATE_WRITE_BARRIER &&
+      host() != NULL &&
+      target->IsHeapObject()) {
+    host()->GetHeap()->incremental_marking()->RecordWrite(
+        host(), &Memory::Object_at(pc_), HeapObject::cast(target));
+  }
+}
+
+
+Address* RelocInfo::target_reference_address() {
+  ASSERT(rmode_ == EXTERNAL_REFERENCE);
+  reconstructed_adr_ptr_ = Assembler::target_address_at(pc_);
+  return &reconstructed_adr_ptr_;
+}
+
+
+Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
+  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+  Address address = Memory::Address_at(pc_);
+  return Handle<JSGlobalPropertyCell>(
+      reinterpret_cast<JSGlobalPropertyCell**>(address));
+}
+
+
+JSGlobalPropertyCell* RelocInfo::target_cell() {
+  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+  return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
+}
+
+
+void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
+                                WriteBarrierMode mode) {
+  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+  Memory::Address_at(pc_) = address;
+  if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
+    // TODO(1550) We are passing NULL as a slot because cell can never be on
+    // evacuation candidate.
+    host()->GetHeap()->incremental_marking()->RecordWrite(
+        host(), NULL, cell);
+  }
+}
+
+
+Address RelocInfo::call_address() {
+  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
+  // The pc_ offset of 0 assumes patched return sequence per
+  // BreakLocationIterator::SetDebugBreakAtReturn(), or debug break
+  // slot per BreakLocationIterator::SetDebugBreakAtSlot().
+  return Assembler::target_address_at(pc_);
+}
+
+
+void RelocInfo::set_call_address(Address target) {
+  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
+  Assembler::set_target_address_at(pc_, target);
+  if (host() != NULL) {
+    Object* target_code = Code::GetCodeFromTargetAddress(target);
+    host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
+        host(), this, HeapObject::cast(target_code));
+  }
+}
+
+
+Object* RelocInfo::call_object() {
+  return *call_object_address();
+}
+
+
+void RelocInfo::set_call_object(Object* target) {
+  *call_object_address() = target;
+}
+
+
+Object** RelocInfo::call_object_address() {
+  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
+         (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
+  return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
+}
+
+
+bool RelocInfo::IsPatchedReturnSequence() {
+  //
+  // The patched return sequence is defined by
+  // BreakLocationIterator::SetDebugBreakAtReturn()
+  // FIXED_SEQUENCE
+
+  Instr instr0 = Assembler::instr_at(pc_);
+  Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
+#if V8_TARGET_ARCH_PPC64
+  Instr instr3 = Assembler::instr_at(pc_ + (3 * Assembler::kInstrSize));
+  Instr instr4 = Assembler::instr_at(pc_ + (4 * Assembler::kInstrSize));
+  Instr binstr = Assembler::instr_at(pc_ + (7 * Assembler::kInstrSize));
+#else
+  Instr binstr = Assembler::instr_at(pc_ + 4 * Assembler::kInstrSize);
+#endif
+  bool patched_return = ((instr0 & kOpcodeMask) == ADDIS &&
+                         (instr1 & kOpcodeMask) == ORI &&
+#if V8_TARGET_ARCH_PPC64
+                         (instr3 & kOpcodeMask) == ORIS &&
+                         (instr4 & kOpcodeMask) == ORI &&
+#endif
+                         (binstr == 0x7d821008));   // twge r2, r2
+
+// printf("IsPatchedReturnSequence: %d\n", patched_return);
+  return patched_return;
+}
+
+
+bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
+  Instr current_instr = Assembler::instr_at(pc_);
+  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
+}
+
+
+void RelocInfo::Visit(ObjectVisitor* visitor) {
+  RelocInfo::Mode mode = rmode();
+  if (mode == RelocInfo::EMBEDDED_OBJECT) {
+    visitor->VisitEmbeddedPointer(this);
+  } else if (RelocInfo::IsCodeTarget(mode)) {
+    visitor->VisitCodeTarget(this);
+  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
+    visitor->VisitGlobalPropertyCell(this);
+  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
+    visitor->VisitExternalReference(this);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  // TODO(isolates): Get a cached isolate below.
+  } else if (((RelocInfo::IsJSReturn(mode) &&
+              IsPatchedReturnSequence()) ||
+             (RelocInfo::IsDebugBreakSlot(mode) &&
+              IsPatchedDebugBreakSlotSequence())) &&
+             Isolate::Current()->debug()->has_break_points()) {
+    visitor->VisitDebugTarget(this);
+#endif
+  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+    visitor->VisitRuntimeEntry(this);
+  }
+}
+
+
+template<typename StaticVisitor>
+void RelocInfo::Visit(Heap* heap) {
+  RelocInfo::Mode mode = rmode();
+  if (mode == RelocInfo::EMBEDDED_OBJECT) {
+    StaticVisitor::VisitEmbeddedPointer(heap, this);
+  } else if (RelocInfo::IsCodeTarget(mode)) {
+    StaticVisitor::VisitCodeTarget(heap, this);
+  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
+    StaticVisitor::VisitGlobalPropertyCell(heap, this);
+  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
+    StaticVisitor::VisitExternalReference(this);
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  } else if (heap->isolate()->debug()->has_break_points() &&
+             ((RelocInfo::IsJSReturn(mode) &&
+              IsPatchedReturnSequence()) ||
+             (RelocInfo::IsDebugBreakSlot(mode) &&
+              IsPatchedDebugBreakSlotSequence()))) {
+    StaticVisitor::VisitDebugTarget(heap, this);
+#endif
+  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+    StaticVisitor::VisitRuntimeEntry(this);
+  }
+}
+
+Operand::Operand(intptr_t immediate, RelocInfo::Mode rmode)  {
+  rm_ = no_reg;
+  imm_ = immediate;
+  rmode_ = rmode;
+}
+
+Operand::Operand(const ExternalReference& f)  {
+  rm_ = no_reg;
+  imm_ = reinterpret_cast<intptr_t>(f.address());
+  rmode_ = RelocInfo::EXTERNAL_REFERENCE;
+}
+
+Operand::Operand(Smi* value) {
+  rm_ = no_reg;
+  imm_ =  reinterpret_cast<intptr_t>(value);
+  rmode_ = RelocInfo::NONE;
+}
+
+Operand::Operand(Register rm) {
+  rm_ = rm;
+  rmode_ = RelocInfo::NONE;  // PPC -why doesn't ARM do this?
+}
+
+void Assembler::CheckBuffer() {
+  if (buffer_space() <= kGap) {
+    GrowBuffer();
+  }
+}
+
+void Assembler::CheckTrampolinePoolQuick() {
+  if (pc_offset() >= next_buffer_check_) {
+    CheckTrampolinePool();
+  }
+}
+
+void Assembler::emit(Instr x) {
+  CheckBuffer();
+  *reinterpret_cast<Instr*>(pc_) = x;
+  pc_ += kInstrSize;
+  CheckTrampolinePoolQuick();
+}
+
+bool Operand::is_reg() const {
+  return rm_.is_valid();
+}
+
+
+// Fetch the 32bit value from the FIXED_SEQUENCE lis/ori
+Address Assembler::target_address_at(Address pc) {
+  Instr instr1 = instr_at(pc);
+  Instr instr2 = instr_at(pc + kInstrSize);
+#if V8_TARGET_ARCH_PPC64
+  Instr instr4 = instr_at(pc + (3*kInstrSize));
+  Instr instr5 = instr_at(pc + (4*kInstrSize));
+#endif
+  // Interpret 2 instructions generated by lis/ori
+  if (IsLis(instr1) && IsOri(instr2)) {
+#if V8_TARGET_ARCH_PPC64
+    // Assemble the 64 bit value.
+    uint64_t hi = (static_cast<uint32_t>((instr1 & kImm16Mask) << 16) |
+                   static_cast<uint32_t>(instr2 & kImm16Mask));
+    uint64_t lo = (static_cast<uint32_t>((instr4 & kImm16Mask) << 16) |
+                   static_cast<uint32_t>(instr5 & kImm16Mask));
+    return reinterpret_cast<Address>((hi << 32) | lo);
+#else
+    // Assemble the 32 bit value.
+    return reinterpret_cast<Address>(
+        ((instr1 & kImm16Mask) << 16) | (instr2 & kImm16Mask));
+#endif
+  }
+
+  PPCPORT_UNIMPLEMENTED();
+  return (Address)0;
+}
+
+
+// This sets the branch destination (which gets loaded at the call address).
+// This is for calls and branches within generated code.  The serializer
+// has already deserialized the lis/ori instructions etc.
+// There is a FIXED_SEQUENCE assumption here
+void Assembler::deserialization_set_special_target_at(
+    Address instruction_payload, Address target) {
+  set_target_address_at(
+      instruction_payload - kInstructionsForPtrConstant * kInstrSize,
+      target);
+}
+
+// This code assumes the FIXED_SEQUENCE of lis/ori
+void Assembler::set_target_address_at(Address pc, Address target) {
+  Instr instr1 = instr_at(pc);
+  Instr instr2 = instr_at(pc + kInstrSize);
+  // Interpret 2 instructions generated by lis/ori
+  if (IsLis(instr1) && IsOri(instr2)) {
+#if V8_TARGET_ARCH_PPC64
+    Instr instr4 = instr_at(pc + (3*kInstrSize));
+    Instr instr5 = instr_at(pc + (4*kInstrSize));
+    // Needs to be fixed up when mov changes to handle 64-bit values.
+    uint32_t* p = reinterpret_cast<uint32_t*>(pc);
+    uintptr_t itarget = reinterpret_cast<uintptr_t>(target);
+
+    instr5 &= ~kImm16Mask;
+    instr5 |= itarget & kImm16Mask;
+    itarget = itarget >> 16;
+
+    instr4 &= ~kImm16Mask;
+    instr4 |= itarget & kImm16Mask;
+    itarget = itarget >> 16;
+
+    instr2 &= ~kImm16Mask;
+    instr2 |= itarget & kImm16Mask;
+    itarget = itarget >> 16;
+
+    instr1 &= ~kImm16Mask;
+    instr1 |= itarget & kImm16Mask;
+    itarget = itarget >> 16;
+
+    *p = instr1;
+    *(p+1) = instr2;
+    *(p+3) = instr4;
+    *(p+4) = instr5;
+    CPU::FlushICache(p, 20);
+#else
+    uint32_t* p = reinterpret_cast<uint32_t*>(pc);
+    uint32_t itarget = reinterpret_cast<uint32_t>(target);
+    int lo_word = itarget & kImm16Mask;
+    int hi_word = itarget >> 16;
+    instr1 &= ~kImm16Mask;
+    instr1 |= hi_word;
+    instr2 &= ~kImm16Mask;
+    instr2 |= lo_word;
+
+    *p = instr1;
+    *(p+1) = instr2;
+    CPU::FlushICache(p, 8);
+#endif
+  } else {
+    UNREACHABLE();
+  }
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_ASSEMBLER_PPC_INL_H_
diff --git a/src/ppc/assembler-ppc.cc b/src/ppc/assembler-ppc.cc
new file mode 100644
index 0000000..ecfa1b4
--- /dev/null
+++ b/src/ppc/assembler-ppc.cc
@@ -0,0 +1,1881 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistribution in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of Sun Microsystems or the names of contributors may
+// be used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2012 the V8 project authors. All rights reserved.
+
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "ppc/assembler-ppc-inl.h"
+#include "serialize.h"
+
+namespace v8 {
+namespace internal {
+
+#ifdef DEBUG
+bool CpuFeatures::initialized_ = false;
+#endif
+unsigned CpuFeatures::supported_ = 0;
+unsigned CpuFeatures::found_by_runtime_probing_ = 0;
+
+// Get the CPU features enabled by the build.
+static unsigned CpuFeaturesImpliedByCompiler() {
+  unsigned answer = 0;
+  return answer;
+}
+
+#if !defined(_AIX)
+// This function uses types in elf.h
+static bool is_processor(const char* p) {
+  static bool read_tried = false;
+  static char *auxv_cpu_type = NULL;
+
+  if (!read_tried) {
+    // Open the AUXV (auxilliary vector) psuedo-file
+    int fd = open("/proc/self/auxv", O_RDONLY);
+
+    read_tried = true;
+    if (fd != -1) {
+#if V8_TARGET_ARCH_PPC64
+      static Elf64_auxv_t buffer[16];
+      Elf64_auxv_t *auxv_element;
+#else
+      static Elf32_auxv_t buffer[16];
+      Elf32_auxv_t *auxv_element;
+#endif
+      int bytes_read = 0;
+      while (bytes_read >= 0) {
+        // Read a chunk of the AUXV
+        bytes_read = read(fd, buffer, sizeof(buffer));
+        // Locate and read the platform field of AUXV if it is in the chunk
+        for (auxv_element = buffer;
+             auxv_element+sizeof(auxv_element) <= buffer+bytes_read &&
+             auxv_element->a_type != AT_NULL;
+             auxv_element++) {
+          if (auxv_element->a_type == AT_PLATFORM) {
+            /* Note: Both auxv_cpu_type and buffer are static */
+            auxv_cpu_type = reinterpret_cast<char*>(auxv_element->a_un.a_val);
+            goto done_reading;
+          }
+        }
+      }
+      done_reading:
+      close(fd);
+    }
+  }
+
+  if (auxv_cpu_type == NULL) {
+    return false;
+  }
+  return (strcmp(auxv_cpu_type, p) == 0);
+}
+#endif
+
+void CpuFeatures::Probe() {
+  unsigned standard_features = static_cast<unsigned>(
+      OS::CpuFeaturesImpliedByPlatform()) | CpuFeaturesImpliedByCompiler();
+  ASSERT(supported_ == 0 || supported_ == standard_features);
+#ifdef DEBUG
+  initialized_ = true;
+#endif
+
+  // Get the features implied by the OS and the compiler settings. This is the
+  // minimal set of features which is also alowed for generated code in the
+  // snapshot.
+  supported_ |= standard_features;
+
+  if (Serializer::enabled()) {
+    // No probing for features if we might serialize (generate snapshot).
+    return;
+  }
+
+  // Detect whether frim instruction is supported (POWER5+)
+  // For now we will just check for processors we know do not
+  // support it
+#if !defined(_AIX)
+  if (!is_processor("ppc970") /* G5 */ && !is_processor("ppc7450") /* G4 */) {
+    // Assume support
+    supported_ |= (1u << FPU);
+  }
+#else
+  // Fallback: assume frim is supported -- will implement processor
+  // detection for other PPC platforms in is_processor() if required
+  supported_ |= (1u << FPU);
+#endif
+}
+
+Register ToRegister(int num) {
+  ASSERT(num >= 0 && num < kNumRegisters);
+  const Register kRegisters[] = {
+    r0,
+    sp,
+    r2, r3, r4, r5, r6, r7, r8, r9, r10,
+    r11, ip, r13, r14, r15,
+    r16, r17, r18, r19, r20, r21, r22, r23, r24,
+    r25, r26, r27, r28, r29, r30, fp
+  };
+  return kRegisters[num];
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of RelocInfo
+
+const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE;
+
+
+bool RelocInfo::IsCodedSpecially() {
+  // The deserializer needs to know whether a pointer is specially
+  // coded.  Being specially coded on PPC means that it is a lis/ori
+  // instruction sequence, and that is always the case inside code
+  // objects.
+  return true;
+}
+
+
+void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
+  // Patch the code at the current address with the supplied instructions.
+  Instr* pc = reinterpret_cast<Instr*>(pc_);
+  Instr* instr = reinterpret_cast<Instr*>(instructions);
+  for (int i = 0; i < instruction_count; i++) {
+    *(pc + i) = *(instr + i);
+  }
+
+  // Indicate that code has changed.
+  CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
+}
+
+
+// Patch the code at the current PC with a call to the target address.
+// Additional guard instructions can be added if required.
+void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
+  // Patch the code at the current address with a call to the target.
+  UNIMPLEMENTED();
+}
+
+
+// -----------------------------------------------------------------------------
+// Implementation of Operand and MemOperand
+// See assembler-ppc-inl.h for inlined constructors
+
+Operand::Operand(Handle<Object> handle) {
+  rm_ = no_reg;
+  // Verify all Objects referred by code are NOT in new space.
+  Object* obj = *handle;
+  ASSERT(!HEAP->InNewSpace(obj));
+  if (obj->IsHeapObject()) {
+    imm_ = reinterpret_cast<intptr_t>(handle.location());
+    rmode_ = RelocInfo::EMBEDDED_OBJECT;
+  } else {
+    // no relocation needed
+    imm_ =  reinterpret_cast<intptr_t>(obj);
+    rmode_ = RelocInfo::NONE;
+  }
+}
+
+MemOperand::MemOperand(Register rn, int32_t offset) {
+  ra_ = rn;
+  rb_ = no_reg;
+  offset_ = offset;
+}
+
+MemOperand::MemOperand(Register ra, Register rb) {
+  ra_ = ra;
+  rb_ = rb;
+  offset_ = 0;
+}
+
+// -----------------------------------------------------------------------------
+// Specific instructions, constants, and masks.
+
+// Spare buffer.
+static const int kMinimalBufferSize = 4*KB;
+
+
+Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
+    : AssemblerBase(arg_isolate),
+      recorded_ast_id_(TypeFeedbackId::None()),
+      positions_recorder_(this),
+      emit_debug_code_(FLAG_debug_code),
+      predictable_code_size_(false) {
+  if (buffer == NULL) {
+    // Do our own buffer management.
+    if (buffer_size <= kMinimalBufferSize) {
+      buffer_size = kMinimalBufferSize;
+
+      if (isolate()->assembler_spare_buffer() != NULL) {
+        buffer = isolate()->assembler_spare_buffer();
+        isolate()->set_assembler_spare_buffer(NULL);
+      }
+    }
+    if (buffer == NULL) {
+      buffer_ = NewArray<byte>(buffer_size);
+    } else {
+      buffer_ = static_cast<byte*>(buffer);
+    }
+    buffer_size_ = buffer_size;
+    own_buffer_ = true;
+
+  } else {
+    // Use externally provided buffer instead.
+    ASSERT(buffer_size > 0);
+    buffer_ = static_cast<byte*>(buffer);
+    buffer_size_ = buffer_size;
+    own_buffer_ = false;
+  }
+
+  // Set up buffer pointers.
+  ASSERT(buffer_ != NULL);
+  pc_ = buffer_;
+  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
+
+  no_trampoline_pool_before_ = 0;
+  trampoline_pool_blocked_nesting_ = 0;
+  // We leave space (kMaxBlockTrampolineSectionSize)
+  // for BlockTrampolinePoolScope buffer.
+  next_buffer_check_ = kMaxCondBranchReach - kMaxBlockTrampolineSectionSize;
+  internal_trampoline_exception_ = false;
+  last_bound_pos_ = 0;
+
+  trampoline_emitted_ = false;
+  unbound_labels_count_ = 0;
+
+  ClearRecordedAstId();
+}
+
+
+Assembler::~Assembler() {
+  if (own_buffer_) {
+    if (isolate()->assembler_spare_buffer() == NULL &&
+        buffer_size_ == kMinimalBufferSize) {
+      isolate()->set_assembler_spare_buffer(buffer_);
+    } else {
+      DeleteArray(buffer_);
+    }
+  }
+}
+
+
+void Assembler::GetCode(CodeDesc* desc) {
+  // Set up code descriptor.
+  desc->buffer = buffer_;
+  desc->buffer_size = buffer_size_;
+  desc->instr_size = pc_offset();
+  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
+}
+
+
+void Assembler::Align(int m) {
+  ASSERT(m >= 4 && IsPowerOf2(m));
+  while ((pc_offset() & (m - 1)) != 0) {
+    nop();
+  }
+}
+
+
+void Assembler::CodeTargetAlign() {
+  Align(8);
+}
+
+
+Condition Assembler::GetCondition(Instr instr) {
+  switch (instr & kCondMask) {
+    case BT:
+      return eq;
+    case BF:
+      return ne;
+    default:
+      UNIMPLEMENTED();
+    }
+  return al;
+}
+
+// PowerPC
+
+bool Assembler::IsLis(Instr instr) {
+  return (instr & kOpcodeMask) == ADDIS;
+}
+
+bool Assembler::IsAddic(Instr instr) {
+  return (instr & kOpcodeMask) == ADDIC;
+}
+
+bool Assembler::IsOri(Instr instr) {
+  return (instr & kOpcodeMask) == ORI;
+}
+
+
+bool Assembler::IsBranch(Instr instr) {
+  return ((instr & kOpcodeMask) == BCX);
+}
+
+// end PowerPC
+
+Register Assembler::GetRA(Instr instr) {
+  Register reg;
+  reg.code_ = Instruction::RAValue(instr);
+  return reg;
+}
+
+Register Assembler::GetRB(Instr instr) {
+  Register reg;
+  reg.code_ = Instruction::RBValue(instr);
+  return reg;
+}
+
+#if V8_TARGET_ARCH_PPC64
+// This code assumes a FIXED_SEQUENCE for 64bit loads (lis/ori)
+bool Assembler::Is64BitLoadIntoR12(Instr instr1, Instr instr2,
+                             Instr instr3, Instr instr4, Instr instr5) {
+  // Check the instructions are indeed a five part load (into r12)
+  // 3d800000       lis     r12, 0
+  // 618c0000       ori     r12, r12, 0
+  // 798c07c6       rldicr  r12, r12, 32, 31
+  // 658c00c3       oris    r12, r12, 195
+  // 618ccd40       ori     r12, r12, 52544
+  return(((instr1 >> 16) == 0x3d80) && ((instr2 >> 16) == 0x618c) &&
+         (instr3 == 0x798c07c6) &&
+         ((instr4 >> 16) == 0x658c) && ((instr5 >> 16) == 0x618c));
+}
+#else
+// This code assumes a FIXED_SEQUENCE for 32bit loads (lis/ori)
+bool Assembler::Is32BitLoadIntoR12(Instr instr1, Instr instr2) {
+  // Check the instruction is indeed a two part load (into r12)
+  // 3d802553       lis     r12, 9555
+  // 618c5000       ori   r12, r12, 20480
+  return(((instr1 >> 16) == 0x3d80) && ((instr2 >> 16) == 0x618c));
+}
+#endif
+
+bool Assembler::IsCmpRegister(Instr instr) {
+  return (((instr & kOpcodeMask) == EXT2) &&
+          ((instr & kExt2OpcodeMask) == CMP));
+}
+
+bool Assembler::IsRlwinm(Instr instr) {
+  return ((instr & kOpcodeMask) == RLWINMX);
+}
+
+#if V8_TARGET_ARCH_PPC64
+bool Assembler::IsRldicl(Instr instr) {
+  return (((instr & kOpcodeMask) == EXT5) &&
+          ((instr & kExt5OpcodeMask) == RLDICL));
+}
+#endif
+
+bool Assembler::IsCmpImmediate(Instr instr) {
+  return ((instr & kOpcodeMask) == CMPI);
+}
+
+Register Assembler::GetCmpImmediateRegister(Instr instr) {
+  ASSERT(IsCmpImmediate(instr));
+  return GetRA(instr);
+}
+
+int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
+  ASSERT(IsCmpImmediate(instr));
+  return instr & kOff16Mask;
+}
+
+// Labels refer to positions in the (to be) generated code.
+// There are bound, linked, and unused labels.
+//
+// Bound labels refer to known positions in the already
+// generated code. pos() is the position the label refers to.
+//
+// Linked labels refer to unknown positions in the code
+// to be generated; pos() is the position of the last
+// instruction using the label.
+
+
+// The link chain is terminated by a negative code position (must be aligned)
+const int kEndOfChain = -4;
+
+
+int Assembler::target_at(int pos)  {
+  Instr instr = instr_at(pos);
+  // check which type of branch this is 16 or 26 bit offset
+  int opcode = instr & kOpcodeMask;
+  if (BX == opcode) {
+    int imm26 = ((instr & kImm26Mask) << 6) >> 6;
+    imm26 &= ~(kAAMask|kLKMask);  // discard AA|LK bits if present
+    if (imm26 == 0)
+        return kEndOfChain;
+    return pos + imm26;
+  } else if (BCX == opcode) {
+    int imm16 = SIGN_EXT_IMM16((instr & kImm16Mask));
+    imm16 &= ~(kAAMask|kLKMask);  // discard AA|LK bits if present
+    if (imm16 == 0)
+        return kEndOfChain;
+    return pos + imm16;
+  } else if ((instr & ~kImm16Mask) == 0) {
+    // Emitted label constant, not part of a branch (regexp PushBacktrack).
+     if (instr == 0) {
+       return kEndOfChain;
+     } else {
+       int32_t imm16 = SIGN_EXT_IMM16(instr);
+       return (imm16 + pos);
+     }
+  }
+
+  PPCPORT_UNIMPLEMENTED();
+  ASSERT(false);
+  return -1;
+}
+
+void Assembler::target_at_put(int pos, int target_pos) {
+  Instr instr = instr_at(pos);
+  int opcode = instr & kOpcodeMask;
+
+  // check which type of branch this is 16 or 26 bit offset
+  if (BX == opcode) {
+    int imm26 = target_pos - pos;
+    ASSERT((imm26 & (kAAMask|kLKMask)) == 0);
+    instr &= ((~kImm26Mask)|kAAMask|kLKMask);
+    ASSERT(is_int26(imm26));
+    instr_at_put(pos, instr | (imm26 & kImm26Mask));
+    return;
+  } else if (BCX == opcode) {
+    int imm16 = target_pos - pos;
+    ASSERT((imm16 & (kAAMask|kLKMask)) == 0);
+    instr &= ((~kImm16Mask)|kAAMask|kLKMask);
+    ASSERT(is_int16(imm16));
+    instr_at_put(pos, instr | (imm16 & kImm16Mask));
+    return;
+  } else if ((instr & ~kImm16Mask) == 0) {
+    ASSERT(target_pos == kEndOfChain || target_pos >= 0);
+    // Emitted label constant, not part of a branch.
+    // Make label relative to Code* of generated Code object.
+    instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
+    return;
+  }
+
+  ASSERT(false);
+}
+
+int Assembler::max_reach_from(int pos) {
+  Instr instr = instr_at(pos);
+  int opcode = instr & kOpcodeMask;
+
+  // check which type of branch this is 16 or 26 bit offset
+  if (BX == opcode) {
+    return 26;
+  } else if (BCX == opcode) {
+    return 16;
+  } else if ((instr & ~kImm16Mask) == 0) {
+    // Emitted label constant, not part of a branch (regexp PushBacktrack).
+    return 16;
+  }
+
+  ASSERT(false);
+  return 0;
+}
+
+void Assembler::bind_to(Label* L, int pos) {
+  ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
+  int32_t trampoline_pos = kInvalidSlotPos;
+  if (L->is_linked() && !trampoline_emitted_) {
+    unbound_labels_count_--;
+    next_buffer_check_ += kTrampolineSlotsSize;
+  }
+
+  while (L->is_linked()) {
+    int fixup_pos = L->pos();
+    int32_t offset = pos - fixup_pos;
+    int maxReach = max_reach_from(fixup_pos);
+    next(L);  // call next before overwriting link with target at fixup_pos
+    if (is_intn(offset, maxReach) == false) {
+      if (trampoline_pos == kInvalidSlotPos) {
+        trampoline_pos = get_trampoline_entry();
+        CHECK(trampoline_pos != kInvalidSlotPos);
+        target_at_put(trampoline_pos, pos);
+      }
+      target_at_put(fixup_pos, trampoline_pos);
+    } else {
+      target_at_put(fixup_pos, pos);
+    }
+  }
+  L->bind_to(pos);
+
+  // Keep track of the last bound label so we don't eliminate any instructions
+  // before a bound label.
+  if (pos > last_bound_pos_)
+    last_bound_pos_ = pos;
+}
+
+void Assembler::bind(Label* L) {
+  ASSERT(!L->is_bound());  // label can only be bound once
+  bind_to(L, pc_offset());
+}
+
+
+void Assembler::next(Label* L) {
+  ASSERT(L->is_linked());
+  int link = target_at(L->pos());
+  if (link == kEndOfChain) {
+    L->Unuse();
+  } else {
+    ASSERT(link >= 0);
+    L->link_to(link);
+  }
+}
+
+bool Assembler::is_near(Label* L, Condition cond) {
+  ASSERT(L->is_bound());
+  if (L->is_bound() == false)
+    return false;
+
+  int maxReach = ((cond == al) ? 26 : 16);
+  int offset = L->pos() - pc_offset();
+
+  return is_intn(offset, maxReach);
+}
+
+void Assembler::a_form(Instr instr,
+                       DwVfpRegister frt,
+                       DwVfpRegister fra,
+                       DwVfpRegister frb,
+                       RCBit r) {
+  emit(instr | frt.code()*B21 | fra.code()*B16 | frb.code()*B11 | r);
+}
+
+void Assembler::d_form(Instr instr,
+                        Register rt,
+                        Register ra,
+                        const intptr_t val,
+                        bool signed_disp) {
+  if (signed_disp) {
+    if (!is_int16(val)) {
+      PrintF("val = %" V8PRIdPTR ", 0x%" V8PRIxPTR "\n", val, val);
+    }
+    ASSERT(is_int16(val));
+  } else {
+    if (!is_uint16(val)) {
+      PrintF("val = %" V8PRIdPTR ", 0x%" V8PRIxPTR
+             ", is_unsigned_imm16(val)=%d, kImm16Mask=0x%x\n",
+             val, val, is_uint16(val), kImm16Mask);
+    }
+    ASSERT(is_uint16(val));
+  }
+  emit(instr | rt.code()*B21 | ra.code()*B16 | (kImm16Mask & val));
+}
+
+void Assembler::x_form(Instr instr,
+                         Register ra,
+                         Register rs,
+                         Register rb,
+                         RCBit r) {
+  emit(instr | rs.code()*B21 | ra.code()*B16 | rb.code()*B11 | r);
+}
+
+void Assembler::xo_form(Instr instr,
+                         Register rt,
+                         Register ra,
+                         Register rb,
+                         OEBit o,
+                         RCBit r) {
+  emit(instr | rt.code()*B21 | ra.code()*B16 | rb.code()*B11 | o | r);
+}
+
+void Assembler::md_form(Instr instr,
+                        Register ra,
+                        Register rs,
+                        int shift,
+                        int maskbit,
+                        RCBit r) {
+  int sh0_4 = shift & 0x1f;
+  int sh5   = (shift >> 5) & 0x1;
+  int m0_4  = maskbit & 0x1f;
+  int m5    = (maskbit >> 5) & 0x1;
+
+  emit(instr | rs.code()*B21 | ra.code()*B16 |
+       sh0_4*B11 | m0_4*B6 | m5*B5 | sh5*B1 | r);
+}
+
+// Returns the next free trampoline entry.
+int32_t Assembler::get_trampoline_entry() {
+  int32_t trampoline_entry = kInvalidSlotPos;
+
+  if (!internal_trampoline_exception_) {
+    trampoline_entry = trampoline_.take_slot();
+
+    if (kInvalidSlotPos == trampoline_entry) {
+      internal_trampoline_exception_ = true;
+    }
+  }
+  return trampoline_entry;
+}
+
+int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
+  int target_pos;
+  if (L->is_bound()) {
+    target_pos = L->pos();
+  } else {
+    if (L->is_linked()) {
+      target_pos = L->pos();  // L's link
+    } else {
+      // was: target_pos = kEndOfChain;
+      // However, using branch to self to mark the first reference
+      // should avoid most instances of branch offset overflow.  See
+      // target_at() for where this is converted back to kEndOfChain.
+      target_pos = pc_offset();
+      if (!trampoline_emitted_) {
+        unbound_labels_count_++;
+        next_buffer_check_ -= kTrampolineSlotsSize;
+      }
+    }
+    L->link_to(pc_offset());
+  }
+
+  return target_pos - pc_offset();
+}
+
+
+void Assembler::label_at_put(Label* L, int at_offset) {
+  int target_pos;
+  if (L->is_bound()) {
+    target_pos = L->pos();
+    instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
+  } else {
+    if (L->is_linked()) {
+      target_pos = L->pos();  // L's link
+    } else {
+      // was: target_pos = kEndOfChain;
+      // However, using branch to self to mark the first reference
+      // should avoid most instances of branch offset overflow.  See
+      // target_at() for where this is converted back to kEndOfChain.
+      target_pos = at_offset;
+      if (!trampoline_emitted_) {
+        unbound_labels_count_++;
+        next_buffer_check_ -= kTrampolineSlotsSize;
+      }
+    }
+    L->link_to(at_offset);
+
+    Instr constant = target_pos - at_offset;
+    ASSERT(is_int16(constant));
+    instr_at_put(at_offset, constant);
+  }
+}
+
+
+// Branch instructions.
+
+// PowerPC
+void Assembler::bclr(BOfield bo, LKBit lk) {
+  positions_recorder()->WriteRecordedPositions();
+  emit(EXT1 | bo | BCLRX | lk);
+}
+
+void Assembler::bcctr(BOfield bo, LKBit lk) {
+  positions_recorder()->WriteRecordedPositions();
+  emit(EXT1 | bo | BCCTRX | lk);
+}
+
+// Pseudo op - branch to link register
+void Assembler::blr() {
+  bclr(BA, LeaveLK);
+}
+
+// Pseudo op - branch to count register -- used for "jump"
+void Assembler::bcr() {
+  bcctr(BA, LeaveLK);
+}
+
+void Assembler::bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk) {
+  positions_recorder()->WriteRecordedPositions();
+  ASSERT(is_int16(branch_offset));
+  emit(BCX | bo | condition_bit*B16 | (kImm16Mask & branch_offset) | lk);
+}
+
+void Assembler::b(int branch_offset, LKBit lk) {
+  positions_recorder()->WriteRecordedPositions();
+  ASSERT((branch_offset & 3) == 0);
+  int imm26 = branch_offset;
+  ASSERT(is_int26(imm26));
+  // todo add AA and LK bits
+  emit(BX | (imm26 & kImm26Mask) | lk);
+}
+
+void Assembler::xori(Register dst, Register src, const Operand& imm) {
+  d_form(XORI, src, dst, imm.imm_, false);
+}
+
+void Assembler::xoris(Register ra, Register rs, const Operand& imm) {
+  d_form(XORIS, rs, ra, imm.imm_, false);
+}
+
+void Assembler::xor_(Register dst, Register src1, Register src2, RCBit rc) {
+  x_form(EXT2 | XORX, dst, src1, src2, rc);
+}
+
+void Assembler::cntlzw_(Register ra, Register rs, RCBit rc) {
+  x_form(EXT2 | CNTLZWX, ra, rs, r0, rc);
+}
+
+void Assembler::and_(Register ra, Register rs, Register rb, RCBit rc) {
+  x_form(EXT2 | ANDX, ra, rs, rb, rc);
+}
+
+
+void Assembler::rlwinm(Register ra, Register rs,
+                       int sh, int mb, int me, RCBit rc) {
+  sh &= 0x1f;
+  mb &= 0x1f;
+  me &= 0x1f;
+  emit(RLWINMX | rs.code()*B21 | ra.code()*B16 | sh*B11 | mb*B6 | me << 1 | rc);
+}
+
+void Assembler::rlwimi(Register ra, Register rs,
+                       int sh, int mb, int me, RCBit rc) {
+  sh &= 0x1f;
+  mb &= 0x1f;
+  me &= 0x1f;
+  emit(RLWIMIX | rs.code()*B21 | ra.code()*B16 | sh*B11 | mb*B6 | me << 1 | rc);
+}
+
+void Assembler::slwi(Register dst, Register src, const Operand& val,
+                     RCBit rc) {
+  ASSERT((32 > val.imm_)&&(val.imm_ >= 0));
+  rlwinm(dst, src, val.imm_, 0, 31-val.imm_, rc);
+}
+void Assembler::srwi(Register dst, Register src, const Operand& val,
+                     RCBit rc) {
+  ASSERT((32 > val.imm_)&&(val.imm_ >= 0));
+  rlwinm(dst, src, 32-val.imm_, val.imm_, 31, rc);
+}
+void Assembler::clrrwi(Register dst, Register src, const Operand& val,
+                       RCBit rc) {
+  ASSERT((32 > val.imm_)&&(val.imm_ >= 0));
+  rlwinm(dst, src, 0, 0, 31-val.imm_, rc);
+}
+void Assembler::clrlwi(Register dst, Register src, const Operand& val,
+                       RCBit rc) {
+  ASSERT((32 > val.imm_)&&(val.imm_ >= 0));
+  rlwinm(dst, src, 0, val.imm_, 31, rc);
+}
+
+
+void Assembler::srawi(Register ra, Register rs, int sh, RCBit r) {
+  emit(EXT2 | SRAWIX | rs.code()*B21 | ra.code()*B16 | sh*B11 | r);
+}
+
+void Assembler::srw(Register dst, Register src1, Register src2, RCBit r) {
+  x_form(EXT2 | SRWX, dst, src1, src2, r);
+}
+
+void Assembler::slw(Register dst, Register src1, Register src2, RCBit r) {
+  x_form(EXT2 | SLWX, dst, src1, src2, r);
+}
+
+void Assembler::sraw(Register ra, Register rs, Register rb, RCBit r) {
+  x_form(EXT2 | SRAW, ra, rs, rb, r);
+}
+
+void Assembler::subi(Register dst, Register src, const Operand& imm) {
+  addi(dst, src, Operand(-(imm.imm_)));
+}
+
+void Assembler::addc(Register dst, Register src1, Register src2,
+                    OEBit o, RCBit r) {
+  xo_form(EXT2 | ADDCX, dst, src1, src2, o, r);
+}
+
+void Assembler::addze(Register dst, Register src1, OEBit o, RCBit r) {
+  // a special xo_form
+  emit(EXT2 | ADDZEX | dst.code()*B21 | src1.code()*B16 | o | r);
+}
+
+void Assembler::sub(Register dst, Register src1, Register src2,
+                    OEBit o, RCBit r) {
+  xo_form(EXT2 | SUBFX, dst, src2, src1, o, r);
+}
+
+void Assembler::subfc(Register dst, Register src1, Register src2,
+                    OEBit o, RCBit r) {
+  xo_form(EXT2 | SUBFCX, dst, src2, src1, o, r);
+}
+
+void Assembler::subfic(Register dst, Register src, const Operand& imm) {
+  d_form(SUBFIC, dst, src, imm.imm_, true);
+}
+
+void Assembler::add(Register dst, Register src1, Register src2,
+                    OEBit o, RCBit r) {
+  xo_form(EXT2 | ADDX, dst, src1, src2, o, r);
+}
+
+// Multiply low word
+void Assembler::mullw(Register dst, Register src1, Register src2,
+                    OEBit o, RCBit r) {
+  xo_form(EXT2 | MULLW, dst, src1, src2, o, r);
+}
+
+// Multiply hi word
+void Assembler::mulhw(Register dst, Register src1, Register src2,
+                    OEBit o, RCBit r) {
+  xo_form(EXT2 | MULHWX, dst, src1, src2, o, r);
+}
+
+// Divide word
+void Assembler::divw(Register dst, Register src1, Register src2,
+                     OEBit o, RCBit r) {
+  xo_form(EXT2 | DIVW, dst, src1, src2, o, r);
+}
+
+void Assembler::addi(Register dst, Register src, const Operand& imm) {
+  ASSERT(!src.is(r0));  // use li instead to show intent
+  d_form(ADDI, dst, src, imm.imm_, true);
+}
+
+void  Assembler::addis(Register dst, Register src, const Operand& imm) {
+  ASSERT(!src.is(r0));  // use lis instead to show intent
+  d_form(ADDIS, dst, src, imm.imm_, true);
+}
+
+void Assembler::addic(Register dst, Register src, const Operand& imm) {
+  d_form(ADDIC, dst, src, imm.imm_, true);
+}
+
+void  Assembler::andi(Register ra, Register rs, const Operand& imm) {
+  d_form(ANDIx, rs, ra, imm.imm_, false);
+}
+
+void Assembler::andis(Register ra, Register rs, const Operand& imm) {
+  d_form(ANDISx, rs, ra, imm.imm_, false);
+}
+
+void Assembler::nor(Register dst, Register src1, Register src2, RCBit r) {
+  x_form(EXT2 | NORX, dst, src1, src2, r);
+}
+
+void Assembler::notx(Register dst, Register src, RCBit r) {
+  x_form(EXT2 | NORX, dst, src, src, r);
+}
+
+void Assembler::ori(Register ra, Register rs, const Operand& imm) {
+  d_form(ORI, rs, ra, imm.imm_, false);
+}
+
+void Assembler::oris(Register dst, Register src, const Operand& imm) {
+  d_form(ORIS, src, dst, imm.imm_, false);
+}
+
+void Assembler::orx(Register dst, Register src1, Register src2, RCBit rc) {
+  x_form(EXT2 | ORX, dst, src1, src2, rc);
+}
+
+void Assembler::cmpi(Register src1, const Operand& src2, CRegister cr) {
+  intptr_t imm16 = src2.imm_;
+#if V8_TARGET_ARCH_PPC64
+  int L = 1;
+#else
+  int L = 0;
+#endif
+  ASSERT(is_int16(imm16));
+  ASSERT(cr.code() >= 0 && cr.code() <= 7);
+  imm16 &= kImm16Mask;
+  emit(CMPI | cr.code()*B23 | L*B21 | src1.code()*B16 | imm16);
+}
+
+void Assembler::cmpli(Register src1, const Operand& src2, CRegister cr) {
+  uintptr_t uimm16 = src2.imm_;
+#if V8_TARGET_ARCH_PPC64
+  int L = 1;
+#else
+  int L = 0;
+#endif
+  ASSERT(is_uint16(uimm16));
+  ASSERT(cr.code() >= 0 && cr.code() <= 7);
+  uimm16 &= kImm16Mask;
+  emit(CMPLI | cr.code()*B23 | L*B21 | src1.code()*B16 | uimm16);
+}
+
+void Assembler::cmp(Register src1, Register src2, CRegister cr) {
+#if V8_TARGET_ARCH_PPC64
+  int L = 1;
+#else
+  int L = 0;
+#endif
+  ASSERT(cr.code() >= 0 && cr.code() <= 7);
+  emit(EXT2 | CMP | cr.code()*B23 | L*B21 | src1.code()*B16 |
+       src2.code()*B11);
+}
+
+void Assembler::cmpl(Register src1, Register src2, CRegister cr) {
+#if V8_TARGET_ARCH_PPC64
+  int L = 1;
+#else
+  int L = 0;
+#endif
+  ASSERT(cr.code() >= 0 && cr.code() <= 7);
+  emit(EXT2 | CMPL | cr.code()*B23 | L*B21 | src1.code()*B16 |
+       src2.code()*B11);
+}
+
+// Pseudo op - load immediate
+void Assembler::li(Register dst, const Operand &imm) {
+  d_form(ADDI, dst, r0, imm.imm_, true);
+}
+
+void  Assembler::lis(Register dst, const Operand& imm) {
+  d_form(ADDIS, dst, r0, imm.imm_, true);
+}
+
+// Pseudo op - move register
+void Assembler::mr(Register dst, Register src) {
+  // actually or(dst, src, src)
+  orx(dst, src, src);
+}
+
+void Assembler::lbz(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(LBZ, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::lbzx(Register rt, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LBZX | rt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lbzux(Register rt, const MemOperand & src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LBZUX | rt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lhz(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(LHZ, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::lhzx(Register rt, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LHZX | rt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lhzux(Register rt, const MemOperand & src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LHZUX | rt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lwz(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(LWZ, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::lwzu(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(LWZU, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::lwzx(Register rt, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LWZX | rt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lwzux(Register rt, const MemOperand & src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LWZUX | rt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lwa(Register dst, const MemOperand &src) {
+#if V8_TARGET_ARCH_PPC64
+  int offset = src.offset();
+  ASSERT(!src.ra_.is(r0));
+  ASSERT(!(offset & 3) && is_int16(offset));
+  offset = kImm16Mask & offset;
+  emit(LD | dst.code()*B21 | src.ra().code()*B16 | offset | 2);
+#else
+  lwz(dst, src);
+#endif
+}
+
+void Assembler::stb(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(STB, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::stbx(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STBX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::stbux(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STBUX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::sth(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(STH, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::sthx(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STHX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::sthux(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STHUX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::stw(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(STW, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::stwu(Register dst, const MemOperand &src) {
+  ASSERT(!src.ra_.is(r0));
+  d_form(STWU, dst, src.ra(), src.offset(), true);
+}
+
+void Assembler::stwx(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STWX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::stwux(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STWUX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::extsb(Register rs, Register ra, RCBit rc) {
+  emit(EXT2 | EXTSB | ra.code()*B21 | rs.code()*B16 | rc);
+}
+
+void Assembler::extsh(Register rs, Register ra, RCBit rc) {
+  emit(EXT2 | EXTSH | ra.code()*B21 | rs.code()*B16 | rc);
+}
+
+void Assembler::neg(Register rt, Register ra, OEBit o, RCBit r) {
+  emit(EXT2 | NEGX | rt.code()*B21 | ra.code()*B16 | o | r);
+}
+
+void Assembler::andc(Register dst, Register src1, Register src2, RCBit rc) {
+  x_form(EXT2 | ANDCX, dst, src1, src2, rc);
+}
+
+#if V8_TARGET_ARCH_PPC64
+// 64bit specific instructions
+void Assembler::ld(Register rd, const MemOperand &src) {
+  int offset = src.offset();
+  ASSERT(!src.ra_.is(r0));
+  ASSERT(!(offset & 3) && is_int16(offset));
+  offset = kImm16Mask & offset;
+  emit(LD | rd.code()*B21 | src.ra().code()*B16 | offset);
+}
+
+void Assembler::ldx(Register rd, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LDX | rd.code()*B21 | ra.code()*B16 | rb.code()*B11);
+}
+
+void Assembler::ldu(Register rd, const MemOperand &src) {
+  int offset = src.offset();
+  ASSERT(!src.ra_.is(r0));
+  ASSERT(!(offset & 3) && is_int16(offset));
+  offset = kImm16Mask & offset;
+  emit(LD | rd.code()*B21 | src.ra().code()*B16 | offset | 1);
+}
+
+void Assembler::ldux(Register rd, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LDUX | rd.code()*B21 | ra.code()*B16 | rb.code()*B11);
+}
+
+void Assembler::std(Register rs, const MemOperand &src) {
+  int offset = src.offset();
+  ASSERT(!src.ra_.is(r0));
+  ASSERT(!(offset & 3) && is_int16(offset));
+  offset = kImm16Mask & offset;
+  emit(STD | rs.code()*B21 | src.ra().code()*B16 | offset);
+}
+
+void Assembler::stdx(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STDX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11);
+}
+
+void Assembler::stdu(Register rs, const MemOperand &src) {
+  int offset = src.offset();
+  ASSERT(!src.ra_.is(r0));
+  ASSERT(!(offset & 3) && is_int16(offset));
+  offset = kImm16Mask & offset;
+  emit(STD | rs.code()*B21 | src.ra().code()*B16 | offset | 1);
+}
+
+void Assembler::stdux(Register rs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STDUX | rs.code()*B21 | ra.code()*B16 | rb.code()*B11);
+}
+
+void Assembler::rldic(Register ra, Register rs, int sh, int mb, RCBit r) {
+  md_form(EXT5 | RLDIC, ra, rs, sh, mb, r);
+}
+
+void Assembler::rldicl(Register ra, Register rs, int sh, int mb, RCBit r) {
+  md_form(EXT5 | RLDICL, ra, rs, sh, mb, r);
+}
+
+void Assembler::rldicr(Register ra, Register rs, int sh, int me, RCBit r) {
+  md_form(EXT5 | RLDICR, ra, rs, sh, me, r);
+}
+
+void Assembler::sldi(Register dst, Register src, const Operand& val,
+                     RCBit rc) {
+  ASSERT((64 > val.imm_)&&(val.imm_ >= 0));
+  rldicr(dst, src, val.imm_, 63-val.imm_, rc);
+}
+void Assembler::srdi(Register dst, Register src, const Operand& val,
+                     RCBit rc) {
+  ASSERT((64 > val.imm_)&&(val.imm_ >= 0));
+  rldicl(dst, src, 64-val.imm_, val.imm_, rc);
+}
+void Assembler::clrrdi(Register dst, Register src, const Operand& val,
+                       RCBit rc) {
+  ASSERT((64 > val.imm_)&&(val.imm_ >= 0));
+  rldicr(dst, src, 0, 63-val.imm_, rc);
+}
+void Assembler::clrldi(Register dst, Register src, const Operand& val,
+                       RCBit rc) {
+  ASSERT((64 > val.imm_)&&(val.imm_ >= 0));
+  rldicl(dst, src, 0, val.imm_, rc);
+}
+
+
+void Assembler::rldimi(Register ra, Register rs, int sh, int mb, RCBit r) {
+  md_form(EXT5 | RLDIMI, ra, rs, sh, mb, r);
+}
+
+
+void Assembler::sradi(Register ra, Register rs, int sh, RCBit r) {
+  int sh0_4 = sh & 0x1f;
+  int sh5   = (sh >> 5) & 0x1;
+
+  emit(EXT2 | SRADIX | rs.code()*B21 | ra.code()*B16 | sh0_4*B11 | sh5*B1 | r);
+}
+
+void Assembler::srd(Register dst, Register src1, Register src2, RCBit r) {
+  x_form(EXT2 | SRDX, dst, src1, src2, r);
+}
+
+void Assembler::sld(Register dst, Register src1, Register src2, RCBit r) {
+  x_form(EXT2 | SLDX, dst, src1, src2, r);
+}
+
+void Assembler::srad(Register ra, Register rs, Register rb, RCBit r) {
+  x_form(EXT2 | SRAD, ra, rs, rb, r);
+}
+
+void Assembler::cntlzd_(Register ra, Register rs, RCBit rc) {
+  x_form(EXT2 | CNTLZDX, ra, rs, r0, rc);
+}
+
+void Assembler::extsw(Register rs, Register ra, RCBit rc) {
+  emit(EXT2 | EXTSW | ra.code()*B21 | rs.code()*B16 | rc);
+}
+
+void Assembler::mulld(Register dst, Register src1, Register src2,
+                      OEBit o, RCBit r) {
+  xo_form(EXT2 | MULLD, dst, src1, src2, o, r);
+}
+
+void Assembler::divd(Register dst, Register src1, Register src2,
+                     OEBit o, RCBit r) {
+  xo_form(EXT2 | DIVD, dst, src1, src2, o, r);
+}
+#endif
+
+
+void Assembler::fake_asm(enum FAKE_OPCODE_T fopcode) {
+  ASSERT(fopcode < fLastFaker);
+  emit(FAKE_OPCODE | FAKER_SUBOPCODE | fopcode);
+}
+
+void Assembler::marker_asm(int mcode) {
+  if (::v8::internal::FLAG_trace_sim_stubs) {
+    ASSERT(mcode < F_NEXT_AVAILABLE_STUB_MARKER);
+    emit(FAKE_OPCODE | MARKER_SUBOPCODE | mcode);
+  }
+}
+
+// Function descriptor for AIX.
+// Code address skips the function descriptor "header".
+// TOC and static chain are ignored and set to 0.
+void Assembler::function_descriptor() {
+  RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
+#if V8_TARGET_ARCH_PPC64
+  uint64_t value = reinterpret_cast<uint64_t>(pc_) + 3 * kPointerSize;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  emit(static_cast<uint32_t>(value & 0xFFFFFFFF));
+  emit(static_cast<uint32_t>(value >> 32));
+#else
+  emit(static_cast<uint32_t>(value >> 32));
+  emit(static_cast<uint32_t>(value & 0xFFFFFFFF));
+#endif
+  emit(static_cast<Instr>(0));
+  emit(static_cast<Instr>(0));
+  emit(static_cast<Instr>(0));
+  emit(static_cast<Instr>(0));
+#else
+  emit(reinterpret_cast<Instr>(pc_) + 3 * kPointerSize);
+  emit(static_cast<Instr>(0));
+  emit(static_cast<Instr>(0));
+#endif
+}
+// end PowerPC
+
+// Primarily used for loading constants
+// This should really move to be in macro-assembler as it
+// is really a pseudo instruction
+// Some usages of this intend for a FIXED_SEQUENCE to be used
+// Todo - break this dependency so we can optimize mov() in general
+// and only use the generic version when we require a fixed sequence
+void Assembler::mov(Register dst, const Operand& src) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  if (src.rmode_ != RelocInfo::NONE) {
+    // some form of relocation needed
+    RecordRelocInfo(src.rmode_, src.imm_);
+  }
+
+#if V8_TARGET_ARCH_PPC64
+  int64_t value = src.immediate();
+  int32_t hi_32 = static_cast<int64_t>(value) >> 32;
+  int32_t lo_32 = static_cast<int32_t>(value);
+  int hi_word = static_cast<int>(hi_32) >> 16;
+  int lo_word = static_cast<int>(hi_32) & 0xFFFF;
+  lis(dst, Operand(SIGN_EXT_IMM16(hi_word)));
+  ori(dst, dst, Operand(lo_word));
+  sldi(dst, dst, Operand(32));
+  hi_word = (static_cast<int>(lo_32) >> 16) & 0xFFFF;
+  lo_word = static_cast<int>(lo_32) & 0xFFFF;
+  oris(dst, dst, Operand(hi_word));
+  ori(dst, dst, Operand(lo_word));
+#else
+  int value = src.immediate();
+  if (!is_trampoline_pool_blocked()) {
+    if (is_int16(value)) {
+      li(dst, Operand(value));
+      return;
+    }
+  }
+  int hi_word = static_cast<int>(value) >> 16;
+  int lo_word = static_cast<int>(value) & 0XFFFF;
+
+  lis(dst, Operand(SIGN_EXT_IMM16(hi_word)));
+  if ((!is_trampoline_pool_blocked()) && (lo_word == 0)) {
+    return;
+  }
+  ori(dst, dst, Operand(lo_word));
+#endif
+}
+
+// Special register instructions
+void Assembler::crxor(int bt, int ba, int bb) {
+  emit(EXT1 | CRXOR | bt*B21 | ba*B16 | bb*B11);
+}
+
+void Assembler::mflr(Register dst) {
+  emit(EXT2 | MFSPR | dst.code()*B21 | 256 << 11);   // Ignore RC bit
+}
+
+void Assembler::mtlr(Register src) {
+  emit(EXT2 | MTSPR | src.code()*B21 | 256 << 11);   // Ignore RC bit
+}
+
+void Assembler::mtctr(Register src) {
+  emit(EXT2 | MTSPR | src.code()*B21 | 288 << 11);   // Ignore RC bit
+}
+
+void Assembler::mtxer(Register src) {
+  emit(EXT2 | MTSPR | src.code()*B21 | 32 << 11);
+}
+
+void Assembler::mcrfs(int bf, int bfa) {
+  emit(EXT4 | MCRFS | bf*B23 | bfa*B18);
+}
+
+void Assembler::mfcr(Register dst) {
+  emit(EXT2 | MFCR | dst.code()*B21);
+}
+
+// end PowerPC
+
+// Exception-generating instructions and debugging support.
+// Stops with a non-negative code less than kNumOfWatchedStops support
+// enabling/disabling and a counter feature. See simulator-ppc.h .
+void Assembler::stop(const char* msg, Condition cond, int32_t code,
+                     CRegister cr) {
+  if (cond != al) {
+    Label skip;
+    b(NegateCondition(cond), &skip, cr);
+    bkpt(0);
+    bind(&skip);
+  } else {
+    bkpt(0);
+  }
+}
+
+void Assembler::bkpt(uint32_t imm16) {
+  emit(0x7d821008);
+}
+
+
+void Assembler::info(const char* msg, Condition cond, int32_t code,
+                     CRegister cr) {
+  if (::v8::internal::FLAG_trace_sim_stubs) {
+    emit(0x7d9ff808);
+#if V8_TARGET_ARCH_PPC64
+    uint64_t value = reinterpret_cast<uint64_t>(msg);
+    emit(static_cast<uint32_t>(value >> 32));
+    emit(static_cast<uint32_t>(value & 0xFFFFFFFF));
+#else
+    emit(reinterpret_cast<Instr>(msg));
+#endif
+  }
+}
+
+void Assembler::dcbf(Register ra, Register rb) {
+    emit(EXT2 | DCBF | ra.code()*B16 | rb.code()*B11);
+}
+
+void Assembler::sync() {
+    emit(EXT2 | SYNC);
+}
+
+void Assembler::icbi(Register ra, Register rb) {
+    emit(EXT2 | ICBI | ra.code()*B16 | rb.code()*B11);
+}
+
+void Assembler::isync() {
+    emit(EXT1 | ISYNC);
+}
+
+// Floating point support
+
+void Assembler::lfd(const DwVfpRegister frt, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(LFD | frt.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::lfdu(const DwVfpRegister frt, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(LFDU | frt.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::lfdx(const DwVfpRegister frt, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LFDX | frt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lfdux(const DwVfpRegister frt, const MemOperand & src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LFDUX | frt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lfs(const DwVfpRegister frt, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  ASSERT(!ra.is(r0));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(LFS | frt.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::lfsu(const DwVfpRegister frt, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  ASSERT(!ra.is(r0));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(LFSU | frt.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::lfsx(const DwVfpRegister frt, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LFSX | frt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::lfsux(const DwVfpRegister frt, const MemOperand & src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | LFSUX | frt.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::stfd(const DwVfpRegister frs, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  ASSERT(!ra.is(r0));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(STFD | frs.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::stfdu(const DwVfpRegister frs, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  ASSERT(!ra.is(r0));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(STFDU | frs.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::stfdx(const DwVfpRegister frs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STFDX | frs.code()*B21 | ra.code()*B16 | rb.code()*B11 | LeaveRC);
+}
+
+void Assembler::stfdux(const DwVfpRegister frs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STFDUX | frs.code()*B21 | ra.code()*B16 | rb.code()*B11 |LeaveRC);
+}
+
+void Assembler::stfs(const DwVfpRegister frs, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  ASSERT(!ra.is(r0));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(STFS | frs.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::stfsu(const DwVfpRegister frs, const MemOperand &src) {
+  int offset = src.offset();
+  Register ra = src.ra();
+  ASSERT(is_int16(offset));
+  ASSERT(!ra.is(r0));
+  int imm16 = offset & kImm16Mask;
+  // could be x_form instruction with some casting magic
+  emit(STFSU | frs.code()*B21 | ra.code()*B16 | imm16);
+}
+
+void Assembler::stfsx(const DwVfpRegister frs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STFSX | frs.code()*B21 | ra.code()*B16 | rb.code()*B11 |LeaveRC);
+}
+
+void Assembler::stfsux(const DwVfpRegister frs, const MemOperand &src) {
+  Register ra = src.ra();
+  Register rb = src.rb();
+  ASSERT(!ra.is(r0));
+  emit(EXT2 | STFSUX | frs.code()*B21 | ra.code()*B16 | rb.code()*B11 |LeaveRC);
+}
+
+void Assembler::fsub(const DwVfpRegister frt,
+                     const DwVfpRegister fra,
+                     const DwVfpRegister frb,
+                     RCBit rc) {
+  a_form(EXT4 | FSUB, frt, fra, frb, rc);
+}
+
+void Assembler::fadd(const DwVfpRegister frt,
+                     const DwVfpRegister fra,
+                     const DwVfpRegister frb,
+                     RCBit rc) {
+  a_form(EXT4 | FADD, frt, fra, frb, rc);
+}
+void Assembler::fmul(const DwVfpRegister frt,
+                     const DwVfpRegister fra,
+                     const DwVfpRegister frc,
+                     RCBit rc) {
+  emit(EXT4 | FMUL | frt.code()*B21 | fra.code()*B16 | frc.code()*B6 | rc);
+}
+void Assembler::fdiv(const DwVfpRegister frt,
+                     const DwVfpRegister fra,
+                     const DwVfpRegister frb,
+                     RCBit rc) {
+  a_form(EXT4 | FDIV, frt, fra, frb, rc);
+}
+
+void Assembler::fcmpu(const DwVfpRegister fra,
+                      const DwVfpRegister frb,
+                      CRegister cr) {
+  ASSERT(cr.code() >= 0 && cr.code() <= 7);
+  emit(EXT4 | FCMPU | cr.code()*B23 | fra.code()*B16 | frb.code()*B11);
+}
+
+void Assembler::fmr(const DwVfpRegister frt,
+                    const DwVfpRegister frb,
+                    RCBit rc) {
+  emit(EXT4 | FMR | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+void Assembler::fctiwz(const DwVfpRegister frt,
+                     const DwVfpRegister frb) {
+  emit(EXT4 | FCTIWZ | frt.code()*B21 | frb.code()*B11);
+}
+
+void Assembler::fctiw(const DwVfpRegister frt,
+                     const DwVfpRegister frb) {
+  emit(EXT4 | FCTIW | frt.code()*B21 | frb.code()*B11);
+}
+
+void Assembler::frim(const DwVfpRegister frt,
+                     const DwVfpRegister frb) {
+  emit(EXT4 | FRIM | frt.code()*B21 | frb.code()*B11);
+}
+
+void Assembler::frsp(const DwVfpRegister frt,
+                     const DwVfpRegister frb,
+                     RCBit rc) {
+  emit(EXT4 | FRSP | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+void Assembler::fcfid(const DwVfpRegister frt,
+                      const DwVfpRegister frb,
+                      RCBit rc) {
+  emit(EXT4 | FCFID | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+void Assembler::fctid(const DwVfpRegister frt,
+                      const DwVfpRegister frb,
+                      RCBit rc) {
+  emit(EXT4 | FCTID | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+void Assembler::fctidz(const DwVfpRegister frt,
+                      const DwVfpRegister frb,
+                      RCBit rc) {
+  emit(EXT4 | FCTIDZ | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+void Assembler::fsel(const DwVfpRegister frt, const DwVfpRegister fra,
+                     const DwVfpRegister frc, const DwVfpRegister frb,
+                     RCBit rc) {
+  emit(EXT4 | FSEL | frt.code()*B21 | fra.code()*B16 | frb.code()*B11 |
+       frc.code()*B6 | rc);
+}
+
+void Assembler::fneg(const DwVfpRegister frt,
+                     const DwVfpRegister frb,
+                     RCBit rc) {
+  emit(EXT4 | FNEG | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+void Assembler::mtfsfi(int bf, int immediate, RCBit rc) {
+  emit(EXT4 | MTFSFI | bf*B23 | immediate*B12 | rc);
+}
+
+void Assembler::mffs(const DwVfpRegister frt, RCBit rc) {
+  emit(EXT4 | MFFS | frt.code()*B21 | rc);
+}
+
+void Assembler::mtfsf(const DwVfpRegister frb, bool L,
+                      int FLM, bool W, RCBit rc) {
+  emit(EXT4 | MTFSF | frb.code()*B11 | W*B16 | FLM*B17 | L*B25 | rc);
+}
+
+void Assembler::fsqrt(const DwVfpRegister frt,
+                      const DwVfpRegister frb,
+                      RCBit rc) {
+  emit(EXT4 | FSQRT | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+void Assembler::fabs(const DwVfpRegister frt,
+                     const DwVfpRegister frb,
+                     RCBit rc) {
+  emit(EXT4 | FABS | frt.code()*B21 | frb.code()*B11 | rc);
+}
+
+// Pseudo instructions.
+void Assembler::nop(int type) {
+  switch (type) {
+    case 0:
+      ori(r0, r0, Operand::Zero());
+      break;
+    case DEBUG_BREAK_NOP:
+      ori(r3, r3, Operand::Zero());
+      break;
+    default:
+      UNIMPLEMENTED();
+  }
+}
+
+
+bool Assembler::IsNop(Instr instr, int type) {
+  ASSERT((0 == type) || (DEBUG_BREAK_NOP == type));
+  int reg = 0;
+  if (DEBUG_BREAK_NOP == type) {
+    reg = 3;
+  }
+  return instr == (ORI | reg*B21 | reg*B16);
+}
+
+// Debugging.
+void Assembler::RecordJSReturn() {
+  positions_recorder()->WriteRecordedPositions();
+  CheckBuffer();
+  RecordRelocInfo(RelocInfo::JS_RETURN);
+}
+
+
+void Assembler::RecordDebugBreakSlot() {
+  positions_recorder()->WriteRecordedPositions();
+  CheckBuffer();
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
+}
+
+
+void Assembler::RecordComment(const char* msg) {
+  if (FLAG_code_comments) {
+    CheckBuffer();
+    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
+  }
+}
+
+
+void Assembler::GrowBuffer() {
+  if (!own_buffer_) FATAL("external code buffer is too small");
+
+  // Compute new buffer size.
+  CodeDesc desc;  // the new buffer
+  if (buffer_size_ < 4*KB) {
+    desc.buffer_size = 4*KB;
+  } else if (buffer_size_ < 1*MB) {
+    desc.buffer_size = 2*buffer_size_;
+  } else {
+    desc.buffer_size = buffer_size_ + 1*MB;
+  }
+  CHECK_GT(desc.buffer_size, 0);  // no overflow
+
+  // Set up new buffer.
+  desc.buffer = NewArray<byte>(desc.buffer_size);
+
+  desc.instr_size = pc_offset();
+  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
+
+  // Copy the data.
+  intptr_t pc_delta = desc.buffer - buffer_;
+  intptr_t rc_delta = (desc.buffer + desc.buffer_size) -
+    (buffer_ + buffer_size_);
+  memmove(desc.buffer, buffer_, desc.instr_size);
+  memmove(reloc_info_writer.pos() + rc_delta,
+          reloc_info_writer.pos(), desc.reloc_size);
+
+  // Switch buffers.
+  DeleteArray(buffer_);
+  buffer_ = desc.buffer;
+  buffer_size_ = desc.buffer_size;
+  pc_ += pc_delta;
+  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
+                               reloc_info_writer.last_pc() + pc_delta);
+
+  // None of our relocation types are pc relative pointing outside the code
+  // buffer nor pc absolute pointing inside the code buffer, so there is no need
+  // to relocate any emitted relocation entries.
+
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  // Relocate runtime entries.
+  for (RelocIterator it(desc); !it.done(); it.next()) {
+    RelocInfo::Mode rmode = it.rinfo()->rmode();
+    if (rmode == RelocInfo::INTERNAL_REFERENCE) {
+      intptr_t* p = reinterpret_cast<intptr_t*>(it.rinfo()->pc());
+      if (*p != 0) {  // 0 means uninitialized.
+        *p += pc_delta;
+      }
+    }
+  }
+#endif
+}
+
+
+void Assembler::db(uint8_t data) {
+  CheckBuffer();
+  *reinterpret_cast<uint8_t*>(pc_) = data;
+  pc_ += sizeof(uint8_t);
+}
+
+
+void Assembler::dd(uint32_t data) {
+  CheckBuffer();
+  *reinterpret_cast<uint32_t*>(pc_) = data;
+  pc_ += sizeof(uint32_t);
+}
+
+
+void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
+  RelocInfo rinfo(pc_, rmode, data, NULL);
+  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
+    // Adjust code for new modes.
+    ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
+           || RelocInfo::IsJSReturn(rmode)
+           || RelocInfo::IsComment(rmode)
+           || RelocInfo::IsPosition(rmode));
+  }
+  if (rinfo.rmode() != RelocInfo::NONE) {
+    // Don't record external references unless the heap will be serialized.
+    if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
+#ifdef DEBUG
+      if (!Serializer::enabled()) {
+        Serializer::TooLateToEnableNow();
+      }
+#endif
+      if (!Serializer::enabled() && !emit_debug_code()) {
+        return;
+      }
+    }
+    ASSERT(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
+    if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
+      RelocInfo reloc_info_with_ast_id(pc_,
+                                       rmode,
+                                       RecordedAstId().ToInt(),
+                                       NULL);
+      ClearRecordedAstId();
+      reloc_info_writer.Write(&reloc_info_with_ast_id);
+    } else {
+      reloc_info_writer.Write(&rinfo);
+    }
+  }
+}
+
+
+void Assembler::BlockTrampolinePoolFor(int instructions) {
+  BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize);
+}
+
+
+void Assembler::CheckTrampolinePool() {
+  // Some small sequences of instructions must not be broken up by the
+  // insertion of a trampoline pool; such sequences are protected by setting
+  // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_,
+  // which are both checked here. Also, recursive calls to CheckTrampolinePool
+  // are blocked by trampoline_pool_blocked_nesting_.
+  if ((trampoline_pool_blocked_nesting_ > 0) ||
+      (pc_offset() < no_trampoline_pool_before_)) {
+    // Emission is currently blocked; make sure we try again as soon as
+    // possible.
+    if (trampoline_pool_blocked_nesting_ > 0) {
+      next_buffer_check_ = pc_offset() + kInstrSize;
+    } else {
+      next_buffer_check_ = no_trampoline_pool_before_;
+    }
+    return;
+  }
+
+  ASSERT(!trampoline_emitted_);
+  ASSERT(unbound_labels_count_ >= 0);
+  if (unbound_labels_count_ > 0) {
+    // First we emit jump, then we emit trampoline pool.
+    { BlockTrampolinePoolScope block_trampoline_pool(this);
+      Label after_pool;
+      b(&after_pool);
+
+      int pool_start = pc_offset();
+      for (int i = 0; i < unbound_labels_count_; i++) {
+        b(&after_pool);
+      }
+      bind(&after_pool);
+      trampoline_ = Trampoline(pool_start, unbound_labels_count_);
+
+      trampoline_emitted_ = true;
+      // As we are only going to emit trampoline once, we need to prevent any
+      // further emission.
+      next_buffer_check_ = kMaxInt;
+    }
+  } else {
+    // Number of branches to unbound label at this point is zero, so we can
+    // move next buffer check to maximum.
+    next_buffer_check_ = pc_offset() +
+      kMaxCondBranchReach - kMaxBlockTrampolineSectionSize;
+  }
+  return;
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/assembler-ppc.h b/src/ppc/assembler-ppc.h
new file mode 100644
index 0000000..95bc342
--- /dev/null
+++ b/src/ppc/assembler-ppc.h
@@ -0,0 +1,1382 @@
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistribution in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of Sun Microsystems or the names of contributors may
+// be used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2012 the V8 project authors. All rights reserved.
+
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+
+// A light-weight PPC Assembler
+// Generates user mode instructions for the PPC architecture up
+
+#ifndef V8_PPC_ASSEMBLER_PPC_H_
+#define V8_PPC_ASSEMBLER_PPC_H_
+#include <stdio.h>
+#if !defined(_AIX)
+#include <elf.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+#include "assembler.h"
+#include "constants-ppc.h"
+#include "serialize.h"
+
+#define ABI_USES_FUNCTION_DESCRIPTORS \
+  (V8_HOST_ARCH_PPC && \
+    (defined(_AIX) || \
+      (defined(V8_TARGET_ARCH_PPC64) && (__BYTE_ORDER != __LITTLE_ENDIAN))))
+
+#define ABI_PASSES_HANDLES_IN_REGS \
+  (!V8_HOST_ARCH_PPC || defined(_AIX) || defined(V8_TARGET_ARCH_PPC64))
+
+#define ABI_RETURNS_HANDLES_IN_REGS \
+  (!V8_HOST_ARCH_PPC || (__BYTE_ORDER == __LITTLE_ENDIAN))
+
+#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS \
+  (!V8_HOST_ARCH_PPC || (__BYTE_ORDER == __LITTLE_ENDIAN))
+
+#define ABI_TOC_ADDRESSABILITY_VIA_IP \
+  (V8_HOST_ARCH_PPC && defined(V8_TARGET_ARCH_PPC64) && \
+    (__BYTE_ORDER == __LITTLE_ENDIAN))
+
+namespace v8 {
+namespace internal {
+
+// CPU Registers.
+//
+// 1) We would prefer to use an enum, but enum values are assignment-
+// compatible with int, which has caused code-generation bugs.
+//
+// 2) We would prefer to use a class instead of a struct but we don't like
+// the register initialization to depend on the particular initialization
+// order (which appears to be different on OS X, Linux, and Windows for the
+// installed versions of C++ we tried). Using a struct permits C-style
+// "initialization". Also, the Register objects cannot be const as this
+// forces initialization stubs in MSVC, making us dependent on initialization
+// order.
+//
+// 3) By not using an enum, we are possibly preventing the compiler from
+// doing certain constant folds, which may significantly reduce the
+// code generated for some assembly instructions (because they boil down
+// to a few constants). If this is a problem, we could change the code
+// such that we use an enum in optimized mode, and the struct in debug
+// mode. This way we get the compile-time error checking in debug mode
+// and best performance in optimized code.
+
+// Core register
+struct Register {
+  static const int kNumRegisters = 32;
+  static const int kNumAllocatableRegisters = 8;  // r3-r10
+  static const int kSizeInBytes = 4;
+
+  static int ToAllocationIndex(Register reg) {
+    int index = reg.code() - 3;  // r0-r2 are skipped
+    ASSERT(index < kNumAllocatableRegisters);
+    return index;
+  }
+
+  static Register FromAllocationIndex(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    return from_code(index + 3);  // r0-r2 are skipped
+  }
+
+  static const char* AllocationIndexToString(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    const char* const names[] = {
+      "r3",
+      "r4",
+      "r5",
+      "r6",
+      "r7",
+      "r8",
+      "r9",
+      "r10",  // currently last allocated register
+      "r11",  // lithium scratch
+      "r12",  // ip
+      "r13",
+      "r14",
+      "r15",
+      "r16",
+      "r17",
+      "r18",
+      "r19",
+      "r20",
+      "r21",
+      "r22",
+      "r23",
+      "r24",
+      "r25",
+      "r26",
+      "r27",
+      "r28",
+      "r29",
+      "r30",
+    };
+    return names[index];
+  }
+
+  static Register from_code(int code) {
+    Register r = { code };
+    return r;
+  }
+
+  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
+  bool is(Register reg) const { return code_ == reg.code_; }
+  int code() const {
+    ASSERT(is_valid());
+    return code_;
+  }
+  int bit() const {
+    ASSERT(is_valid());
+    return 1 << code_;
+  }
+
+  void set_code(int code) {
+    code_ = code;
+    ASSERT(is_valid());
+  }
+
+  // Unfortunately we can't make this private in a struct.
+  int code_;
+};
+
+// These constants are used in several locations, including static initializers
+const int kRegister_no_reg_Code = -1;
+const int kRegister_r0_Code = 0;
+const int kRegister_sp_Code = 1;  // todo - rename to SP
+const int kRegister_r2_Code = 2;  // special on PowerPC
+const int kRegister_r3_Code = 3;
+const int kRegister_r4_Code = 4;
+const int kRegister_r5_Code = 5;
+const int kRegister_r6_Code = 6;
+const int kRegister_r7_Code = 7;
+const int kRegister_r8_Code = 8;
+const int kRegister_r9_Code = 9;
+const int kRegister_r10_Code = 10;
+const int kRegister_r11_Code = 11;
+const int kRegister_ip_Code = 12;  // todo - fix
+const int kRegister_r13_Code = 13;
+const int kRegister_r14_Code = 14;
+const int kRegister_r15_Code = 15;
+
+const int kRegister_r16_Code = 16;
+const int kRegister_r17_Code = 17;
+const int kRegister_r18_Code = 18;
+const int kRegister_r19_Code = 19;
+const int kRegister_r20_Code = 20;
+const int kRegister_r21_Code = 21;
+const int kRegister_r22_Code = 22;
+const int kRegister_r23_Code = 23;
+const int kRegister_r24_Code = 24;
+const int kRegister_r25_Code = 25;
+const int kRegister_r26_Code = 26;
+const int kRegister_r27_Code = 27;
+const int kRegister_r28_Code = 28;
+const int kRegister_r29_Code = 29;
+const int kRegister_r30_Code = 30;
+const int kRegister_fp_Code = 31;
+
+const Register no_reg = { kRegister_no_reg_Code };
+
+const Register r0  = { kRegister_r0_Code };
+const Register sp  = { kRegister_sp_Code };
+const Register r2  = { kRegister_r2_Code };
+const Register r3  = { kRegister_r3_Code };
+const Register r4  = { kRegister_r4_Code };
+const Register r5  = { kRegister_r5_Code };
+const Register r6  = { kRegister_r6_Code };
+const Register r7  = { kRegister_r7_Code };
+const Register r8  = { kRegister_r8_Code };
+const Register r9  = { kRegister_r9_Code };
+const Register r10 = { kRegister_r10_Code };
+// Used as lithium codegen scratch register.
+const Register r11 = { kRegister_r11_Code };
+const Register ip  = { kRegister_ip_Code };
+// Used as roots register.
+const Register r13  = { kRegister_r13_Code };
+const Register r14  = { kRegister_r14_Code };
+const Register r15  = { kRegister_r15_Code };
+
+const Register r16  = { kRegister_r16_Code };
+const Register r17  = { kRegister_r17_Code };
+const Register r18  = { kRegister_r18_Code };
+const Register r19  = { kRegister_r19_Code };
+// Used as context register.
+const Register r20  = { kRegister_r20_Code };
+const Register r21  = { kRegister_r21_Code };
+const Register r22  = { kRegister_r22_Code };
+const Register r23  = { kRegister_r23_Code };
+const Register r24  = { kRegister_r24_Code };
+const Register r25  = { kRegister_r25_Code };
+const Register r26  = { kRegister_r26_Code };
+const Register r27  = { kRegister_r27_Code };
+const Register r28  = { kRegister_r28_Code };
+const Register r29  = { kRegister_r29_Code };
+const Register r30  = { kRegister_r30_Code };
+const Register fp = { kRegister_fp_Code };
+
+// Double word FP register.
+struct DwVfpRegister {
+  static const int kNumRegisters = 32;
+  static const int kNumVolatileRegisters = 14;     // d0-d13
+  static const int kNumAllocatableRegisters = 12;  // d1-d12
+
+  inline static int ToAllocationIndex(DwVfpRegister reg);
+
+  static DwVfpRegister FromAllocationIndex(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    return from_code(index + 1);  // d0 is skipped
+  }
+
+  static const char* AllocationIndexToString(int index) {
+    ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+    const char* const names[] = {
+      "d1",
+      "d2",
+      "d3",
+      "d4",
+      "d5",
+      "d6",
+      "d7",
+      "d8",
+      "d9",
+      "d10",
+      "d11",
+      "d12",
+    };
+    return names[index];
+  }
+
+  static DwVfpRegister from_code(int code) {
+    DwVfpRegister r = { code };
+    return r;
+  }
+
+  // Supporting d0 to d15, can be later extended to d31.
+  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
+  bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
+
+  int code() const {
+    ASSERT(is_valid());
+    return code_;
+  }
+  int bit() const {
+    ASSERT(is_valid());
+    return 1 << code_;
+  }
+  void split_code(int* vm, int* m) const {
+    ASSERT(is_valid());
+    *m = (code_ & 0x10) >> 4;
+    *vm = code_ & 0x0F;
+  }
+
+  int code_;
+};
+
+
+typedef DwVfpRegister DoubleRegister;
+
+const DwVfpRegister no_dreg = { -1 };
+const DwVfpRegister d0  = {  0 };
+const DwVfpRegister d1  = {  1 };
+const DwVfpRegister d2  = {  2 };
+const DwVfpRegister d3  = {  3 };
+const DwVfpRegister d4  = {  4 };
+const DwVfpRegister d5  = {  5 };
+const DwVfpRegister d6  = {  6 };
+const DwVfpRegister d7  = {  7 };
+const DwVfpRegister d8  = {  8 };
+const DwVfpRegister d9  = {  9 };
+const DwVfpRegister d10 = { 10 };
+const DwVfpRegister d11 = { 11 };
+const DwVfpRegister d12 = { 12 };
+const DwVfpRegister d13 = { 13 };
+const DwVfpRegister d14 = { 14 };
+const DwVfpRegister d15 = { 15 };
+const DwVfpRegister d16 = { 16 };
+const DwVfpRegister d17 = { 17 };
+const DwVfpRegister d18 = { 18 };
+const DwVfpRegister d19 = { 19 };
+const DwVfpRegister d20 = { 20 };
+const DwVfpRegister d21 = { 21 };
+const DwVfpRegister d22 = { 22 };
+const DwVfpRegister d23 = { 23 };
+const DwVfpRegister d24 = { 24 };
+const DwVfpRegister d25 = { 25 };
+const DwVfpRegister d26 = { 26 };
+const DwVfpRegister d27 = { 27 };
+const DwVfpRegister d28 = { 28 };
+const DwVfpRegister d29 = { 29 };
+const DwVfpRegister d30 = { 30 };
+const DwVfpRegister d31 = { 31 };
+
+// Aliases for double registers.  Defined using #define instead of
+// "static const DwVfpRegister&" because Clang complains otherwise when a
+// compilation unit that includes this header doesn't use the variables.
+#define kFirstCalleeSavedDoubleReg d14
+#define kLastCalleeSavedDoubleReg d31
+#define kDoubleRegZero d14
+#define kScratchDoubleReg d13
+
+Register ToRegister(int num);
+
+// Coprocessor register
+struct CRegister {
+  bool is_valid() const { return 0 <= code_ && code_ < 16; }
+  bool is(CRegister creg) const { return code_ == creg.code_; }
+  int code() const {
+    ASSERT(is_valid());
+    return code_;
+  }
+  int bit() const {
+    ASSERT(is_valid());
+    return 1 << code_;
+  }
+
+  // Unfortunately we can't make this private in a struct.
+  int code_;
+};
+
+
+const CRegister no_creg = { -1 };
+
+const CRegister cr0  = {  0 };
+const CRegister cr1  = {  1 };
+const CRegister cr2  = {  2 };
+const CRegister cr3  = {  3 };
+const CRegister cr4  = {  4 };
+const CRegister cr5  = {  5 };
+const CRegister cr6  = {  6 };
+const CRegister cr7  = {  7 };
+const CRegister cr8  = {  8 };
+const CRegister cr9  = {  9 };
+const CRegister cr10 = { 10 };
+const CRegister cr11 = { 11 };
+const CRegister cr12 = { 12 };
+const CRegister cr13 = { 13 };
+const CRegister cr14 = { 14 };
+const CRegister cr15 = { 15 };
+
+// -----------------------------------------------------------------------------
+// Machine instruction Operands
+
+// Class Operand represents a shifter operand in data processing instructions
+class Operand BASE_EMBEDDED {
+ public:
+  // immediate
+  INLINE(explicit Operand(intptr_t immediate,
+         RelocInfo::Mode rmode = RelocInfo::NONE));
+  INLINE(static Operand Zero()) {
+    return Operand(static_cast<intptr_t>(0));
+  }
+  INLINE(explicit Operand(const ExternalReference& f));
+  explicit Operand(Handle<Object> handle);
+  INLINE(explicit Operand(Smi* value));
+
+  // rm
+  INLINE(explicit Operand(Register rm));
+
+  // Return true if this is a register operand.
+  INLINE(bool is_reg() const);
+
+  inline intptr_t immediate() const {
+    ASSERT(!rm_.is_valid());
+    return imm_;
+  }
+
+  Register rm() const { return rm_; }
+
+ private:
+  Register rm_;
+  intptr_t imm_;  // valid if rm_ == no_reg
+  RelocInfo::Mode rmode_;
+
+  friend class Assembler;
+  friend class MacroAssembler;
+};
+
+
+// Class MemOperand represents a memory operand in load and store instructions
+// On PowerPC we have base register + 16bit signed value
+// Alternatively we can have a 16bit signed value immediate
+class MemOperand BASE_EMBEDDED {
+ public:
+  explicit MemOperand(Register rn, int32_t offset = 0);
+
+  explicit MemOperand(Register ra, Register rb);
+
+  int32_t offset() const {
+    ASSERT(rb_.is(no_reg));
+    return offset_;
+  }
+
+  // PowerPC - base register
+  Register ra() const {
+    ASSERT(!ra_.is(no_reg));
+    return ra_;
+  }
+
+  Register rb() const {
+    ASSERT(offset_ == 0 && !rb_.is(no_reg));
+    return rb_;
+  }
+
+ private:
+  Register ra_;  // base
+  int32_t offset_;  // offset
+  Register rb_;  // index
+
+  friend class Assembler;
+};
+
+// CpuFeatures keeps track of which features are supported by the target CPU.
+// Supported features must be enabled by a Scope before use.
+class CpuFeatures : public AllStatic {
+ public:
+  // Detect features of the target CPU. Set safe defaults if the serializer
+  // is enabled (snapshots must be portable).
+  static void Probe();
+
+  // Check whether a feature is supported by the target CPU.
+  static bool IsSupported(CpuFeature f) {
+    ASSERT(initialized_);
+    return (supported_ & (1u << f)) != 0;
+  }
+
+#ifdef DEBUG
+  // Check whether a feature is currently enabled.
+  static bool IsEnabled(CpuFeature f) {
+    ASSERT(initialized_);
+    Isolate* isolate = Isolate::UncheckedCurrent();
+    if (isolate == NULL) {
+      // When no isolate is available, work as if we're running in
+      // release mode.
+      return IsSupported(f);
+    }
+    unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
+    return (enabled & (1u << f)) != 0;
+  }
+#endif
+
+  // Enable a specified feature within a scope.
+  class Scope BASE_EMBEDDED {
+#ifdef DEBUG
+
+   public:
+    explicit Scope(CpuFeature f) {
+      unsigned mask = 1u << f;
+      ASSERT(CpuFeatures::IsSupported(f));
+      ASSERT(!Serializer::enabled() ||
+             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
+      isolate_ = Isolate::UncheckedCurrent();
+      old_enabled_ = 0;
+      if (isolate_ != NULL) {
+        old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
+        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
+      }
+    }
+    ~Scope() {
+      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
+      if (isolate_ != NULL) {
+        isolate_->set_enabled_cpu_features(old_enabled_);
+      }
+    }
+
+   private:
+    Isolate* isolate_;
+    unsigned old_enabled_;
+#else
+
+   public:
+    explicit Scope(CpuFeature f) {}
+#endif
+  };
+
+  class TryForceFeatureScope BASE_EMBEDDED {
+   public:
+    explicit TryForceFeatureScope(CpuFeature f)
+        : old_supported_(CpuFeatures::supported_) {
+      if (CanForce()) {
+        CpuFeatures::supported_ |= (1u << f);
+      }
+    }
+
+    ~TryForceFeatureScope() {
+      if (CanForce()) {
+        CpuFeatures::supported_ = old_supported_;
+      }
+    }
+
+   private:
+    static bool CanForce() {
+      // It's only safe to temporarily force support of CPU features
+      // when there's only a single isolate, which is guaranteed when
+      // the serializer is enabled.
+      return Serializer::enabled();
+    }
+
+    const unsigned old_supported_;
+  };
+
+ private:
+#ifdef DEBUG
+  static bool initialized_;
+#endif
+  static unsigned supported_;
+  static unsigned found_by_runtime_probing_;
+
+  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
+};
+
+
+class Assembler : public AssemblerBase {
+ public:
+  // Create an assembler. Instructions and relocation information are emitted
+  // into a buffer, with the instructions starting from the beginning and the
+  // relocation information starting from the end of the buffer. See CodeDesc
+  // for a detailed comment on the layout (globals.h).
+  //
+  // If the provided buffer is NULL, the assembler allocates and grows its own
+  // buffer, and buffer_size determines the initial buffer size. The buffer is
+  // owned by the assembler and deallocated upon destruction of the assembler.
+  //
+  // If the provided buffer is not NULL, the assembler uses the provided buffer
+  // for code generation and assumes its size to be buffer_size. If the buffer
+  // is too small, a fatal error occurs. No deallocation of the buffer is done
+  // upon destruction of the assembler.
+  Assembler(Isolate* isolate, void* buffer, int buffer_size);
+  ~Assembler();
+
+  // Overrides the default provided by FLAG_debug_code.
+  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
+
+  // Avoids using instructions that vary in size in unpredictable ways between
+  // the snapshot and the running VM.  This is needed by the full compiler so
+  // that it can recompile code with debug support and fix the PC.
+  void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
+
+  // GetCode emits any pending (non-emitted) code and fills the descriptor
+  // desc. GetCode() is idempotent; it returns the same result if no other
+  // Assembler functions are invoked in between GetCode() calls.
+  void GetCode(CodeDesc* desc);
+
+  // Label operations & relative jumps (PPUM Appendix D)
+  //
+  // Takes a branch opcode (cc) and a label (L) and generates
+  // either a backward branch or a forward branch and links it
+  // to the label fixup chain. Usage:
+  //
+  // Label L;    // unbound label
+  // j(cc, &L);  // forward branch to unbound label
+  // bind(&L);   // bind label to the current pc
+  // j(cc, &L);  // backward branch to bound label
+  // bind(&L);   // illegal: a label may be bound only once
+  //
+  // Note: The same Label can be used for forward and backward branches
+  // but it may be bound only once.
+
+  void bind(Label* L);  // binds an unbound label L to the current code position
+  // Determines if Label is bound and near enough so that a single
+  // branch instruction can be used to reach it.
+  bool is_near(Label* L, Condition cond);
+
+  // Returns the branch offset to the given label from the current code position
+  // Links the label to the current position if it is still unbound
+  // Manages the jump elimination optimization if the second parameter is true.
+  int branch_offset(Label* L, bool jump_elimination_allowed);
+
+  // Puts a labels target address at the given position.
+  // The high 8 bits are set to zero.
+  void label_at_put(Label* L, int at_offset);
+
+  // Read/Modify the code target address in the branch/call instruction at pc.
+  INLINE(static Address target_address_at(Address pc));
+  INLINE(static void set_target_address_at(Address pc, Address target));
+
+  // Return the code target address at a call site from the return address
+  // of that call in the instruction stream.
+  inline static Address target_address_from_return_address(Address pc);
+
+  // This sets the branch destination.
+  // This is for calls and branches within generated code.
+  inline static void deserialization_set_special_target_at(
+      Address instruction_payload, Address target);
+
+  // Size of an instruction.
+  static const int kInstrSize = sizeof(Instr);
+
+  // Here we are patching the address in the LUI/ORI instruction pair.
+  // These values are used in the serialization process and must be zero for
+  // PPC platform, as Code, Embedded Object or External-reference pointers
+  // are split across two consecutive instructions and don't exist separately
+  // in the code, so the serializer should not step forwards in memory after
+  // a target is resolved and written.
+  static const int kSpecialTargetSize = 0;
+
+  // Number of consecutive instructions used to store pointer sized constant.
+#if V8_TARGET_ARCH_PPC64
+  static const int kInstructionsForPtrConstant = 5;
+#else
+  static const int kInstructionsForPtrConstant = 2;
+#endif
+
+  // Distance between the instruction referring to the address of the call
+  // target and the return address.
+
+  // Call sequence is a FIXED_SEQUENCE:
+  // lis     r8, 2148      @ call address hi
+  // ori     r8, r8, 5728  @ call address lo
+  // mtlr    r8
+  // blrl
+  //                      @ return address
+  // in 64bit mode, the addres load is a 5 instruction sequence
+#if V8_TARGET_ARCH_PPC64
+  static const int kCallTargetAddressOffset = 7 * kInstrSize;
+#else
+  static const int kCallTargetAddressOffset = 4 * kInstrSize;
+#endif
+
+  // Distance between start of patched return sequence and the emitted address
+  // to jump to.
+  // Patched return sequence is a FIXED_SEQUENCE:
+  //   lis r0, <address hi>
+  //   ori r0, r0, <address lo>
+  //   mtlr r0
+  //   blrl
+  static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
+
+  // Distance between start of patched debug break slot and the emitted address
+  // to jump to.
+  // Patched debug break slot code is a FIXED_SEQUENCE:
+  //   lis r0, <address hi>
+  //   ori r0, r0, <address lo>
+  //   mtlr r0
+  //   blrl
+  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
+
+  // Difference between address of current opcode and value read from pc
+  // register.
+  static const int kPcLoadDelta = 0;  // Todo: remove
+
+#if V8_TARGET_ARCH_PPC64
+  static const int kPatchDebugBreakSlotReturnOffset = 7 * kInstrSize;
+#else
+  static const int kPatchDebugBreakSlotReturnOffset = 4 * kInstrSize;
+#endif
+
+  // This is the length of the BreakLocationIterator::SetDebugBreakAtReturn()
+  // code patch FIXED_SEQUENCE
+#if V8_TARGET_ARCH_PPC64
+  static const int kJSReturnSequenceInstructions = 8;
+#else
+  static const int kJSReturnSequenceInstructions = 5;
+#endif
+
+  // This is the length of the code sequence from SetDebugBreakAtSlot()
+  // FIXED_SEQUENCE
+#if V8_TARGET_ARCH_PPC64
+  static const int kDebugBreakSlotInstructions = 7;
+#else
+  static const int kDebugBreakSlotInstructions = 4;
+#endif
+  static const int kDebugBreakSlotLength =
+      kDebugBreakSlotInstructions * kInstrSize;
+
+  static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
+    return ((cr.code() * CRWIDTH) + crbit);
+  }
+
+  // ---------------------------------------------------------------------------
+  // Code generation
+
+  // Insert the smallest number of nop instructions
+  // possible to align the pc offset to a multiple
+  // of m. m must be a power of 2 (>= 4).
+  void Align(int m);
+  // Aligns code to something that's optimal for a jump target for the platform.
+  void CodeTargetAlign();
+
+  // Branch instructions
+  void bclr(BOfield bo, LKBit lk);
+  void blr();
+  void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
+  void b(int branch_offset, LKBit lk);
+
+  void bcctr(BOfield bo, LKBit lk);
+  void bcr();
+
+  // Convenience branch instructions using labels
+  void b(Label* L, LKBit lk = LeaveLK)  {
+    b(branch_offset(L, false), lk);
+  }
+
+  void bc_short(Condition cond, Label* L, CRegister cr = cr7,
+                LKBit lk = LeaveLK)  {
+    ASSERT(cond != al);
+    ASSERT(cr.code() >= 0 && cr.code() <= 7);
+
+    int b_offset = branch_offset(L, false);
+
+    switch (cond) {
+      case eq:
+        bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
+        break;
+      case ne:
+        bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
+        break;
+      case gt:
+        bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
+        break;
+      case le:
+        bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
+        break;
+      case lt:
+        bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
+        break;
+      case ge:
+        bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
+        break;
+      case unordered:
+        bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
+        break;
+      case ordered:
+        bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
+        break;
+      case overflow:
+        bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
+        break;
+      case nooverflow:
+        bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
+        break;
+      default:
+        UNIMPLEMENTED();
+    }
+  }
+
+  void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK)  {
+    if (cond == al) {
+        b(L, lk);
+        return;
+    }
+
+    if ((L->is_bound() && is_near(L, cond)) ||
+        !is_trampoline_emitted()) {
+      bc_short(cond, L, cr, lk);
+      return;
+    }
+
+    Label skip;
+    Condition neg_cond = NegateCondition(cond);
+    bc_short(neg_cond, &skip, cr);
+    b(L, lk);
+    bind(&skip);
+  }
+
+  void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(ne, L, cr, lk); }
+  void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(eq, L, cr, lk); }
+  void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(lt, L, cr, lk); }
+  void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(ge, L, cr, lk); }
+  void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(le, L, cr, lk); }
+  void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(gt, L, cr, lk); }
+  void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(unordered, L, cr, lk); }
+  void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
+    b(ordered, L, cr, lk); }
+  void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
+    b(overflow, L, cr, lk); }
+  void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
+    b(nooverflow, L, cr, lk); }
+
+  // Decrement CTR; branch if CTR != 0
+  void bdnz(Label* L, LKBit lk = LeaveLK) {
+    bc(branch_offset(L, false), DCBNZ, 0, lk);
+  }
+
+  // Data-processing instructions
+
+  // PowerPC
+  void sub(Register dst, Register src1, Register src2,
+           OEBit s = LeaveOE, RCBit r = LeaveRC);
+
+  void subfic(Register dst, Register src, const Operand& imm);
+
+  void subfc(Register dst, Register src1, Register src2,
+           OEBit s = LeaveOE, RCBit r = LeaveRC);
+
+  void add(Register dst, Register src1, Register src2,
+           OEBit s = LeaveOE, RCBit r = LeaveRC);
+
+  void addc(Register dst, Register src1, Register src2,
+                    OEBit o = LeaveOE, RCBit r = LeaveRC);
+
+  void addze(Register dst, Register src1, OEBit o, RCBit r);
+
+  void mullw(Register dst, Register src1, Register src2,
+               OEBit o = LeaveOE, RCBit r = LeaveRC);
+
+  void mulhw(Register dst, Register src1, Register src2,
+               OEBit o = LeaveOE, RCBit r = LeaveRC);
+
+  void divw(Register dst, Register src1, Register src2,
+            OEBit o = LeaveOE, RCBit r = LeaveRC);
+
+  void addi(Register dst, Register src, const Operand& imm);
+  void addis(Register dst, Register src, const Operand& imm);
+  void addic(Register dst, Register src, const Operand& imm);
+
+  void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
+  void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
+  void andi(Register ra, Register rs, const Operand& imm);
+  void andis(Register ra, Register rs, const Operand& imm);
+  void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
+  void notx(Register dst, Register src, RCBit r = LeaveRC);
+  void ori(Register dst, Register src, const Operand& imm);
+  void oris(Register dst, Register src, const Operand& imm);
+  void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
+  void xori(Register dst, Register src, const Operand& imm);
+  void xoris(Register ra, Register rs, const Operand& imm);
+  void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
+  void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
+  void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
+  void li(Register dst, const Operand& src);
+  void lis(Register dst, const Operand& imm);
+  void mr(Register dst, Register src);
+
+  void lbz(Register dst, const MemOperand& src);
+  void lbzx(Register dst, const MemOperand& src);
+  void lbzux(Register dst, const MemOperand& src);
+  void lhz(Register dst, const MemOperand& src);
+  void lhzx(Register dst, const MemOperand& src);
+  void lhzux(Register dst, const MemOperand& src);
+  void lwz(Register dst, const MemOperand& src);
+  void lwzu(Register dst, const MemOperand& src);
+  void lwzx(Register dst, const MemOperand& src);
+  void lwzux(Register dst, const MemOperand& src);
+  void lwa(Register dst, const MemOperand& src);
+  void stb(Register dst, const MemOperand& src);
+  void stbx(Register dst, const MemOperand& src);
+  void stbux(Register dst, const MemOperand& src);
+  void sth(Register dst, const MemOperand& src);
+  void sthx(Register dst, const MemOperand& src);
+  void sthux(Register dst, const MemOperand& src);
+  void stw(Register dst, const MemOperand& src);
+  void stwu(Register dst, const MemOperand& src);
+  void stwx(Register rs, const MemOperand& src);
+  void stwux(Register rs, const MemOperand& src);
+
+  void extsb(Register rs, Register ra, RCBit r = LeaveRC);
+  void extsh(Register rs, Register ra, RCBit r = LeaveRC);
+
+  void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
+
+#if V8_TARGET_ARCH_PPC64
+  void ld(Register rd, const MemOperand &src);
+  void ldx(Register rd, const MemOperand &src);
+  void ldu(Register rd, const MemOperand &src);
+  void ldux(Register rd, const MemOperand &src);
+  void std(Register rs, const MemOperand &src);
+  void stdx(Register rs, const MemOperand &src);
+  void stdu(Register rs, const MemOperand &src);
+  void stdux(Register rs, const MemOperand &src);
+  void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
+  void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
+  void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
+  void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
+  void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
+  void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
+  void clrrdi(Register dst, Register src, const Operand& val,
+              RCBit rc = LeaveRC);
+  void clrldi(Register dst, Register src, const Operand& val,
+              RCBit rc = LeaveRC);
+  void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
+  void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
+  void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
+  void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
+  void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC);
+  void extsw(Register rs, Register ra, RCBit r = LeaveRC);
+  void mulld(Register dst, Register src1, Register src2,
+             OEBit o = LeaveOE, RCBit r = LeaveRC);
+  void divd(Register dst, Register src1, Register src2,
+            OEBit o = LeaveOE, RCBit r = LeaveRC);
+#endif
+
+  void rlwinm(Register ra, Register rs, int sh, int mb, int me,
+              RCBit rc = LeaveRC);
+  void rlwimi(Register ra, Register rs, int sh, int mb, int me,
+              RCBit rc = LeaveRC);
+  void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
+  void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
+  void clrrwi(Register dst, Register src, const Operand& val,
+              RCBit rc = LeaveRC);
+  void clrlwi(Register dst, Register src, const Operand& val,
+              RCBit rc = LeaveRC);
+  void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
+  void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
+  void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
+  void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
+
+  void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC);
+  // end PowerPC
+
+  void subi(Register dst, Register src1, const Operand& src2);
+
+  void cmp(Register src1, Register src2, CRegister cr = cr7);
+  void cmpl(Register src1, Register src2, CRegister cr = cr7);
+
+  void mov(Register dst, const Operand& src);
+
+  // Multiply instructions
+
+  // PowerPC
+  void mul(Register dst, Register src1, Register src2,
+           OEBit s = LeaveOE, RCBit r = LeaveRC);
+
+  // Miscellaneous arithmetic instructions
+
+  // Special register access
+  // PowerPC
+  void crxor(int bt, int ba, int bb);
+  void mflr(Register dst);
+  void mtlr(Register src);
+  void mtctr(Register src);
+  void mtxer(Register src);
+  void mcrfs(int bf, int bfa);
+  void mfcr(Register dst);
+
+  void fake_asm(enum FAKE_OPCODE_T fopcode);
+  void marker_asm(int mcode);
+  void function_descriptor();
+  // end PowerPC
+
+  // Exception-generating instructions and debugging support
+  void stop(const char* msg,
+            Condition cond = al,
+            int32_t code = kDefaultStopCode,
+            CRegister cr = cr7);
+
+  void bkpt(uint32_t imm16);  // v5 and above
+
+  // Informational messages when simulating
+  void info(const char* msg,
+            Condition cond = al,
+            int32_t code = kDefaultStopCode,
+            CRegister cr = cr7);
+
+  void dcbf(Register ra, Register rb);
+  void sync();
+  void icbi(Register ra, Register rb);
+  void isync();
+
+  // Support for floating point
+  void lfd(const DwVfpRegister frt, const MemOperand& src);
+  void lfdu(const DwVfpRegister frt, const MemOperand& src);
+  void lfdx(const DwVfpRegister frt, const MemOperand& src);
+  void lfdux(const DwVfpRegister frt, const MemOperand& src);
+  void lfs(const DwVfpRegister frt, const MemOperand& src);
+  void lfsu(const DwVfpRegister frt, const MemOperand& src);
+  void lfsx(const DwVfpRegister frt, const MemOperand& src);
+  void lfsux(const DwVfpRegister frt, const MemOperand& src);
+  void stfd(const DwVfpRegister frs, const MemOperand& src);
+  void stfdu(const DwVfpRegister frs, const MemOperand& src);
+  void stfdx(const DwVfpRegister frs, const MemOperand& src);
+  void stfdux(const DwVfpRegister frs, const MemOperand& src);
+  void stfs(const DwVfpRegister frs, const MemOperand& src);
+  void stfsu(const DwVfpRegister frs, const MemOperand& src);
+  void stfsx(const DwVfpRegister frs, const MemOperand& src);
+  void stfsux(const DwVfpRegister frs, const MemOperand& src);
+
+  void fadd(const DwVfpRegister frt, const DwVfpRegister fra,
+            const DwVfpRegister frb, RCBit rc = LeaveRC);
+  void fsub(const DwVfpRegister frt, const DwVfpRegister fra,
+            const DwVfpRegister frb, RCBit rc = LeaveRC);
+  void fdiv(const DwVfpRegister frt, const DwVfpRegister fra,
+            const DwVfpRegister frb, RCBit rc = LeaveRC);
+  void fmul(const DwVfpRegister frt, const DwVfpRegister fra,
+            const DwVfpRegister frc, RCBit rc = LeaveRC);
+  void fcmpu(const DwVfpRegister fra, const DwVfpRegister frb,
+             CRegister cr = cr7);
+  void fmr(const DwVfpRegister frt, const DwVfpRegister frb,
+           RCBit rc = LeaveRC);
+  void fctiwz(const DwVfpRegister frt, const DwVfpRegister frb);
+  void fctiw(const DwVfpRegister frt, const DwVfpRegister frb);
+  void frim(const DwVfpRegister frt, const DwVfpRegister frb);
+  void frsp(const DwVfpRegister frt, const DwVfpRegister frb,
+            RCBit rc = LeaveRC);
+  void fcfid(const DwVfpRegister frt, const DwVfpRegister frb,
+            RCBit rc = LeaveRC);
+  void fctid(const DwVfpRegister frt, const DwVfpRegister frb,
+            RCBit rc = LeaveRC);
+  void fctidz(const DwVfpRegister frt, const DwVfpRegister frb,
+            RCBit rc = LeaveRC);
+  void fsel(const DwVfpRegister frt, const DwVfpRegister fra,
+            const DwVfpRegister frc, const DwVfpRegister frb,
+            RCBit rc = LeaveRC);
+  void fneg(const DwVfpRegister frt, const DwVfpRegister frb,
+            RCBit rc = LeaveRC);
+  void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
+  void mffs(const DwVfpRegister frt, RCBit rc = LeaveRC);
+  void mtfsf(const DwVfpRegister frb, bool L = 1, int FLM = 0, bool W = 0,
+             RCBit rc = LeaveRC);
+  void fsqrt(const DwVfpRegister frt, const DwVfpRegister frb,
+             RCBit rc = LeaveRC);
+  void fabs(const DwVfpRegister frt, const DwVfpRegister frb,
+            RCBit rc = LeaveRC);
+
+  // Pseudo instructions
+
+  // Different nop operations are used by the code generator to detect certain
+  // states of the generated code.
+  enum NopMarkerTypes {
+    NON_MARKING_NOP = 0,
+    DEBUG_BREAK_NOP,
+    // IC markers.
+    PROPERTY_ACCESS_INLINED,
+    PROPERTY_ACCESS_INLINED_CONTEXT,
+    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
+    // Helper values.
+    LAST_CODE_MARKER,
+    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
+  };
+
+  void nop(int type = 0);   // 0 is the default non-marking type.
+
+  void push(Register src) {
+#if V8_TARGET_ARCH_PPC64
+    stdu(src, MemOperand(sp, -8));
+#else
+    stwu(src, MemOperand(sp, -4));
+#endif
+  }
+
+  void pop(Register dst) {
+#if V8_TARGET_ARCH_PPC64
+    ld(dst, MemOperand(sp));
+    addi(sp, sp, Operand(8));
+#else
+    lwz(dst, MemOperand(sp));
+    addi(sp, sp, Operand(4));
+#endif
+  }
+
+  void pop() {
+    addi(sp, sp, Operand(kPointerSize));
+  }
+
+  // Jump unconditionally to given label.
+  void jmp(Label* L) { b(L); }
+
+  bool predictable_code_size() const { return predictable_code_size_; }
+
+  // Check the code size generated from label to here.
+  int SizeOfCodeGeneratedSince(Label* label) {
+    return pc_offset() - label->pos();
+  }
+
+  // Check the number of instructions generated from label to here.
+  int InstructionsGeneratedSince(Label* label) {
+    return SizeOfCodeGeneratedSince(label) / kInstrSize;
+  }
+
+  // Class for scoping postponing the trampoline pool generation.
+  class BlockTrampolinePoolScope {
+   public:
+    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
+      assem_->StartBlockTrampolinePool();
+    }
+    ~BlockTrampolinePoolScope() {
+      assem_->EndBlockTrampolinePool();
+    }
+
+   private:
+    Assembler* assem_;
+
+    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
+  };
+
+  // Debugging
+
+  // Mark address of the ExitJSFrame code.
+  void RecordJSReturn();
+
+  // Mark address of a debug break slot.
+  void RecordDebugBreakSlot();
+
+  // Record the AST id of the CallIC being compiled, so that it can be placed
+  // in the relocation information.
+  void SetRecordedAstId(TypeFeedbackId ast_id) {
+// PPC - this shouldn't be failing roohack   ASSERT(recorded_ast_id_.IsNone());
+    recorded_ast_id_ = ast_id;
+  }
+
+  TypeFeedbackId RecordedAstId() {
+    // roohack - another issue??? ASSERT(!recorded_ast_id_.IsNone());
+    return recorded_ast_id_;
+  }
+
+  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
+
+  // Record a comment relocation entry that can be used by a disassembler.
+  // Use --code-comments to enable.
+  void RecordComment(const char* msg);
+
+  // Writes a single byte or word of data in the code stream.  Used
+  // for inline tables, e.g., jump-tables.
+  void db(uint8_t data);
+  void dd(uint32_t data);
+
+  int pc_offset() const { return pc_ - buffer_; }
+
+  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
+
+  // Read/patch instructions
+  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
+  void instr_at_put(int pos, Instr instr) {
+    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
+  }
+  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
+  static void instr_at_put(byte* pc, Instr instr) {
+    *reinterpret_cast<Instr*>(pc) = instr;
+  }
+  static Condition GetCondition(Instr instr);
+
+  static bool IsLis(Instr instr);
+  static bool IsAddic(Instr instr);
+  static bool IsOri(Instr instr);
+
+  static bool IsBranch(Instr instr);
+  static Register GetRA(Instr instr);
+  static Register GetRB(Instr instr);
+#if V8_TARGET_ARCH_PPC64
+  static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2,
+                                 Instr instr3, Instr instr4, Instr instr5);
+#else
+  static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
+#endif
+
+  static bool IsCmpRegister(Instr instr);
+  static bool IsCmpImmediate(Instr instr);
+  static bool IsRlwinm(Instr instr);
+#if V8_TARGET_ARCH_PPC64
+  static bool IsRldicl(Instr instr);
+#endif
+  static Register GetCmpImmediateRegister(Instr instr);
+  static int GetCmpImmediateRawImmediate(Instr instr);
+  static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
+
+  // Postpone the generation of the trampoline pool for the specified number of
+  // instructions.
+  void BlockTrampolinePoolFor(int instructions);
+  void CheckTrampolinePool();
+
+ protected:
+  // Relocation for a type-recording IC has the AST id added to it.  This
+  // member variable is a way to pass the information from the call site to
+  // the relocation info.
+  TypeFeedbackId recorded_ast_id_;
+
+  bool emit_debug_code() const { return emit_debug_code_; }
+
+  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
+
+  // Decode branch instruction at pos and return branch target pos
+  int target_at(int pos);
+
+  // Patch branch instruction at pos to branch to given branch target pos
+  void target_at_put(int pos, int target_pos);
+
+  // Record reloc info for current pc_
+  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
+
+  // Block the emission of the trampoline pool before pc_offset.
+  void BlockTrampolinePoolBefore(int pc_offset) {
+    if (no_trampoline_pool_before_ < pc_offset)
+      no_trampoline_pool_before_ = pc_offset;
+  }
+
+  void StartBlockTrampolinePool() {
+    trampoline_pool_blocked_nesting_++;
+  }
+
+  void EndBlockTrampolinePool() {
+    trampoline_pool_blocked_nesting_--;
+  }
+
+  bool is_trampoline_pool_blocked() const {
+    return trampoline_pool_blocked_nesting_ > 0;
+  }
+
+  bool has_exception() const {
+    return internal_trampoline_exception_;
+  }
+
+  bool is_trampoline_emitted() const {
+    return trampoline_emitted_;
+  }
+
+
+ private:
+  // Code buffer:
+  // The buffer into which code and relocation info are generated.
+  byte* buffer_;
+  int buffer_size_;
+  // True if the assembler owns the buffer, false if buffer is external.
+  bool own_buffer_;
+
+  // Code generation
+  // The relocation writer's position is at least kGap bytes below the end of
+  // the generated instructions. This is so that multi-instruction sequences do
+  // not have to check for overflow. The same is true for writes of large
+  // relocation info entries.
+  static const int kGap = 32;
+  byte* pc_;  // the program counter; moves forward
+
+  // Repeated checking whether the trampoline pool should be emitted is rather
+  // expensive. By default we only check again once a number of instructions
+  // has been generated.
+  int next_buffer_check_;  // pc offset of next buffer check.
+
+  // Emission of the trampoline pool may be blocked in some code sequences.
+  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
+  int no_trampoline_pool_before_;  // Block emission before this pc offset.
+
+  // Relocation info generation
+  // Each relocation is encoded as a variable size value
+  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
+  RelocInfoWriter reloc_info_writer;
+
+  // The bound position, before this we cannot do instruction elimination.
+  int last_bound_pos_;
+
+  // Code emission
+  inline void CheckBuffer();
+  void GrowBuffer();
+  inline void emit(Instr x);
+  inline void CheckTrampolinePoolQuick();
+
+  // Instruction generation
+  void a_form(Instr instr, DwVfpRegister frt, DwVfpRegister fra,
+              DwVfpRegister frb, RCBit r);
+  void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
+              bool signed_disp);
+  void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
+  void xo_form(Instr instr, Register rt, Register ra, Register rb,
+               OEBit o, RCBit r);
+  void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
+               RCBit r);
+
+  // Labels
+  void print(Label* L);
+  int  max_reach_from(int pos);
+  void bind_to(Label* L, int pos);
+  void next(Label* L);
+
+  class Trampoline {
+   public:
+    Trampoline() {
+      next_slot_ = 0;
+      free_slot_count_ = 0;
+    }
+    Trampoline(int start, int slot_count) {
+      next_slot_ = start;
+      free_slot_count_ = slot_count;
+    }
+    int take_slot() {
+      int trampoline_slot = kInvalidSlotPos;
+      if (free_slot_count_ <= 0) {
+        // We have run out of space on trampolines.
+        // Make sure we fail in debug mode, so we become aware of each case
+        // when this happens.
+        ASSERT(0);
+        // Internal exception will be caught.
+      } else {
+        trampoline_slot = next_slot_;
+        free_slot_count_--;
+        next_slot_ += kTrampolineSlotsSize;
+      }
+      return trampoline_slot;
+    }
+
+   private:
+    int next_slot_;
+    int free_slot_count_;
+  };
+
+  int32_t get_trampoline_entry();
+  int unbound_labels_count_;
+  // If trampoline is emitted, generated code is becoming large. As
+  // this is already a slow case which can possibly break our code
+  // generation for the extreme case, we use this information to
+  // trigger different mode of branch instruction generation, where we
+  // no longer use a single branch instruction.
+  bool trampoline_emitted_;
+  static const int kTrampolineSlotsSize = kInstrSize;
+  static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
+  static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
+  static const int kInvalidSlotPos = -1;
+
+  Trampoline trampoline_;
+  bool internal_trampoline_exception_;
+
+  friend class RegExpMacroAssemblerPPC;
+  friend class RelocInfo;
+  friend class CodePatcher;
+  friend class BlockTrampolinePoolScope;
+
+  PositionsRecorder positions_recorder_;
+
+  bool emit_debug_code_;
+  bool predictable_code_size_;
+
+  friend class PositionsRecorder;
+  friend class EnsureSpace;
+};
+
+
+class EnsureSpace BASE_EMBEDDED {
+ public:
+  explicit EnsureSpace(Assembler* assembler) {
+    assembler->CheckBuffer();
+  }
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_ASSEMBLER_PPC_H_
diff --git a/src/ppc/builtins-ppc.cc b/src/ppc/builtins-ppc.cc
new file mode 100644
index 0000000..cdda043
--- /dev/null
+++ b/src/ppc/builtins-ppc.cc
@@ -0,0 +1,1910 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "codegen.h"
+#include "debug.h"
+#include "deoptimizer.h"
+#include "full-codegen.h"
+#include "runtime.h"
+
+namespace v8 {
+namespace internal {
+
+
+#define __ ACCESS_MASM(masm)
+
+void Builtins::Generate_Adaptor(MacroAssembler* masm,
+                                CFunctionId id,
+                                BuiltinExtraArguments extra_args) {
+  // ----------- S t a t e -------------
+  //  -- r3                 : number of arguments excluding receiver
+  //  -- r4                 : called function (only guaranteed when
+  //                          extra_args requires it)
+  //  -- cp                 : context
+  //  -- sp[0]              : last argument
+  //  -- ...
+  //  -- sp[4 * (argc - 1)] : first argument (argc == r0)
+  //  -- sp[4 * argc]       : receiver
+  // -----------------------------------
+
+  // Insert extra arguments.
+  int num_extra_args = 0;
+  if (extra_args == NEEDS_CALLED_FUNCTION) {
+    num_extra_args = 1;
+    __ push(r4);
+  } else {
+    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
+  }
+
+  // JumpToExternalReference expects r0 to contain the number of arguments
+  // including the receiver and the extra arguments.
+  __ addi(r3, r3, Operand(num_extra_args + 1));
+  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
+}
+
+
+// Load the built-in InternalArray function from the current context.
+static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
+                                              Register result) {
+  // Load the native context.
+
+  __ LoadP(result,
+           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ LoadP(result,
+           FieldMemOperand(result, GlobalObject::kNativeContextOffset));
+  // Load the InternalArray function from the native context.
+  __ LoadP(result,
+           MemOperand(result,
+                      Context::SlotOffset(
+                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
+}
+
+
+// Load the built-in Array function from the current context.
+static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
+  // Load the native context.
+
+  __ LoadP(result,
+           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ LoadP(result,
+           FieldMemOperand(result, GlobalObject::kNativeContextOffset));
+  // Load the Array function from the native context.
+  __ LoadP(result,
+           MemOperand(result,
+                      Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
+}
+
+
+// Allocate an empty JSArray. The allocated array is put into the result
+// register. An elements backing store is allocated with size initial_capacity
+// and filled with the hole values.
+static void AllocateEmptyJSArray(MacroAssembler* masm,
+                                 Register array_function,
+                                 Register result,
+                                 Register scratch1,
+                                 Register scratch2,
+                                 Register scratch3,
+                                 Label* gc_required) {
+  const int initial_capacity = JSArray::kPreallocatedArrayElements;
+  STATIC_ASSERT(initial_capacity >= 0);
+  __ LoadInitialArrayMap(array_function, scratch2, scratch1, false);
+
+  // Allocate the JSArray object together with space for a fixed array with the
+  // requested elements.
+  int size = JSArray::kSize;
+  if (initial_capacity > 0) {
+    size += FixedArray::SizeFor(initial_capacity);
+  }
+  __ AllocateInNewSpace(size,
+                        result,
+                        scratch2,
+                        scratch3,
+                        gc_required,
+                        TAG_OBJECT);
+
+  // Future optimization: defer tagging the result pointer for more
+  // efficient 64-bit memory accesses (due to alignment requirements
+  // on the memoperand offset).
+
+  // Allocated the JSArray. Now initialize the fields except for the elements
+  // array.
+  // result: JSObject
+  // scratch1: initial map
+  // scratch2: start of next object
+  __ StoreP(scratch1, FieldMemOperand(result, JSObject::kMapOffset), r0);
+  __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
+  __ StoreP(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset), r0);
+  // Field JSArray::kElementsOffset is initialized later.
+  __ li(scratch3,  Operand(0, RelocInfo::NONE));
+  __ StoreP(scratch3, FieldMemOperand(result, JSArray::kLengthOffset), r0);
+
+  if (initial_capacity == 0) {
+    __ StoreP(scratch1, FieldMemOperand(result, JSArray::kElementsOffset), r0);
+    return;
+  }
+
+  // Calculate the location of the elements array and set elements array member
+  // of the JSArray.
+  // result: JSObject
+  // scratch2: start of next object
+  __ addi(scratch1, result, Operand(JSArray::kSize));
+  __ StoreP(scratch1, FieldMemOperand(result, JSArray::kElementsOffset), r0);
+
+  // Clear the heap tag on the elements array.
+  __ subi(scratch1, scratch1, Operand(kHeapObjectTag));
+
+  // Initialize the FixedArray and fill it with holes. FixedArray length is
+  // stored as a smi.
+  // result: JSObject
+  // scratch1: elements array (untagged)
+  // scratch2: start of next object
+  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
+  STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset);
+  __ StoreP(scratch3, MemOperand(scratch1));
+  __ addi(scratch1, scratch1, Operand(kPointerSize));
+  __ LoadSmiLiteral(scratch3,  Smi::FromInt(initial_capacity));
+  STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
+  __ StoreP(scratch3, MemOperand(scratch1));
+  __ addi(scratch1, scratch1, Operand(kPointerSize));
+
+  // Fill the FixedArray with the hole value. Inline the code if short.
+  STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize);
+  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
+  static const int kLoopUnfoldLimit = 4;
+  if (initial_capacity <= kLoopUnfoldLimit) {
+    for (int i = 0; i < initial_capacity; i++) {
+      __ StoreP(scratch3, MemOperand(scratch1));
+      __ addi(scratch1, scratch1, Operand(kPointerSize));
+    }
+  } else {
+    Label loop, entry;
+    __ addi(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
+    __ b(&entry);
+    __ bind(&loop);
+    __ StoreP(scratch3, MemOperand(scratch1));
+    __ addi(scratch1, scratch1, Operand(kPointerSize));
+    __ bind(&entry);
+    __ cmp(scratch1, scratch2);
+    __ blt(&loop);
+  }
+}
+
+// Allocate a JSArray with the number of elements stored in a register. The
+// register array_function holds the built-in Array function and the register
+// array_size holds the size of the array as a smi. The allocated array is put
+// into the result register and beginning and end of the FixedArray elements
+// storage is put into registers elements_array_storage and elements_array_end
+// (see  below for when that is not the case). If the parameter fill_with_holes
+// is true the allocated elements backing store is filled with the hole values
+// otherwise it is left uninitialized. When the backing store is filled the
+// register elements_array_storage is scratched.
+static void AllocateJSArray(MacroAssembler* masm,
+                            Register array_function,  // Array function.
+                            Register array_size,  // As a smi, cannot be 0.
+                            Register result,
+                            Register elements_array_storage,
+                            Register elements_array_end,
+                            Register scratch1,
+                            Register scratch2,
+                            bool fill_with_hole,
+                            Label* gc_required) {
+  // Load the initial map from the array function.
+  __ LoadInitialArrayMap(array_function, scratch2,
+                         elements_array_storage, fill_with_hole);
+
+  if (FLAG_debug_code) {  // Assert that array size is not zero.
+    __ cmpi(array_size, Operand::Zero());
+    __ Assert(ne, "array size is unexpectedly 0");
+  }
+
+  // Allocate the JSArray object together with space for a FixedArray with the
+  // requested number of elements.  We omit the TAG_OBJECT flag and defer
+  // tagging the pointer until the end so that we can more efficiently perform
+  // aligned memory accesses.
+  __ li(elements_array_end,
+         Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize));
+  __ SmiUntag(scratch1, array_size);
+  __ add(elements_array_end, elements_array_end, scratch1);
+  __ AllocateInNewSpace(
+      elements_array_end,
+      result,
+      scratch1,
+      scratch2,
+      gc_required,
+      static_cast<AllocationFlags>(SIZE_IN_WORDS));
+
+  // Allocated the JSArray. Now initialize the fields except for the elements
+  // array.
+  // result: JSObject (untagged)
+  // elements_array_storage: initial map
+  // array_size: size of array (smi)
+  __ StoreP(elements_array_storage, MemOperand(result, JSObject::kMapOffset));
+  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
+  __ StoreP(elements_array_storage,
+            MemOperand(result, JSArray::kPropertiesOffset));
+  // Field JSArray::kElementsOffset is initialized later.
+  __ StoreP(array_size, MemOperand(result, JSArray::kLengthOffset));
+
+  // Calculate the location of the elements array and set elements array member
+  // of the JSArray.
+  // result: JSObject (untagged)
+  // array_size: size of array (smi)
+  __ addi(elements_array_storage, result,
+          Operand(JSArray::kSize + kHeapObjectTag));
+  __ StoreP(elements_array_storage,
+            MemOperand(result, JSArray::kElementsOffset));
+
+  // Clear the heap tag on the elements array.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ subi(elements_array_storage,
+         elements_array_storage,
+         Operand(kHeapObjectTag));
+  // Initialize the fixed array and fill it with holes. FixedArray length is
+  // stored as a smi.
+  // result: JSObject (untagged)
+  // elements_array_storage: elements array (untagged)
+  // array_size: size of array (smi)
+  __ LoadRoot(scratch1, Heap::kFixedArrayMapRootIndex);
+  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
+  __ StoreP(scratch1, MemOperand(elements_array_storage));
+  __ addi(elements_array_storage, elements_array_storage,
+          Operand(kPointerSize));
+  STATIC_ASSERT(kSmiTag == 0);
+  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
+  __ StoreP(array_size, MemOperand(elements_array_storage));
+  __ addi(elements_array_storage, elements_array_storage,
+          Operand(kPointerSize));
+
+  // Calculate elements array and elements array end.
+  // result: JSObject (untagged)
+  // elements_array_storage: elements array element storage
+  // array_size: smi-tagged size of elements array
+  __ SmiToPtrArrayOffset(scratch1, array_size);
+  __ add(elements_array_end, elements_array_storage, scratch1);
+
+  // Fill the allocated FixedArray with the hole value if requested.
+  // result: JSObject (untagged)
+  // elements_array_storage: elements array element storage
+  // elements_array_end: start of next object
+  if (fill_with_hole) {
+    Label loop, entry;
+    __ LoadRoot(scratch1, Heap::kTheHoleValueRootIndex);
+    __ b(&entry);
+    __ bind(&loop);
+    __ StoreP(scratch1, MemOperand(elements_array_storage));
+    __ addi(elements_array_storage, elements_array_storage,
+           Operand(kPointerSize));
+    __ bind(&entry);
+    __ cmp(elements_array_storage, elements_array_end);
+    __ blt(&loop);
+  }
+
+  // Tag object
+  __ addi(result, result, Operand(kHeapObjectTag));
+}
+
+// Create a new array for the built-in Array function. This function allocates
+// the JSArray object and the FixedArray elements array and initializes these.
+// If the Array cannot be constructed in native code the runtime is called. This
+// function assumes the following state:
+//   r3: argc
+//   r4: constructor (built-in Array function)
+//   lr: return address
+//   sp[0]: last argument
+// This function is used for both construct and normal calls of Array. The only
+// difference between handling a construct call and a normal call is that for a
+// construct call the constructor function in r1 needs to be preserved for
+// entering the generic code. In both cases argc in r0 needs to be preserved.
+// Both registers are preserved by this code so no need to differentiate between
+// construct call and normal call.
+static void ArrayNativeCode(MacroAssembler* masm,
+                            Label* call_generic_code) {
+  Counters* counters = masm->isolate()->counters();
+  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
+      has_non_smi_element, finish, cant_transition_map, not_double;
+
+  // Check for array construction with zero arguments or one.
+  __ cmpi(r3, Operand(0, RelocInfo::NONE));
+  __ bne(&argc_one_or_more);
+
+  // Handle construction of an empty array.
+  __ bind(&empty_array);
+  AllocateEmptyJSArray(masm,
+                       r4,
+                       r5,
+                       r6,
+                       r7,
+                       r8,
+                       call_generic_code);
+  __ IncrementCounter(counters->array_function_native(), 1, r6, r7);
+  // Set up return value, remove receiver from stack and return.
+  __ mr(r3, r5);
+  __ addi(sp, sp, Operand(kPointerSize));
+  __ blr();
+
+  // Check for one argument. Bail out if argument is not smi or if it is
+  // negative.
+  __ bind(&argc_one_or_more);
+  __ cmpi(r3, Operand(1));
+  __ bne(&argc_two_or_more);
+  STATIC_ASSERT(kSmiTag == 0);
+  __ LoadP(r5, MemOperand(sp));  // Get the argument from the stack.
+  __ cmpi(r5, Operand::Zero());
+  __ bne(&not_empty_array);
+  __ Drop(1);  // Adjust stack.
+  __ li(r3, Operand::Zero());  // Treat this as a call with argc of zero.
+  __ b(&empty_array);
+
+  __ bind(&not_empty_array);
+  __ TestIfPositiveSmi(r5, r6);
+  __ bne(call_generic_code, cr0);
+
+  // Handle construction of an empty array of a certain size. Bail out if size
+  // is too large to actually allocate an elements array.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ CmpSmiLiteral(r5, Smi::FromInt(JSObject::kInitialMaxFastElementArray), r0);
+  __ bge(call_generic_code);
+
+  // r3: argc
+  // r4: constructor
+  // r5: array_size (smi)
+  // sp[0]: argument
+  AllocateJSArray(masm,
+                  r4,
+                  r5,
+                  r6,
+                  r7,
+                  r8,
+                  r9,
+                  r10,
+                  true,
+                  call_generic_code);
+  __ IncrementCounter(counters->array_function_native(), 1, r5, r7);
+  // Set up return value, remove receiver and argument from stack and return.
+  __ mr(r3, r6);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ blr();
+
+  // Handle construction of an array from a list of arguments.
+  __ bind(&argc_two_or_more);
+  // Convet argc to a smi.
+  __ SmiTag(r5, r3);
+
+  // r3: argc
+  // r4: constructor
+  // r5: array_size (smi)
+  // sp[0]: last argument
+  AllocateJSArray(masm,
+                  r4,
+                  r5,
+                  r6,
+                  r7,
+                  r8,
+                  r9,
+                  r10,
+                  false,
+                  call_generic_code);
+  __ IncrementCounter(counters->array_function_native(), 1, r5, r9);
+
+  // Fill arguments as array elements. Copy from the top of the stack (last
+  // element) to the array backing store filling it backwards. Note:
+  // elements_array_end points after the backing store therefore PreIndex is
+  // used when filling the backing store.
+  // r3: argc
+  // r6: JSArray
+  // r7: elements_array storage start (untagged)
+  // r8: elements_array_end (untagged)
+  // sp[0]: last argument
+  Label loop, entry;
+  __ mr(r10, sp);
+  __ b(&entry);
+  __ bind(&loop);
+  __ LoadP(r5, MemOperand(r10));
+  __ addi(r10, r10, Operand(kPointerSize));
+  if (FLAG_smi_only_arrays) {
+    __ JumpIfNotSmi(r5, &has_non_smi_element);
+  }
+  __ StorePU(r5, MemOperand(r8, -kPointerSize));
+  __ bind(&entry);
+  __ cmp(r7, r8);
+  __ blt(&loop);
+
+  __ bind(&finish);
+  __ mr(sp, r10);
+
+  // Remove caller arguments and receiver from the stack, setup return value and
+  // return.
+  // r3: argc
+  // r6: JSArray
+  // sp[0]: receiver
+  __ addi(sp, sp, Operand(kPointerSize));
+  __ mr(r3, r6);
+  __ blr();
+
+  __ bind(&has_non_smi_element);
+  // Double values are handled by the runtime.
+  __ CheckMap(
+      r5, r22, Heap::kHeapNumberMapRootIndex, &not_double, DONT_DO_SMI_CHECK);
+  __ bind(&cant_transition_map);
+  __ UndoAllocationInNewSpace(r6, r7);
+  __ b(call_generic_code);
+
+  __ bind(&not_double);
+  // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS.
+  // r6: JSArray
+  __ LoadP(r5, FieldMemOperand(r6, HeapObject::kMapOffset));
+  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
+                                         FAST_ELEMENTS,
+                                         r5,
+                                         r22,
+                                         &cant_transition_map);
+  __ StoreP(r5, FieldMemOperand(r6, HeapObject::kMapOffset), r0);
+  __ RecordWriteField(r6,
+                      HeapObject::kMapOffset,
+                      r5,
+                      r22,
+                      kLRHasNotBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  Label loop2;
+  __ subi(r10, r10, Operand(kPointerSize));
+  __ bind(&loop2);
+  __ LoadP(r5, MemOperand(r10));
+  __ addi(r10, r10, Operand(kPointerSize));
+  __ StorePU(r5, MemOperand(r8, -kPointerSize));
+  __ cmp(r7, r8);
+  __ blt(&loop2);
+  __ b(&finish);
+}
+
+
+void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3     : number of arguments
+  //  -- lr     : return address
+  //  -- sp[...]: constructor arguments
+  // -----------------------------------
+  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
+
+  // Get the InternalArray function.
+  GenerateLoadInternalArrayFunction(masm, r4);
+
+  if (FLAG_debug_code) {
+    // Initial map for the builtin InternalArray functions should be maps.
+    __ LoadP(r5, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
+    STATIC_ASSERT(kSmiTagMask < 0x8000);
+    __ andi(r0, r5, Operand(kSmiTagMask));
+    __ Assert(ne, "Unexpected initial map for InternalArray function", cr0);
+    __ CompareObjectType(r5, r6, r7, MAP_TYPE);
+    __ Assert(eq, "Unexpected initial map for InternalArray function");
+  }
+
+  // Run the native code for the InternalArray function called as a normal
+  // function.
+  ArrayNativeCode(masm, &generic_array_code);
+
+  // Jump to the generic array code if the specialized code cannot handle the
+  // construction.
+  __ bind(&generic_array_code);
+
+  Handle<Code> array_code =
+      masm->isolate()->builtins()->InternalArrayCodeGeneric();
+  __ Jump(array_code, RelocInfo::CODE_TARGET);
+}
+
+
+void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3     : number of arguments
+  //  -- lr     : return address
+  //  -- sp[...]: constructor arguments
+  // -----------------------------------
+  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
+
+  // Get the Array function.
+  GenerateLoadArrayFunction(masm, r4);
+
+  if (FLAG_debug_code) {
+    // Initial map for the builtin Array functions should be maps.
+    __ LoadP(r5, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
+    STATIC_ASSERT(kSmiTagMask < 0x8000);
+    __ andi(r0, r5, Operand(kSmiTagMask));
+    __ Assert(ne, "Unexpected initial map for Array function", cr0);
+    __ CompareObjectType(r5, r6, r7, MAP_TYPE);
+    __ Assert(eq, "Unexpected initial map for Array function");
+  }
+
+  // Run the native code for the Array function called as a normal function.
+  ArrayNativeCode(masm, &generic_array_code);
+
+  // Jump to the generic array code if the specialized code cannot handle
+  // the construction.
+  __ bind(&generic_array_code);
+
+  Handle<Code> array_code =
+      masm->isolate()->builtins()->ArrayCodeGeneric();
+  __ Jump(array_code, RelocInfo::CODE_TARGET);
+}
+
+
+void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3     : number of arguments
+  //  -- r4     : constructor function
+  //  -- lr     : return address
+  //  -- sp[...]: constructor arguments
+  // -----------------------------------
+  Label generic_constructor;
+
+  if (FLAG_debug_code) {
+    // The array construct code is only set for the builtin and internal
+    // Array functions which always have a map.
+    // Initial map for the builtin Array function should be a map.
+    __ LoadP(r5, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
+    __ andi(r0, r5, Operand(kSmiTagMask));
+    __ Assert(ne, "Unexpected initial map for Array function", cr0);
+    __ CompareObjectType(r5, r6, r7, MAP_TYPE);
+    __ Assert(eq, "Unexpected initial map for Array function");
+  }
+
+  // Run the native code for the Array function called as a constructor.
+  ArrayNativeCode(masm, &generic_constructor);
+
+  // Jump to the generic construct code in case the specialized code cannot
+  // handle the construction.
+  __ bind(&generic_constructor);
+  Handle<Code> generic_construct_stub =
+      masm->isolate()->builtins()->JSConstructStubGeneric();
+  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
+}
+
+
+void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3                     : number of arguments
+  //  -- r4                     : constructor function
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->string_ctor_calls(), 1, r5, r6);
+
+  Register function = r4;
+  if (FLAG_debug_code) {
+    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r5);
+    __ cmp(function, r5);
+    __ Assert(eq, "Unexpected String function");
+  }
+
+  // Load the first arguments in r3 and get rid of the rest.
+  Label no_arguments;
+  __ cmpi(r3, Operand(0, RelocInfo::NONE));
+  __ beq(&no_arguments);
+  // First args = sp[(argc - 1) * 4].
+  __ subi(r3, r3, Operand(1));
+  __ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2));
+  __ add(sp, sp, r3);
+  __ LoadP(r3, MemOperand(sp));
+  // sp now point to args[0], drop args[0] + receiver.
+  __ Drop(2);
+
+  Register argument = r5;
+  Label not_cached, argument_is_string;
+  NumberToStringStub::GenerateLookupNumberStringCache(
+      masm,
+      r3,        // Input.
+      argument,  // Result.
+      r6,        // Scratch.
+      r7,        // Scratch.
+      r8,        // Scratch.
+      false,     // Is it a Smi?
+      &not_cached);
+  __ IncrementCounter(counters->string_ctor_cached_number(), 1, r6, r7);
+  __ bind(&argument_is_string);
+
+  // ----------- S t a t e -------------
+  //  -- r5     : argument converted to string
+  //  -- r4     : constructor function
+  //  -- lr     : return address
+  // -----------------------------------
+
+  Label gc_required;
+  __ AllocateInNewSpace(JSValue::kSize,
+                        r3,  // Result.
+                        r6,  // Scratch.
+                        r7,  // Scratch.
+                        &gc_required,
+                        TAG_OBJECT);
+
+  // Initialising the String Object.
+  Register map = r6;
+  __ LoadGlobalFunctionInitialMap(function, map, r7);
+  if (FLAG_debug_code) {
+    __ lbz(r7, FieldMemOperand(map, Map::kInstanceSizeOffset));
+    __ cmpi(r7, Operand(JSValue::kSize >> kPointerSizeLog2));
+    __ Assert(eq, "Unexpected string wrapper instance size");
+    __ lbz(r7, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
+    __ cmpi(r7, Operand(0, RelocInfo::NONE));
+    __ Assert(eq, "Unexpected unused properties of string wrapper");
+  }
+  __ StoreP(map, FieldMemOperand(r3, HeapObject::kMapOffset), r0);
+
+  __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
+  __ StoreP(r6, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0);
+  __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
+
+  __ StoreP(argument, FieldMemOperand(r3, JSValue::kValueOffset), r0);
+
+  // Ensure the object is fully initialized.
+  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
+
+  __ Ret();
+
+  // The argument was not found in the number to string cache. Check
+  // if it's a string already before calling the conversion builtin.
+  Label convert_argument;
+  __ bind(&not_cached);
+  __ JumpIfSmi(r3, &convert_argument);
+
+  // Is it a String?
+  __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ lbz(r6, FieldMemOperand(r5, Map::kInstanceTypeOffset));
+  STATIC_ASSERT(kNotStringTag != 0);
+  __ andi(r0, r6, Operand(kIsNotStringMask));
+  __ bne(&convert_argument, cr0);
+  __ mr(argument, r3);
+  __ IncrementCounter(counters->string_ctor_conversions(), 1, r6, r7);
+  __ b(&argument_is_string);
+
+  // Invoke the conversion builtin and put the result into r5.
+  __ bind(&convert_argument);
+  __ push(function);  // Preserve the function.
+  __ IncrementCounter(counters->string_ctor_conversions(), 1, r6, r7);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(r3);
+    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
+  }
+  __ pop(function);
+  __ mr(argument, r3);
+  __ b(&argument_is_string);
+
+  // Load the empty string into r5, remove the receiver from the
+  // stack, and jump back to the case where the argument is a string.
+  __ bind(&no_arguments);
+  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
+  __ Drop(1);
+  __ b(&argument_is_string);
+
+  // At this point the argument is already a string. Call runtime to
+  // create a string wrapper.
+  __ bind(&gc_required);
+  __ IncrementCounter(counters->string_ctor_gc_required(), 1, r6, r7);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(argument);
+    __ CallRuntime(Runtime::kNewStringWrapper, 1);
+  }
+  __ Ret();
+}
+
+
+static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
+  __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r5, FieldMemOperand(r5, SharedFunctionInfo::kCodeOffset));
+  __ addi(r5, r5, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ mtctr(r5);
+  __ bcr();
+}
+
+
+void Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
+  GenerateTailCallToSharedCode(masm);
+}
+
+
+void Builtins::Generate_ParallelRecompile(MacroAssembler* masm) {
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+    // Push a copy of the function onto the stack.
+    __ push(r4);
+    // Push call kind information.
+    __ push(r8);
+
+    __ push(r4);  // Function is also the parameter to the runtime call.
+    __ CallRuntime(Runtime::kParallelRecompile, 1);
+
+    // Restore call kind information.
+    __ pop(r8);
+    // Restore receiver.
+    __ pop(r4);
+
+    // Tear down internal frame.
+  }
+
+  GenerateTailCallToSharedCode(masm);
+}
+
+
+static void Generate_JSConstructStubHelper(MacroAssembler* masm,
+                                           bool is_api_function,
+                                           bool count_constructions) {
+  // ----------- S t a t e -------------
+  //  -- r3     : number of arguments
+  //  -- r4     : constructor function
+  //  -- lr     : return address
+  //  -- sp[...]: constructor arguments
+  // -----------------------------------
+
+  // Should never count constructions for api objects.
+  ASSERT(!is_api_function || !count_constructions);
+
+  Isolate* isolate = masm->isolate();
+
+  // Enter a construct frame.
+  {
+    FrameScope scope(masm, StackFrame::CONSTRUCT);
+
+    // Preserve the two incoming parameters on the stack.
+    __ SmiTag(r3);
+    __ push(r3);  // Smi-tagged arguments count.
+    __ push(r4);  // Constructor function.
+
+    // Try to allocate the object without transitioning into C code. If any of
+    // the preconditions is not met, the code bails out to the runtime call.
+    Label rt_call, allocated;
+    if (FLAG_inline_new) {
+      Label undo_allocation;
+#ifdef ENABLE_DEBUGGER_SUPPORT
+      ExternalReference debug_step_in_fp =
+          ExternalReference::debug_step_in_fp_address(isolate);
+      __ mov(r5, Operand(debug_step_in_fp));
+      __ LoadP(r5, MemOperand(r5));
+      __ cmpi(r5, Operand::Zero());
+      __ bne(&rt_call);
+#endif
+
+      // Load the initial map and verify that it is in fact a map.
+      // r4: constructor function
+      __ LoadP(r5, FieldMemOperand(r4,
+                                   JSFunction::kPrototypeOrInitialMapOffset));
+      __ JumpIfSmi(r5, &rt_call);
+      __ CompareObjectType(r5, r6, r7, MAP_TYPE);
+      __ bne(&rt_call);
+
+      // Check that the constructor is not constructing a JSFunction (see
+      // comments in Runtime_NewObject in runtime.cc). In which case the
+      // initial map's instance type would be JS_FUNCTION_TYPE.
+      // r4: constructor function
+      // r5: initial map
+      __ CompareInstanceType(r5, r6, JS_FUNCTION_TYPE);
+      __ beq(&rt_call);
+
+      if (count_constructions) {
+        Label allocate;
+        // Decrease generous allocation count.
+        __ LoadP(r6, FieldMemOperand(r4,
+                                     JSFunction::kSharedFunctionInfoOffset));
+        MemOperand constructor_count =
+            FieldMemOperand(r6, SharedFunctionInfo::kConstructionCountOffset);
+        __ lbz(r7, constructor_count);
+        __ addi(r7, r7, Operand(-1));
+        __ stb(r7, constructor_count);
+        __ cmpi(r7, Operand::Zero());
+        __ bne(&allocate);
+
+        __ push(r4);
+        __ push(r5);
+
+        __ push(r4);  // constructor
+        // The call will replace the stub, so the countdown is only done once.
+        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
+
+        __ pop(r5);
+        __ pop(r4);
+
+        __ bind(&allocate);
+      }
+
+      // Now allocate the JSObject on the heap.
+      // r4: constructor function
+      // r5: initial map
+      __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset));
+      __ AllocateInNewSpace(r6, r7, r8, r9, &rt_call, SIZE_IN_WORDS);
+
+      // Allocated the JSObject, now initialize the fields. Map is set to
+      // initial map and properties and elements are set to empty fixed array.
+      // r4: constructor function
+      // r5: initial map
+      // r6: object size
+      // r7: JSObject (not tagged)
+      __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex);
+      __ mr(r8, r7);
+      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
+      __ StoreP(r5, MemOperand(r8));
+      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
+      __ StorePU(r9, MemOperand(r8, kPointerSize));
+      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
+      __ StorePU(r9, MemOperand(r8, kPointerSize));
+      __ addi(r8, r8, Operand(kPointerSize));
+
+      // Fill all the in-object properties with the appropriate filler.
+      // r4: constructor function
+      // r5: initial map
+      // r6: object size (in words)
+      // r7: JSObject (not tagged)
+      // r8: First in-object property of JSObject (not tagged)
+      uint32_t byte;
+      __ ShiftLeftImm(r9, r6, Operand(kPointerSizeLog2));
+      __ add(r9, r7, r9);  // End of object.
+      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
+      __ LoadRoot(r10, Heap::kUndefinedValueRootIndex);
+      if (count_constructions) {
+        __ lwz(r3, FieldMemOperand(r5, Map::kInstanceSizesOffset));
+        // Fetch Map::kPreAllocatedPropertyFieldsByte field from r3
+        // and multiply by kPointerSizeLog2
+        STATIC_ASSERT(Map::kPreAllocatedPropertyFieldsByte < 4);
+        byte = Map::kPreAllocatedPropertyFieldsByte;
+#if __BYTE_ORDER == __BIG_ENDIAN
+        byte = 3 - byte;
+#endif
+        __ ExtractBitRange(r3, r3,
+                           ((byte + 1) * kBitsPerByte) - 1,
+                           byte * kBitsPerByte);
+        __ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2));
+        __ add(r3, r8, r3);
+        // r3: offset of first field after pre-allocated fields
+        if (FLAG_debug_code) {
+          __ cmp(r3, r9);
+          __ Assert(le, "Unexpected number of pre-allocated property fields.");
+        }
+        __ InitializeFieldsWithFiller(r8, r3, r10);
+        // To allow for truncation.
+        __ LoadRoot(r10, Heap::kOnePointerFillerMapRootIndex);
+      }
+      __ InitializeFieldsWithFiller(r8, r9, r10);
+
+      // Add the object tag to make the JSObject real, so that we can continue
+      // and jump into the continuation code at any time from now on. Any
+      // failures need to undo the allocation, so that the heap is in a
+      // consistent state and verifiable.
+      __ addi(r7, r7, Operand(kHeapObjectTag));
+
+      // Check if a non-empty properties array is needed. Continue with
+      // allocated object if not fall through to runtime call if it is.
+      // r4: constructor function
+      // r7: JSObject
+      // r8: start of next object (not tagged)
+      __ lbz(r6, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset));
+      // The field instance sizes contains both pre-allocated property fields
+      // and in-object properties.
+      __ lwz(r3, FieldMemOperand(r5, Map::kInstanceSizesOffset));
+      // Fetch Map::kPreAllocatedPropertyFieldsByte field from r3
+      STATIC_ASSERT(Map::kPreAllocatedPropertyFieldsByte < 4);
+      byte = Map::kPreAllocatedPropertyFieldsByte;
+#if __BYTE_ORDER == __BIG_ENDIAN
+      byte = 3 - byte;
+#endif
+      __ ExtractBitRange(r9, r3,
+                         ((byte + 1) * kBitsPerByte) - 1,
+                         byte * kBitsPerByte);
+      __ add(r6, r6, r9);
+      STATIC_ASSERT(Map::kInObjectPropertiesByte < 4);
+      byte = Map::kInObjectPropertiesByte;
+#if __BYTE_ORDER == __BIG_ENDIAN
+      byte = 3 - byte;
+#endif
+      __ ExtractBitRange(r9, r3,
+                         ((byte + 1) * kBitsPerByte) - 1,
+                         byte * kBitsPerByte);
+      __ sub(r6, r6, r9);  // roohack - sub order may be incorrect
+      __ cmpi(r6, Operand::Zero());
+
+      // Done if no extra properties are to be allocated.
+      __ beq(&allocated);
+      __ Assert(ge, "Property allocation count failed.");
+
+      // Scale the number of elements by pointer size and add the header for
+      // FixedArrays to the start of the next object calculation from above.
+      // r4: constructor
+      // r6: number of elements in properties array
+      // r7: JSObject
+      // r8: start of next object
+      __ addi(r3, r6, Operand(FixedArray::kHeaderSize / kPointerSize));
+      __ AllocateInNewSpace(
+          r3,
+          r8,
+          r9,
+          r5,
+          &undo_allocation,
+          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
+
+      // Initialize the FixedArray.
+      // r4: constructor
+      // r6: number of elements in properties array
+      // r7: JSObject
+      // r8: FixedArray (not tagged)
+      __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
+      __ mr(r5, r8);
+      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
+      __ StoreP(r9, MemOperand(r5));
+      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
+      __ SmiTag(r3, r6);
+      __ StorePU(r3, MemOperand(r5, kPointerSize));
+      __ addi(r5, r5, Operand(kPointerSize));
+
+      // Initialize the fields to undefined.
+      // r4: constructor function
+      // r5: First element of FixedArray (not tagged)
+      // r6: number of elements in properties array
+      // r7: JSObject
+      // r8: FixedArray (not tagged)
+      __ ShiftLeftImm(r9, r6, Operand(kPointerSizeLog2));
+      __ add(r9, r5, r9);  // End of object.
+      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
+      { Label loop, entry;
+        if (count_constructions) {
+          __ LoadRoot(r10, Heap::kUndefinedValueRootIndex);
+        } else if (FLAG_debug_code) {
+          __ LoadRoot(r11, Heap::kUndefinedValueRootIndex);
+          __ cmp(r10, r11);
+          __ Assert(eq, "Undefined value not loaded.");
+        }
+        __ b(&entry);
+        __ bind(&loop);
+        __ StoreP(r10, MemOperand(r5));
+        __ addi(r5, r5, Operand(kPointerSize));
+        __ bind(&entry);
+        __ cmp(r5, r9);
+        __ blt(&loop);
+      }
+
+      // Store the initialized FixedArray into the properties field of
+      // the JSObject
+      // r4: constructor function
+      // r7: JSObject
+      // r8: FixedArray (not tagged)
+      __ addi(r8, r8, Operand(kHeapObjectTag));  // Add the heap tag.
+      __ StoreP(r8, FieldMemOperand(r7, JSObject::kPropertiesOffset), r0);
+
+      // Continue with JSObject being successfully allocated
+      // r4: constructor function
+      // r7: JSObject
+      __ b(&allocated);
+
+      // Undo the setting of the new top so that the heap is verifiable. For
+      // example, the map's unused properties potentially do not match the
+      // allocated objects unused properties.
+      // r7: JSObject (previous new top)
+      __ bind(&undo_allocation);
+      __ UndoAllocationInNewSpace(r7, r8);
+    }
+
+    // Allocate the new receiver object using the runtime call.
+    // r4: constructor function
+    __ bind(&rt_call);
+    __ push(r4);  // argument for Runtime_NewObject
+    __ CallRuntime(Runtime::kNewObject, 1);
+    __ mr(r7, r3);
+
+    // Receiver for constructor call allocated.
+    // r7: JSObject
+    __ bind(&allocated);
+    __ push(r7);
+    __ push(r7);
+
+    // Reload the number of arguments and the constructor from the stack.
+    // sp[0]: receiver
+    // sp[1]: receiver
+    // sp[2]: constructor function
+    // sp[3]: number of arguments (smi-tagged)
+    __ LoadP(r4, MemOperand(sp, 2 * kPointerSize));
+    __ LoadP(r6, MemOperand(sp, 3 * kPointerSize));
+
+    // Set up pointer to last argument.
+    __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset));
+
+    // Set up number of arguments for function call below
+    __ SmiUntag(r3, r6);
+
+    // Copy arguments and receiver to the expression stack.
+    // r3: number of arguments
+    // r4: constructor function
+    // r5: address of last argument (caller sp)
+    // r6: number of arguments (smi-tagged)
+    // sp[0]: receiver
+    // sp[1]: receiver
+    // sp[2]: constructor function
+    // sp[3]: number of arguments (smi-tagged)
+    Label loop, no_args;
+    __ cmpi(r3, Operand::Zero());
+    __ beq(&no_args);
+    __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
+    __ mtctr(r3);
+    __ bind(&loop);
+    __ subi(ip, ip, Operand(kPointerSize));
+    __ LoadPX(r0, MemOperand(r5, ip));
+    __ push(r0);
+    __ bdnz(&loop);
+    __ bind(&no_args);
+
+    // Call the function.
+    // r3: number of arguments
+    // r4: constructor function
+    if (is_api_function) {
+      __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+      Handle<Code> code =
+          masm->isolate()->builtins()->HandleApiCallConstruct();
+      ParameterCount expected(0);
+      __ InvokeCode(code, expected, expected,
+                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
+    } else {
+      ParameterCount actual(r3);
+      __ InvokeFunction(r4, actual, CALL_FUNCTION,  // roohack
+                        NullCallWrapper(), CALL_AS_METHOD);
+    }
+
+    // Store offset of return address for deoptimizer.
+    if (!is_api_function && !count_constructions) {
+      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
+    }
+
+    // Restore context from the frame.
+    // r3: result
+    // sp[0]: receiver
+    // sp[1]: constructor function
+    // sp[2]: number of arguments (smi-tagged)
+    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+
+    // If the result is an object (in the ECMA sense), we should get rid
+    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
+    // on page 74.
+    Label use_receiver, exit;
+
+    // If the result is a smi, it is *not* an object in the ECMA sense.
+    // r3: result
+    // sp[0]: receiver (newly allocated object)
+    // sp[1]: constructor function
+    // sp[2]: number of arguments (smi-tagged)
+    __ JumpIfSmi(r3, &use_receiver);
+
+    // If the type of the result (stored in its map) is less than
+    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
+    __ CompareObjectType(r3, r6, r6, FIRST_SPEC_OBJECT_TYPE);
+    __ bge(&exit);
+
+    // Throw away the result of the constructor invocation and use the
+    // on-stack receiver as the result.
+    __ bind(&use_receiver);
+    __ LoadP(r3, MemOperand(sp));
+
+    // Remove receiver from the stack, remove caller arguments, and
+    // return.
+    __ bind(&exit);
+    // r3: result
+    // sp[0]: receiver (newly allocated object)
+    // sp[1]: constructor function
+    // sp[2]: number of arguments (smi-tagged)
+    __ LoadP(r4, MemOperand(sp, 2 * kPointerSize));
+
+    // Leave construct frame.
+  }
+
+  __ SmiToPtrArrayOffset(r4, r4);
+  __ add(sp, sp, r4);
+  __ addi(sp, sp, Operand(kPointerSize));
+  __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5);
+  __ blr();
+}
+
+
+void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
+  Generate_JSConstructStubHelper(masm, false, true);
+}
+
+
+void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
+  Generate_JSConstructStubHelper(masm, false, false);
+}
+
+
+void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
+  Generate_JSConstructStubHelper(masm, true, false);
+}
+
+
+static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
+                                             bool is_construct) {
+  // Called from Generate_JS_Entry
+  // r3: code entry
+  // r4: function
+  // r5: receiver
+  // r6: argc
+  // r7: argv
+  // r0,r8-r9, cp may be clobbered
+
+  // Clear the context before we push it when entering the internal frame.
+  __ li(cp, Operand(0, RelocInfo::NONE));
+
+  // Enter an internal frame.
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+    // Set up the context from the function argument.
+    __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+
+    __ InitializeRootRegister();
+
+    // Push the function and the receiver onto the stack.
+    __ push(r4);
+    __ push(r5);
+
+    // Copy arguments to the stack in a loop.
+    // r4: function
+    // r6: argc
+    // r7: argv, i.e. points to first arg
+    Label loop, entry;
+    __ ShiftLeftImm(r0, r6, Operand(kPointerSizeLog2));
+    __ add(r5, r7, r0);
+    // r5 points past last arg.
+    __ b(&entry);
+    __ bind(&loop);
+    __ LoadP(r8, MemOperand(r7));  // read next parameter
+    __ addi(r7, r7, Operand(kPointerSize));
+    __ LoadP(r0, MemOperand(r8));  // dereference handle
+    __ push(r0);  // push parameter
+    __ bind(&entry);
+    __ cmp(r7, r5);
+    __ bne(&loop);
+
+    // Initialize all JavaScript callee-saved registers, since they will be seen
+    // by the garbage collector as part of handlers.
+    __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
+    __ mr(r14, r7);
+    __ mr(r15, r7);
+    __ mr(r16, r7);
+    __ mr(r22, r7);  // hmmm, possibly should be reassigned to r17
+
+    // Invoke the code and pass argc as r3.
+    __ mr(r3, r6);
+    if (is_construct) {
+      CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
+      __ CallStub(&stub);
+    } else {
+      ParameterCount actual(r3);
+      __ InvokeFunction(r4, actual, CALL_FUNCTION,
+                        NullCallWrapper(), CALL_AS_METHOD);
+    }
+    // Exit the JS frame and remove the parameters (except function), and
+    // return.
+  }
+  __ blr();
+
+  // r3: result
+}
+
+
+void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
+  Generate_JSEntryTrampolineHelper(masm, false);
+}
+
+
+void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
+  Generate_JSEntryTrampolineHelper(masm, true);
+}
+
+
+void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
+  // Enter an internal frame.
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+    // Preserve the function.
+    __ push(r4);
+    // Push call kind information.
+    __ push(r8);
+
+    // Push the function on the stack as the argument to the runtime function.
+    __ push(r4);
+    __ CallRuntime(Runtime::kLazyCompile, 1);
+    // Calculate the entry point.
+    __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+    // Restore call kind information.
+    __ pop(r8);
+    // Restore saved function.
+    __ pop(r4);
+
+    // Tear down internal frame.
+  }
+
+  // Do a tail-call of the compiled function.
+  __ Jump(r5);
+}
+
+
+void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
+  // Enter an internal frame.
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+    // Preserve the function.
+    __ push(r4);
+    // Push call kind information.
+    __ push(r8);
+
+    // Push the function on the stack as the argument to the runtime function.
+    __ push(r4);
+    __ CallRuntime(Runtime::kLazyRecompile, 1);
+    // Calculate the entry point.
+    __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+    // Restore call kind information.
+    __ pop(r8);
+    // Restore saved function.
+    __ pop(r4);
+
+    // Tear down internal frame.
+  }
+
+  // Do a tail-call of the compiled function.
+  __ Jump(r5);
+}
+
+
+static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
+                                             Deoptimizer::BailoutType type) {
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    // Pass the function and deoptimization type to the runtime system.
+    __ LoadSmiLiteral(r3, Smi::FromInt(static_cast<int>(type)));
+    __ push(r3);
+    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
+  }
+
+  // Get the full codegen state from the stack and untag it -> r9.
+  __ LoadP(r9, MemOperand(sp, 0 * kPointerSize));
+  __ SmiUntag(r9);
+  // Switch on the state.
+  Label with_tos_register, unknown_state;
+  __ cmpi(r9, Operand(FullCodeGenerator::NO_REGISTERS));
+  __ bne(&with_tos_register);
+  __ addi(sp, sp, Operand(1 * kPointerSize));  // Remove state.
+  __ Ret();
+
+  __ bind(&with_tos_register);
+  __ LoadP(r3, MemOperand(sp, 1 * kPointerSize));
+  __ cmpi(r9, Operand(FullCodeGenerator::TOS_REG));
+  __ bne(&unknown_state);
+  __ addi(sp, sp, Operand(2 * kPointerSize));  // Remove state.
+  __ Ret();
+
+  __ bind(&unknown_state);
+  __ stop("no cases left");
+}
+
+
+void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
+  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
+}
+
+
+void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
+  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
+}
+
+
+void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
+  // For now, we are relying on the fact that Runtime::NotifyOSR
+  // doesn't do any garbage collection which allows us to save/restore
+  // the registers without worrying about which of them contain
+  // pointers. This seems a bit fragile.
+  __ mflr(r0);
+  RegList saved_regs =
+      (kJSCallerSaved | kCalleeSaved | r0.bit() | fp.bit()) & ~sp.bit();
+  __ MultiPush(saved_regs);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ CallRuntime(Runtime::kNotifyOSR, 0);
+  }
+  __ MultiPop(saved_regs);
+  __ mtlr(r0);
+  __ Ret();
+}
+
+
+void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
+  // Lookup the function in the JavaScript frame and push it as an
+  // argument to the on-stack replacement function.
+  __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(r3);
+    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
+  }
+
+  // If the result was -1 it means that we couldn't optimize the
+  // function. Just return and continue in the unoptimized version.
+  Label skip;
+  __ CmpSmiLiteral(r3, Smi::FromInt(-1), r0);
+  __ bne(&skip);
+  __ Ret();
+
+  __ bind(&skip);
+  // Untag the AST id and push it on the stack.
+  __ SmiUntag(r3);
+  __ push(r3);
+
+  // Generate the code for doing the frame-to-frame translation using
+  // the deoptimizer infrastructure.
+  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
+  generator.Generate();
+}
+
+
+void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
+  // 1. Make sure we have at least one argument.
+  // r3: actual number of arguments
+  { Label done;
+    __ cmpi(r3, Operand::Zero());
+    __ bne(&done);
+    __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+    __ push(r5);
+    __ addi(r3, r3, Operand(1));
+    __ bind(&done);
+  }
+
+  // 2. Get the function to call (passed as receiver) from the stack, check
+  //    if it is a function.
+  // r3: actual number of arguments
+  Label slow, non_function;
+  __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2));
+  __ add(r4, sp, r4);
+  __ LoadP(r4, MemOperand(r4));
+  __ JumpIfSmi(r4, &non_function);
+  __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE);
+  __ bne(&slow);
+
+  // 3a. Patch the first argument if necessary when calling a function.
+  // r3: actual number of arguments
+  // r4: function
+  Label shift_arguments;
+  __ li(r7, Operand(0, RelocInfo::NONE));  // indicate regular JS_FUNCTION
+  { Label convert_to_object, use_global_receiver, patch_receiver;
+    // Change context eagerly in case we need the global receiver.
+    __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+
+    // Do not transform the receiver for strict mode functions.
+    __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+    __ lwz(r6, FieldMemOperand(r5, SharedFunctionInfo::kCompilerHintsOffset));
+    __ TestBit(r6,
+#if V8_TARGET_ARCH_PPC64
+               SharedFunctionInfo::kStrictModeFunction,
+#else
+               SharedFunctionInfo::kStrictModeFunction + kSmiTagSize,
+#endif
+               r0);
+    __ bne(&shift_arguments, cr0);
+
+    // Do not transform the receiver for native (Compilerhints already in r6).
+    __ TestBit(r6,
+#if V8_TARGET_ARCH_PPC64
+               SharedFunctionInfo::kNative,
+#else
+               SharedFunctionInfo::kNative + kSmiTagSize,
+#endif
+               r0);
+    __ bne(&shift_arguments, cr0);
+
+    // Compute the receiver in non-strict mode.
+    __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
+    __ add(r5, sp, ip);
+    __ LoadP(r5, MemOperand(r5, -kPointerSize));
+    // r3: actual number of arguments
+    // r4: function
+    // r5: first argument
+    __ JumpIfSmi(r5, &convert_to_object);
+
+    __ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
+    __ cmp(r5, r6);
+    __ beq(&use_global_receiver);
+    __ LoadRoot(r6, Heap::kNullValueRootIndex);
+    __ cmp(r5, r6);
+    __ beq(&use_global_receiver);
+
+    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
+    __ CompareObjectType(r5, r6, r6, FIRST_SPEC_OBJECT_TYPE);
+    __ bge(&shift_arguments);
+
+    __ bind(&convert_to_object);
+
+    {
+      // Enter an internal frame in order to preserve argument count.
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      __ SmiTag(r3);
+      __ push(r3);
+
+      __ push(r5);
+      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ mr(r5, r3);
+
+      __ pop(r3);
+      __ SmiUntag(r3);
+
+      // Exit the internal frame.
+    }
+
+    // Restore the function to r4, and the flag to r7.
+    __ ShiftLeftImm(r7, r3, Operand(kPointerSizeLog2));
+    __ add(r7, sp, r7);
+    __ LoadP(r4, MemOperand(r7));
+    __ li(r7, Operand(0, RelocInfo::NONE));
+    __ b(&patch_receiver);
+
+    // Use the global receiver object from the called function as the
+    // receiver.
+    __ bind(&use_global_receiver);
+    const int kGlobalIndex =
+        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
+    __ LoadP(r5, FieldMemOperand(cp, kGlobalIndex));
+    __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kNativeContextOffset));
+    __ LoadP(r5, FieldMemOperand(r5, kGlobalIndex));
+    __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalReceiverOffset));
+
+    __ bind(&patch_receiver);
+    __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
+    __ add(r6, sp, ip);
+    __ StoreP(r5, MemOperand(r6, -kPointerSize));
+
+    __ b(&shift_arguments);
+  }
+
+  // 3b. Check for function proxy.
+  __ bind(&slow);
+  __ li(r7, Operand(1, RelocInfo::NONE));  // indicate function proxy
+  __ cmpi(r5, Operand(JS_FUNCTION_PROXY_TYPE));
+  __ beq(&shift_arguments);
+  __ bind(&non_function);
+  __ li(r7, Operand(2, RelocInfo::NONE));  // indicate non-function
+
+  // 3c. Patch the first argument when calling a non-function.  The
+  //     CALL_NON_FUNCTION builtin expects the non-function callee as
+  //     receiver, so overwrite the first argument which will ultimately
+  //     become the receiver.
+  // r3: actual number of arguments
+  // r4: function
+  // r7: call type (0: JS function, 1: function proxy, 2: non-function)
+  __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
+  __ add(r5, sp, ip);
+  __ StoreP(r4, MemOperand(r5, -kPointerSize));
+
+  // 4. Shift arguments and return address one slot down on the stack
+  //    (overwriting the original receiver).  Adjust argument count to make
+  //    the original first argument the new receiver.
+  // r3: actual number of arguments
+  // r4: function
+  // r7: call type (0: JS function, 1: function proxy, 2: non-function)
+  __ bind(&shift_arguments);
+  { Label loop;
+    // Calculate the copy start address (destination). Copy end address is sp.
+    __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2));
+    __ add(r5, sp, ip);
+
+    __ bind(&loop);
+    __ LoadP(ip, MemOperand(r5, -kPointerSize));
+    __ StoreP(ip, MemOperand(r5));
+    __ subi(r5, r5, Operand(kPointerSize));
+    __ cmp(r5, sp);
+    __ bne(&loop);
+    // Adjust the actual number of arguments and remove the top element
+    // (which is a copy of the last argument).
+    __ subi(r3, r3, Operand(1));
+    __ pop();
+  }
+
+  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
+  //     or a function proxy via CALL_FUNCTION_PROXY.
+  // r3: actual number of arguments
+  // r4: function
+  // r7: call type (0: JS function, 1: function proxy, 2: non-function)
+  { Label function, non_proxy;
+    __ cmpi(r7, Operand::Zero());
+    __ beq(&function);
+    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
+    __ li(r5, Operand(0, RelocInfo::NONE));
+    __ SetCallKind(r8, CALL_AS_METHOD);
+    __ cmpi(r7, Operand(1));
+    __ bne(&non_proxy);
+
+    __ push(r4);  // re-add proxy object as additional argument
+    __ addi(r3, r3, Operand(1));
+    __ GetBuiltinEntry(r6, Builtins::CALL_FUNCTION_PROXY);
+    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+            RelocInfo::CODE_TARGET);
+
+    __ bind(&non_proxy);
+    __ GetBuiltinEntry(r6, Builtins::CALL_NON_FUNCTION);
+    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+            RelocInfo::CODE_TARGET);
+    __ bind(&function);
+  }
+
+  // 5b. Get the code to call from the function and check that the number of
+  //     expected arguments matches what we're providing.  If so, jump
+  //     (tail-call) to the code in register edx without checking arguments.
+  // r3: actual number of arguments
+  // r4: function
+  __ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadWordArith(r5,
+         FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset));
+#if !defined(V8_TARGET_ARCH_PPC64)
+  __ SmiUntag(r5);
+#endif
+  __ LoadP(r6, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
+  __ SetCallKind(r8, CALL_AS_METHOD);
+  __ cmp(r5, r3);  // Check formal and actual parameter counts.
+  Label skip;
+  __ beq(&skip);
+  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+          RelocInfo::CODE_TARGET);
+
+  __ bind(&skip);
+  ParameterCount expected(0);
+  __ InvokeCode(r6, expected, expected, JUMP_FUNCTION,
+                NullCallWrapper(), CALL_AS_METHOD);
+}
+
+
+void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
+  const int kIndexOffset    = -5 * kPointerSize;
+  const int kLimitOffset    = -4 * kPointerSize;
+  const int kArgsOffset     =  2 * kPointerSize;
+  const int kRecvOffset     =  3 * kPointerSize;
+  const int kFunctionOffset =  4 * kPointerSize;
+
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+
+    __ LoadP(r3, MemOperand(fp, kFunctionOffset));  // get the function
+    __ push(r3);
+    __ LoadP(r3, MemOperand(fp, kArgsOffset));  // get the args array
+    __ push(r3);
+    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
+
+    // Check the stack for overflow. We are not trying to catch
+    // interruptions (e.g. debug break and preemption) here, so the "real stack
+    // limit" is checked.
+    Label okay;
+    __ LoadRoot(r5, Heap::kRealStackLimitRootIndex);
+    // Make r5 the space we have left. The stack might already be overflowed
+    // here which will cause r5 to become negative.
+    __ sub(r5, sp, r5);
+    // Check if the arguments will overflow the stack.
+    __ SmiToPtrArrayOffset(r0, r3);
+    __ cmp(r5, r0);
+    __ bgt(&okay);  // Signed comparison.
+
+    // Out of stack space.
+    __ LoadP(r4, MemOperand(fp, kFunctionOffset));
+    __ push(r4);
+    __ push(r3);
+    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
+    // End of stack check.
+
+    // Push current limit and index.
+    __ bind(&okay);
+    __ push(r3);  // limit
+    __ li(r4, Operand(0, RelocInfo::NONE));  // initial index
+    __ push(r4);
+
+    // Get the receiver.
+    __ LoadP(r3, MemOperand(fp, kRecvOffset));
+
+    // Check that the function is a JS function (otherwise it must be a proxy).
+    Label push_receiver;
+    __ LoadP(r4, MemOperand(fp, kFunctionOffset));
+    __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE);
+    __ bne(&push_receiver);
+
+    // Change context eagerly to get the right global object if necessary.
+    __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+    // Load the shared function info while the function is still in r4.
+    __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+
+    // Compute the receiver.
+    // Do not transform the receiver for strict mode functions.
+    Label call_to_object, use_global_receiver;
+    __ lwz(r5, FieldMemOperand(r5, SharedFunctionInfo::kCompilerHintsOffset));
+    __ TestBit(r5,
+#if V8_TARGET_ARCH_PPC64
+               SharedFunctionInfo::kStrictModeFunction,
+#else
+               SharedFunctionInfo::kStrictModeFunction + kSmiTagSize,
+#endif
+               r0);
+    __ bne(&push_receiver, cr0);
+
+    // Do not transform the receiver for strict mode functions.
+    __ TestBit(r5,
+#if V8_TARGET_ARCH_PPC64
+               SharedFunctionInfo::kNative,
+#else
+               SharedFunctionInfo::kNative + kSmiTagSize,
+#endif
+               r0);
+    __ bne(&push_receiver, cr0);
+
+    // Compute the receiver in non-strict mode.
+    __ JumpIfSmi(r3, &call_to_object);
+    __ LoadRoot(r4, Heap::kNullValueRootIndex);
+    __ cmp(r3, r4);
+    __ beq(&use_global_receiver);
+    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
+    __ cmp(r3, r4);
+    __ beq(&use_global_receiver);
+
+    // Check if the receiver is already a JavaScript object.
+    // r3: receiver
+    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
+    __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
+    __ bge(&push_receiver);
+
+    // Convert the receiver to a regular object.
+    // r3: receiver
+    __ bind(&call_to_object);
+    __ push(r3);
+    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ b(&push_receiver);
+
+    // Use the current global receiver object as the receiver.
+    __ bind(&use_global_receiver);
+    const int kGlobalOffset =
+        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
+    __ LoadP(r3, FieldMemOperand(cp, kGlobalOffset));
+    __ LoadP(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
+    __ LoadP(r3, FieldMemOperand(r3, kGlobalOffset));
+    __ LoadP(r3, FieldMemOperand(r3, GlobalObject::kGlobalReceiverOffset));
+
+    // Push the receiver.
+    // r3: receiver
+    __ bind(&push_receiver);
+    __ push(r3);
+
+    // Copy all arguments from the array to the stack.
+    Label entry, loop;
+    __ LoadP(r3, MemOperand(fp, kIndexOffset));
+    __ b(&entry);
+
+    // Load the current argument from the arguments array and push it to the
+    // stack.
+    // r3: current argument index
+    __ bind(&loop);
+    __ LoadP(r4, MemOperand(fp, kArgsOffset));
+    __ push(r4);
+    __ push(r3);
+
+    // Call the runtime to access the property in the arguments array.
+    __ CallRuntime(Runtime::kGetProperty, 2);
+    __ push(r3);
+
+    // Use inline caching to access the arguments.
+    __ LoadP(r3, MemOperand(fp, kIndexOffset));
+    __ AddSmiLiteral(r3, r3, Smi::FromInt(1), r0);
+    __ StoreP(r3, MemOperand(fp, kIndexOffset));
+
+    // Test if the copy loop has finished copying all the elements from the
+    // arguments object.
+    __ bind(&entry);
+    __ LoadP(r4, MemOperand(fp, kLimitOffset));
+    __ cmp(r3, r4);
+    __ bne(&loop);
+
+    // Invoke the function.
+    Label call_proxy;
+    ParameterCount actual(r3);
+    __ SmiUntag(r3);
+    __ LoadP(r4, MemOperand(fp, kFunctionOffset));
+    __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE);
+    __ bne(&call_proxy);
+    __ InvokeFunction(r4, actual, CALL_FUNCTION,
+                      NullCallWrapper(), CALL_AS_METHOD);
+
+    frame_scope.GenerateLeaveFrame();
+    __ addi(sp, sp, Operand(3 * kPointerSize));
+    __ blr();
+
+    // Invoke the function proxy.
+    __ bind(&call_proxy);
+    __ push(r4);  // add function proxy as last argument
+    __ addi(r3, r3, Operand(1));
+    __ li(r5, Operand(0, RelocInfo::NONE));
+    __ SetCallKind(r8, CALL_AS_METHOD);
+    __ GetBuiltinEntry(r6, Builtins::CALL_FUNCTION_PROXY);
+    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+            RelocInfo::CODE_TARGET);
+
+    // Tear down the internal frame and remove function, receiver and args.
+  }
+  __ addi(sp, sp, Operand(3 * kPointerSize));
+  __ blr();
+}
+
+
+static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
+  __ SmiTag(r3);
+  __ LoadSmiLiteral(r7, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  __ mflr(r0);
+  __ push(r0);
+  __ Push(fp, r7, r4, r3);
+  __ addi(fp, sp, Operand(3 * kPointerSize));
+}
+
+
+static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3 : result being passed through
+  // -----------------------------------
+  // Get the number of arguments passed (as a smi), tear down the frame and
+  // then tear down the parameters.
+  __ LoadP(r4, MemOperand(fp, -3 * kPointerSize));
+  __ mr(sp, fp);
+  __ LoadP(fp, MemOperand(sp));
+  __ LoadP(r0, MemOperand(sp, kPointerSize));
+  __ mtlr(r0);
+  __ SmiToPtrArrayOffset(r0, r4);
+  __ add(sp, sp, r0);
+  __ addi(sp, sp, Operand(3 * kPointerSize));  // adjust for receiver + fp + lr
+}
+
+
+void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3 : actual number of arguments
+  //  -- r4 : function (passed through to callee)
+  //  -- r5 : expected number of arguments
+  //  -- r6 : code entry to call
+  //  -- r8 : call kind information
+  // -----------------------------------
+
+  Label invoke, dont_adapt_arguments;
+
+  Label enough, too_few;
+  __ cmp(r3, r5);
+  __ blt(&too_few);
+  __ cmpi(r5, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
+  __ beq(&dont_adapt_arguments);
+
+  {  // Enough parameters: actual >= expected
+    __ bind(&enough);
+    EnterArgumentsAdaptorFrame(masm);
+
+    // Calculate copy start address into r3 and copy end address into r5.
+    // r3: actual number of arguments as a smi
+    // r4: function
+    // r5: expected number of arguments
+    // r6: code entry to call
+    __ SmiToPtrArrayOffset(r3, r3);
+    __ add(r3, r3, fp);
+    // adjust for return address and receiver
+    __ addi(r3, r3, Operand(2 * kPointerSize));
+    __ ShiftLeftImm(r5, r5, Operand(kPointerSizeLog2));
+    __ sub(r5, r3, r5);
+
+    // Copy the arguments (including the receiver) to the new stack frame.
+    // r3: copy start address
+    // r4: function
+    // r5: copy end address
+    // r6: code entry to call
+
+    Label copy;
+    __ bind(&copy);
+    __ LoadP(ip, MemOperand(r3, 0));
+    __ push(ip);
+    __ cmp(r3, r5);  // Compare before moving to next argument.
+    __ subi(r3, r3, Operand(kPointerSize));
+    __ bne(&copy);
+
+    __ b(&invoke);
+  }
+
+  {  // Too few parameters: Actual < expected
+    __ bind(&too_few);
+    EnterArgumentsAdaptorFrame(masm);
+
+    // Calculate copy start address into r0 and copy end address is fp.
+    // r3: actual number of arguments as a smi
+    // r4: function
+    // r5: expected number of arguments
+    // r6: code entry to call
+    __ SmiToPtrArrayOffset(r3, r3);
+    __ add(r3, r3, fp);
+
+    // Copy the arguments (including the receiver) to the new stack frame.
+    // r3: copy start address
+    // r4: function
+    // r5: expected number of arguments
+    // r6: code entry to call
+    Label copy;
+    __ bind(&copy);
+    // Adjust load for return address and receiver.
+    __ LoadP(ip, MemOperand(r3, 2 * kPointerSize));
+    __ push(ip);
+    __ cmp(r3, fp);  // Compare before moving to next argument.
+    __ subi(r3, r3, Operand(kPointerSize));
+    __ bne(&copy);
+
+    // Fill the remaining expected arguments with undefined.
+    // r4: function
+    // r5: expected number of arguments
+    // r6: code entry to call
+    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+    __ ShiftLeftImm(r5, r5, Operand(kPointerSizeLog2));
+    __ sub(r5, fp, r5);
+    __ subi(r5, r5, Operand(4 * kPointerSize));  // Adjust for frame.
+
+    Label fill;
+    __ bind(&fill);
+    __ push(ip);
+    __ cmp(sp, r5);
+    __ bne(&fill);
+  }
+
+  // Call the entry point.
+  __ bind(&invoke);
+  __ Call(r6);
+
+  // Store offset of return address for deoptimizer.
+  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
+
+  // Exit frame and return.
+  LeaveArgumentsAdaptorFrame(masm);
+  __ blr();
+
+
+  // -------------------------------------------
+  // Dont adapt arguments.
+  // -------------------------------------------
+  __ bind(&dont_adapt_arguments);
+  __ Jump(r6);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc
new file mode 100644
index 0000000..fe52630
--- /dev/null
+++ b/src/ppc/code-stubs-ppc.cc
@@ -0,0 +1,7530 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "bootstrapper.h"
+#include "code-stubs.h"
+#include "regexp-macro-assembler.h"
+#include "ppc/regexp-macro-assembler-ppc.h"
+
+namespace v8 {
+namespace internal {
+
+
+#define __ ACCESS_MASM(masm)
+
+static void EmitIdenticalObjectComparison(MacroAssembler* masm,
+                                          Label* slow,
+                                          Condition cond,
+                                          bool never_nan_nan);
+static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+                                    Register lhs,
+                                    Register rhs,
+                                    Label* lhs_not_nan,
+                                    Label* slow,
+                                    bool strict);
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+                                           Register lhs,
+                                           Register rhs);
+
+
+// Check if the operand is a heap number.
+static void EmitCheckForHeapNumber(MacroAssembler* masm, Register operand,
+                                   Register scratch1, Register scratch2,
+                                   Label* not_a_heap_number) {
+  __ LoadP(scratch1, FieldMemOperand(operand, HeapObject::kMapOffset));
+  __ LoadRoot(scratch2, Heap::kHeapNumberMapRootIndex);
+  __ cmp(scratch1, scratch2);
+  __ bne(not_a_heap_number);
+}
+
+
+void ToNumberStub::Generate(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in eax.
+  Label check_heap_number, call_builtin;
+  __ JumpIfNotSmi(r3, &check_heap_number);
+  __ Ret();
+
+  __ bind(&check_heap_number);
+  EmitCheckForHeapNumber(masm, r3, r4, ip, &call_builtin);
+  __ Ret();
+
+  __ bind(&call_builtin);
+  __ push(r3);
+  __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
+}
+
+
+void FastNewClosureStub::Generate(MacroAssembler* masm) {
+  // Create a new closure from the given function info in new
+  // space. Set the context to the current context in cp.
+  Counters* counters = masm->isolate()->counters();
+
+  Label gc;
+
+  // Pop the function info from the stack.
+  __ pop(r6);
+
+  // Attempt to allocate new JSFunction in new space.
+  __ AllocateInNewSpace(JSFunction::kSize,
+                        r3,
+                        r4,
+                        r5,
+                        &gc,
+                        TAG_OBJECT);
+
+  __ IncrementCounter(counters->fast_new_closure_total(), 1, r9, r10);
+
+  int map_index = (language_mode_ == CLASSIC_MODE)
+      ? Context::FUNCTION_MAP_INDEX
+      : Context::STRICT_MODE_FUNCTION_MAP_INDEX;
+
+  // Compute the function map in the current native context and set that
+  // as the map of the allocated object.
+  __ LoadP(r5,
+           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kNativeContextOffset));
+  __ LoadP(r8, MemOperand(r5, Context::SlotOffset(map_index)));
+  __ StoreP(r8, FieldMemOperand(r3, HeapObject::kMapOffset), r0);
+
+  // Initialize the rest of the function. We don't have to update the
+  // write barrier because the allocated object is in new space.
+  __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex);
+  __ LoadRoot(r8, Heap::kTheHoleValueRootIndex);
+  __ StoreP(r4, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0);
+  __ StoreP(r4, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
+  __ StoreP(r8, FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset),
+            r0);
+  __ StoreP(r6, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset), r0);
+  __ StoreP(cp, FieldMemOperand(r3, JSFunction::kContextOffset), r0);
+  __ StoreP(r4, FieldMemOperand(r3, JSFunction::kLiteralsOffset), r0);
+
+  // Initialize the code pointer in the function to be the one
+  // found in the shared function info object.
+  // But first check if there is an optimized version for our context.
+  Label check_optimized;
+  Label install_unoptimized;
+  if (FLAG_cache_optimized_code) {
+    __ LoadP(r4,
+             FieldMemOperand(r6, SharedFunctionInfo::kOptimizedCodeMapOffset));
+    __ cmpi(r4, Operand::Zero());
+    __ bne(&check_optimized);
+  }
+  __ bind(&install_unoptimized);
+  __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
+  __ StoreP(r7, FieldMemOperand(r3, JSFunction::kNextFunctionLinkOffset), r0);
+  __ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kCodeOffset));
+  __ addi(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ StoreP(r6, FieldMemOperand(r3, JSFunction::kCodeEntryOffset), r0);
+
+  // Return result. The argument function info has been popped already.
+  __ Ret();
+
+  __ bind(&check_optimized);
+
+  __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1, r9, r10);
+
+  // r5 holds native context, r4 points to fixed array of 3-element entries
+  // (native context, optimized code, literals).
+  // The optimized code map must never be empty, so check the first elements.
+  Label install_optimized;
+  // Speculatively move code object into r7
+  __ LoadP(r7, FieldMemOperand(r4, FixedArray::kHeaderSize + kPointerSize));
+  __ LoadP(r8, FieldMemOperand(r4, FixedArray::kHeaderSize));
+  __ cmp(r5, r8);
+  __ beq(&install_optimized);
+
+  // Iterate through the rest of map backwards.  r7 holds an index as a Smi.
+  Label loop;
+  __ LoadP(r7, FieldMemOperand(r4, FixedArray::kLengthOffset));
+  __ bind(&loop);
+  // Do not double check first entry.
+
+  __ CmpSmiLiteral(r7, Smi::FromInt(SharedFunctionInfo::kEntryLength), r0);
+  __ beq(&install_unoptimized);
+  // Skip an entry.
+  __ SubSmiLiteral(r7, r7, Smi::FromInt(SharedFunctionInfo::kEntryLength), r0);
+  __ addi(r8, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ SmiToPtrArrayOffset(r9, r7);
+  __ LoadPX(r8, MemOperand(r8, r9));
+  __ cmp(r5, r8);
+  __ bne(&loop);
+  // Hit: fetch the optimized code.
+  // TODO(penguin): potential to use x-form for this sequence
+  __ addi(r8, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ SmiToPtrArrayOffset(r9, r7);
+  __ add(r8, r8, r9);
+  __ LoadPU(r7, MemOperand(r8, kPointerSize));
+
+  __ bind(&install_optimized);
+  __ IncrementCounter(counters->fast_new_closure_install_optimized(),
+                      1, r9, r10);
+
+  // TODO(fschneider): Idea: store proper code pointers in the map and either
+  // unmangle them on marking or do nothing as the whole map is discarded on
+  // major GC anyway.
+  __ addi(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ StoreP(r7, FieldMemOperand(r3, JSFunction::kCodeEntryOffset), r0);
+
+  // Now link a function into a list of optimized functions.
+  __ LoadP(r7, ContextOperand(r5, Context::OPTIMIZED_FUNCTIONS_LIST));
+
+  __ StoreP(r7, FieldMemOperand(r3, JSFunction::kNextFunctionLinkOffset), r0);
+  // No need for write barrier as JSFunction (eax) is in the new space.
+
+  __ StoreP(r3, ContextOperand(r5, Context::OPTIMIZED_FUNCTIONS_LIST), r0);
+  // Store JSFunction (eax) into edx before issuing write barrier as
+  // it clobbers all the registers passed.
+  __ mr(r7, r3);
+  __ RecordWriteContextSlot(
+      r5,
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST),
+      r7,
+      r4,
+      kLRHasNotBeenSaved,
+      kDontSaveFPRegs);
+
+  // Return result. The argument function info has been popped already.
+  __ Ret();
+
+  // Create a new closure through the slower runtime call.
+  __ bind(&gc);
+  __ LoadRoot(r7, Heap::kFalseValueRootIndex);
+  __ Push(cp, r6, r7);
+  __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
+}
+
+
+void FastNewContextStub::Generate(MacroAssembler* masm) {
+  // Try to allocate the context in new space.
+  Label gc;
+  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
+
+  // Attempt to allocate the context in new space.
+  __ AllocateInNewSpace(FixedArray::SizeFor(length),
+                        r3,
+                        r4,
+                        r5,
+                        &gc,
+                        TAG_OBJECT);
+
+  // Load the function from the stack.
+  __ LoadP(r6, MemOperand(sp, 0));
+
+  // Set up the object header.
+  __ LoadRoot(r4, Heap::kFunctionContextMapRootIndex);
+  __ LoadSmiLiteral(r5, Smi::FromInt(length));
+  __ StoreP(r5, FieldMemOperand(r3, FixedArray::kLengthOffset), r0);
+  __ StoreP(r4, FieldMemOperand(r3, HeapObject::kMapOffset), r0);
+
+  // Set up the fixed slots, copy the global object from the previous context.
+  __ LoadP(r5,
+           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ LoadSmiLiteral(r4, Smi::FromInt(0));
+  __ StoreP(r6, MemOperand(r3, Context::SlotOffset(Context::CLOSURE_INDEX)),
+            r0);
+  __ StoreP(cp, MemOperand(r3, Context::SlotOffset(Context::PREVIOUS_INDEX)),
+            r0);
+  __ StoreP(r4, MemOperand(r3, Context::SlotOffset(Context::EXTENSION_INDEX)),
+            r0);
+  __ StoreP(r5,
+            MemOperand(r3, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)),
+            r0);
+
+  // Initialize the rest of the slots to undefined.
+  __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
+  for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
+    __ StoreP(r4, MemOperand(r3, Context::SlotOffset(i)), r0);
+  }
+
+  // Remove the on-stack argument and return.
+  __ mr(cp, r3);
+  __ pop();
+  __ Ret();
+
+  // Need to collect. Call into runtime system.
+  __ bind(&gc);
+  __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
+}
+
+
+void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
+  // Stack layout on entry:
+  //
+  // [sp]: function.
+  // [sp + kPointerSize]: serialized scope info
+
+  // Try to allocate the context in new space.
+  Label gc;
+  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
+  __ AllocateInNewSpace(FixedArray::SizeFor(length),
+                        r3, r4, r5, &gc, TAG_OBJECT);
+
+  // Load the function from the stack.
+  __ LoadP(r6, MemOperand(sp, 0));
+
+  // Load the serialized scope info from the stack.
+  __ LoadP(r4, MemOperand(sp, 1 * kPointerSize));
+
+  // Set up the object header.
+  __ LoadRoot(r5, Heap::kBlockContextMapRootIndex);
+  __ StoreP(r5, FieldMemOperand(r3, HeapObject::kMapOffset), r0);
+  __ LoadSmiLiteral(r5, Smi::FromInt(length));
+  __ StoreP(r5, FieldMemOperand(r3, FixedArray::kLengthOffset), r0);
+
+  // If this block context is nested in the native context we get a smi
+  // sentinel instead of a function. The block context should get the
+  // canonical empty function of the native context as its closure which
+  // we still have to look up.
+  Label after_sentinel;
+  __ JumpIfNotSmi(r6, &after_sentinel);
+  if (FLAG_debug_code) {
+    const char* message = "Expected 0 as a Smi sentinel";
+    __ cmpi(r6, Operand::Zero());
+    __ Assert(eq, message);
+  }
+  __ LoadP(r6, GlobalObjectOperand());
+  __ LoadP(r6, FieldMemOperand(r6, GlobalObject::kNativeContextOffset));
+  __ LoadP(r6, ContextOperand(r6, Context::CLOSURE_INDEX));
+  __ bind(&after_sentinel);
+
+  // Set up the fixed slots, copy the global object from the previous context.
+  __ LoadP(r5, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ StoreP(r6, ContextOperand(r3, Context::CLOSURE_INDEX), r0);
+  __ StoreP(cp, ContextOperand(r3, Context::PREVIOUS_INDEX), r0);
+  __ StoreP(r4, ContextOperand(r3, Context::EXTENSION_INDEX), r0);
+  __ StoreP(r5, ContextOperand(r3, Context::GLOBAL_OBJECT_INDEX), r0);
+
+  // Initialize the rest of the slots to the hole value.
+  __ LoadRoot(r4, Heap::kTheHoleValueRootIndex);
+  for (int i = 0; i < slots_; i++) {
+    __ StoreP(r4, ContextOperand(r3, i + Context::MIN_CONTEXT_SLOTS), r0);
+  }
+
+  // Remove the on-stack argument and return.
+  __ mr(cp, r3);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ Ret();
+
+  // Need to collect. Call into runtime system.
+  __ bind(&gc);
+  __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
+}
+
+
+static void GenerateFastCloneShallowArrayCommon(
+    MacroAssembler* masm,
+    int length,
+    FastCloneShallowArrayStub::Mode mode,
+    Label* fail) {
+  // Registers on entry:
+  //
+  // r6: boilerplate literal array.
+  ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS);
+
+  // All sizes here are multiples of kPointerSize.
+  int elements_size = 0;
+  if (length > 0) {
+    elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
+        ? FixedDoubleArray::SizeFor(length)
+        : FixedArray::SizeFor(length);
+  }
+  int size = JSArray::kSize + elements_size;
+
+  // Allocate both the JS array and the elements array in one big
+  // allocation. This avoids multiple limit checks.
+  __ AllocateInNewSpace(size,
+                        r3,
+                        r4,
+                        r5,
+                        fail,
+                        TAG_OBJECT);
+
+  // Copy the JS array part.
+  for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
+    if ((i != JSArray::kElementsOffset) || (length == 0)) {
+      __ LoadP(r4, FieldMemOperand(r6, i));
+      __ StoreP(r4, FieldMemOperand(r3, i), r0);
+    }
+  }
+
+  if (length > 0) {
+    // Get hold of the elements array of the boilerplate and setup the
+    // elements pointer in the resulting object.
+    __ LoadP(r6, FieldMemOperand(r6, JSArray::kElementsOffset));
+    __ addi(r5, r3, Operand(JSArray::kSize));
+    __ StoreP(r5, FieldMemOperand(r3, JSArray::kElementsOffset), r0);
+
+    // Copy the elements array.
+    ASSERT((elements_size % kPointerSize) == 0);
+    __ CopyFields(r5, r6, r4.bit(), elements_size / kPointerSize);
+  }
+}
+
+void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
+  // Stack layout on entry:
+  //
+  // [sp]: constant elements.
+  // [sp + kPointerSize]: literal index.
+  // [sp + (2 * kPointerSize)]: literals array.
+
+  // Load boilerplate object into r3 and check if we need to create a
+  // boilerplate.
+  Label slow_case;
+  __ LoadP(r6, MemOperand(sp, 2 * kPointerSize));
+  __ LoadP(r3, MemOperand(sp, 1 * kPointerSize));
+  __ addi(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+
+  __ mr(r0, r3);
+  __ SmiToPtrArrayOffset(r3, r3);
+  __ LoadPX(r6, MemOperand(r6, r3));
+  __ mr(r3, r0);
+
+  __ CompareRoot(r6, Heap::kUndefinedValueRootIndex);
+  __ beq(&slow_case);
+
+  FastCloneShallowArrayStub::Mode mode = mode_;
+  if (mode == CLONE_ANY_ELEMENTS) {
+    Label double_elements, check_fast_elements;
+    __ LoadP(r3, FieldMemOperand(r6, JSArray::kElementsOffset));
+    __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ CompareRoot(r3, Heap::kFixedCOWArrayMapRootIndex);
+    __ bne(&check_fast_elements);
+    GenerateFastCloneShallowArrayCommon(masm, 0,
+                                        COPY_ON_WRITE_ELEMENTS, &slow_case);
+    // Return and remove the on-stack parameters.
+    __ addi(sp, sp, Operand(3 * kPointerSize));
+    __ Ret();
+
+    __ bind(&check_fast_elements);
+    __ CompareRoot(r3, Heap::kFixedArrayMapRootIndex);
+    __ bne(&double_elements);
+    GenerateFastCloneShallowArrayCommon(masm, length_,
+                                        CLONE_ELEMENTS, &slow_case);
+    // Return and remove the on-stack parameters.
+    __ addi(sp, sp, Operand(3 * kPointerSize));
+    __ Ret();
+
+    __ bind(&double_elements);
+    mode = CLONE_DOUBLE_ELEMENTS;
+    // Fall through to generate the code to handle double elements.
+  }
+
+  if (FLAG_debug_code) {
+    const char* message;
+    Heap::RootListIndex expected_map_index;
+    if (mode == CLONE_ELEMENTS) {
+      message = "Expected (writable) fixed array";
+      expected_map_index = Heap::kFixedArrayMapRootIndex;
+    } else if (mode == CLONE_DOUBLE_ELEMENTS) {
+      message = "Expected (writable) fixed double array";
+      expected_map_index = Heap::kFixedDoubleArrayMapRootIndex;
+    } else {
+      ASSERT(mode == COPY_ON_WRITE_ELEMENTS);
+      message = "Expected copy-on-write fixed array";
+      expected_map_index = Heap::kFixedCOWArrayMapRootIndex;
+    }
+    __ push(r6);
+    __ LoadP(r6, FieldMemOperand(r6, JSArray::kElementsOffset));
+    __ LoadP(r6, FieldMemOperand(r6, HeapObject::kMapOffset));
+    __ CompareRoot(r6, expected_map_index);
+    __ Assert(eq, message);
+    __ pop(r6);
+  }
+
+  GenerateFastCloneShallowArrayCommon(masm, length_, mode, &slow_case);
+
+  // Return and remove the on-stack parameters.
+  __ addi(sp, sp, Operand(3 * kPointerSize));
+  __ Ret();
+
+  __ bind(&slow_case);
+  __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
+}
+
+
+void FastCloneShallowObjectStub::Generate(MacroAssembler* masm) {
+  // Stack layout on entry:
+  //
+  // [sp]: object literal flags.
+  // [sp + kPointerSize]: constant properties.
+  // [sp + (2 * kPointerSize)]: literal index.
+  // [sp + (3 * kPointerSize)]: literals array.
+
+  // Load boilerplate object into r3 and check if we need to create a
+  // boilerplate.
+  Label slow_case;
+  __ LoadP(r6, MemOperand(sp, 3 * kPointerSize));
+  __ LoadP(r3, MemOperand(sp, 2 * kPointerSize));
+  __ addi(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ mr(r0, r3);
+  __ SmiToPtrArrayOffset(r3, r3);
+  __ LoadPX(r6, MemOperand(r6, r3));
+  __ mr(r3, r0);
+
+  __ CompareRoot(r6, Heap::kUndefinedValueRootIndex);
+  __ beq(&slow_case);
+
+  // Check that the boilerplate contains only fast properties and we can
+  // statically determine the instance size.
+  int size = JSObject::kHeaderSize + length_ * kPointerSize;
+  __ LoadP(r3, FieldMemOperand(r6, HeapObject::kMapOffset));
+  __ lbz(r3, FieldMemOperand(r3, Map::kInstanceSizeOffset));
+  __ cmpi(r3, Operand(size >> kPointerSizeLog2));
+  __ bne(&slow_case);
+
+  // Allocate the JS object and copy header together with all in-object
+  // properties from the boilerplate.
+  __ AllocateInNewSpace(size, r3, r4, r5, &slow_case, TAG_OBJECT);
+  for (int i = 0; i < size; i += kPointerSize) {
+    __ LoadP(r4, FieldMemOperand(r6, i));
+    __ StoreP(r4, FieldMemOperand(r3, i), r0);
+  }
+
+  // Return and remove the on-stack parameters.
+  __ addi(sp, sp, Operand(4 * kPointerSize));
+  __ Ret();
+
+  __ bind(&slow_case);
+  __ TailCallRuntime(Runtime::kCreateObjectLiteralShallow, 4, 1);
+}
+
+
+// Takes a Smi and converts to an IEEE 64 bit floating point value in two
+// registers.  The format is 1 sign bit, 11 exponent bits (biased 1023) and
+// 52 fraction bits (20 in the first word, 32 in the second).  Zeros is a
+// scratch register.  Destroys the source register.  No GC occurs during this
+// stub so you don't have to set up the frame.
+class ConvertToDoubleStub : public CodeStub {
+ public:
+  ConvertToDoubleStub(Register result_reg_1,
+                      Register result_reg_2,
+                      Register source_reg,
+                      Register scratch_reg)
+      : result1_(result_reg_1),
+        result2_(result_reg_2),
+        source_(source_reg),
+        zeros_(scratch_reg) { }
+
+ private:
+  Register result1_;
+  Register result2_;
+  Register source_;
+  Register zeros_;
+
+  // Minor key encoding in 16 bits.
+  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+  class OpBits: public BitField<Token::Value, 2, 14> {};
+
+  Major MajorKey() { return ConvertToDouble; }
+  int MinorKey() {
+    // Encode the parameters in a unique 16 bit value.
+    return  result1_.code() +
+           (result2_.code() << 4) +
+           (source_.code() << 8) +
+           (zeros_.code() << 12);
+  }
+
+  void Generate(MacroAssembler* masm);
+};
+
+void FloatingPointHelper::LoadSmis(MacroAssembler* masm,
+                                   Register scratch1,
+                                   Register scratch2) {
+  __ SmiToDoubleFPRegister(r3, d2, scratch1);
+  __ SmiToDoubleFPRegister(r4, d1, scratch1);
+}
+
+// needs cleanup for extra parameters that are unused
+void FloatingPointHelper::LoadOperands(
+    MacroAssembler* masm,
+    Register heap_number_map,
+    Register scratch1,
+    Register scratch2,
+    Label* slow) {
+  // Load right operand (r3) to d2
+  LoadNumber(masm, r3, d2, heap_number_map, scratch1, scratch2, slow);
+
+  // Load left operand (r4) to d1
+  LoadNumber(masm, r4, d1, heap_number_map, scratch1, scratch2, slow);
+}
+
+// needs cleanup for extra parameters that are unused
+// also needs a scratch double register instead of d3
+void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
+                                     Register object,
+                                     DwVfpRegister dst,
+                                     Register heap_number_map,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     Label* not_number) {
+  __ AssertRootValue(heap_number_map,
+                     Heap::kHeapNumberMapRootIndex,
+                     "HeapNumberMap register clobbered.");
+
+  Label is_smi, done;
+
+  // Smi-check
+  __ UntagAndJumpIfSmi(scratch1, object, &is_smi);
+  // Heap number check
+  __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
+
+  // Handle loading a double from a heap number
+  // Load the double from tagged HeapNumber to double register.
+  __ lfd(dst, FieldMemOperand(object, HeapNumber::kValueOffset));
+  __ b(&done);
+
+  // Handle loading a double from a smi.
+  __ bind(&is_smi);
+
+  // Convert untagged smi to double using FP instructions.
+  FloatingPointHelper::ConvertIntToDouble(masm, scratch1, dst);
+
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
+                                               Register object,
+                                               Register dst,
+                                               Register heap_number_map,
+                                               Register scratch1,
+                                               Register scratch2,
+                                               Register scratch3,
+                                               DwVfpRegister double_scratch,
+                                               Label* not_number) {
+  __ AssertRootValue(heap_number_map,
+                     Heap::kHeapNumberMapRootIndex,
+                     "HeapNumberMap register clobbered.");
+  Label done;
+  Label not_in_int32_range;
+
+  __ UntagAndJumpIfSmi(dst, object, &done);
+  __ LoadP(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
+  __ cmp(scratch1, heap_number_map);
+  __ bne(not_number);
+  __ ConvertToInt32(object,
+                    dst,
+                    scratch1,
+                    scratch2,
+                    double_scratch,
+                    &not_in_int32_range);
+  __ b(&done);
+
+  __ bind(&not_in_int32_range);
+  __ lwz(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
+  __ lwz(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
+
+  __ EmitOutOfInt32RangeTruncate(dst,
+                                 scratch1,
+                                 scratch2,
+                                 scratch3);
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
+                                             Register src,
+                                             DwVfpRegister double_dst) {
+  ASSERT(!src.is(r0));
+
+  __ subi(sp, sp, Operand(8));  // reserve one temporary double on the stack
+
+  // sign-extend src to 64-bit and store it to temp double on the stack
+#if V8_TARGET_ARCH_PPC64
+  __ extsw(r0, src);
+  __ std(r0, MemOperand(sp, 0));
+#else
+  __ srawi(r0, src, 31);
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ stw(r0, MemOperand(sp, 4));
+  __ stw(src, MemOperand(sp, 0));
+#else
+  __ stw(r0, MemOperand(sp, 0));
+  __ stw(src, MemOperand(sp, 4));
+#endif
+#endif
+
+  // load into FPR
+  __ lfd(double_dst, MemOperand(sp, 0));
+
+  __ addi(sp, sp, Operand(8));  // restore stack
+
+  // convert to double
+  __ fcfid(double_dst, double_dst);
+}
+
+
+void FloatingPointHelper::ConvertUnsignedIntToDouble(MacroAssembler* masm,
+                                                     Register src,
+                                                     DwVfpRegister double_dst) {
+  ASSERT(!src.is(r0));
+
+  __ subi(sp, sp, Operand(8));  // reserve one temporary double on the stack
+
+  // zero-extend src to 64-bit and store it to temp double on the stack
+#if V8_TARGET_ARCH_PPC64
+  __ clrldi(r0, src, Operand(32));
+  __ std(r0, MemOperand(sp, 0));
+#else
+  __ li(r0, Operand::Zero());
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ stw(r0, MemOperand(sp, 4));
+  __ stw(src, MemOperand(sp, 0));
+#else
+  __ stw(r0, MemOperand(sp, 0));
+  __ stw(src, MemOperand(sp, 4));
+#endif
+#endif
+
+  // load into FPR
+  __ lfd(double_dst, MemOperand(sp, 0));
+
+  __ addi(sp, sp, Operand(8));  // restore stack
+
+  // convert to double
+  __ fcfid(double_dst, double_dst);
+}
+
+void FloatingPointHelper::ConvertIntToFloat(MacroAssembler* masm,
+                                            const DwVfpRegister dst,
+                                            const Register src,
+                                            const Register int_scratch) {
+  __ subi(sp, sp, Operand(8));  // reserve one temporary double on the stack
+
+  // sign-extend src to 64-bit and store it to temp double on the stack
+#if V8_TARGET_ARCH_PPC64
+  __ extsw(int_scratch, src);
+  __ std(int_scratch, MemOperand(sp, 0));
+#else
+  __ srawi(int_scratch, src, 31);
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ stw(int_scratch, MemOperand(sp, 4));
+  __ stw(src, MemOperand(sp, 0));
+#else
+  __ stw(int_scratch, MemOperand(sp, 0));
+  __ stw(src, MemOperand(sp, 4));
+#endif
+#endif
+
+  // load sign-extended src into FPR
+  __ lfd(dst, MemOperand(sp, 0));
+
+  __ addi(sp, sp, Operand(8));  // restore stack
+
+  __ fcfid(dst, dst);
+  __ frsp(dst, dst);
+}
+
+void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
+                                                  Register object,
+                                                  DwVfpRegister double_dst,
+                                                  DwVfpRegister double_scratch,
+                                                  Register heap_number_map,
+                                                  Register scratch1,
+                                                  Register scratch2,
+                                                  Label* not_int32) {
+  ASSERT(!scratch1.is(object) && !scratch2.is(object));
+  ASSERT(!scratch1.is(scratch2));
+  ASSERT(!heap_number_map.is(object) &&
+         !heap_number_map.is(scratch1) &&
+         !heap_number_map.is(scratch2));
+
+  Label done, obj_is_not_smi;
+
+  __ JumpIfNotSmi(object, &obj_is_not_smi);
+  __ SmiUntag(scratch1, object);
+  ConvertIntToDouble(masm, scratch1, double_dst);
+  __ b(&done);
+
+  __ bind(&obj_is_not_smi);
+  __ AssertRootValue(heap_number_map,
+                     Heap::kHeapNumberMapRootIndex,
+                     "HeapNumberMap register clobbered.");
+  __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
+
+  // Load the double value.
+  __ lfd(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset));
+
+  __ EmitVFPTruncate(kRoundToZero,
+                     scratch1,
+                     double_dst,
+                     scratch2,
+                     double_scratch,
+                     kCheckForInexactConversion);
+
+  // Jump to not_int32 if the operation did not succeed.
+  __ bne(not_int32);
+
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
+                                            Register object,
+                                            Register dst,
+                                            Register heap_number_map,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Register scratch3,
+                                            DwVfpRegister double_scratch0,
+                                            DwVfpRegister double_scratch1,
+                                            Label* not_int32) {
+  ASSERT(!dst.is(object));
+  ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
+  ASSERT(!scratch1.is(scratch2) &&
+         !scratch1.is(scratch3) &&
+         !scratch2.is(scratch3));
+
+  Label done;
+
+  __ UntagAndJumpIfSmi(dst, object, &done);
+
+  __ AssertRootValue(heap_number_map,
+                     Heap::kHeapNumberMapRootIndex,
+                     "HeapNumberMap register clobbered.");
+  __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
+
+  // Load the double value.
+  __ lfd(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset));
+
+  __ EmitVFPTruncate(kRoundToZero,
+                     dst,
+                     double_scratch0,
+                     scratch1,
+                     double_scratch1,
+                     kCheckForInexactConversion);
+
+  // Jump to not_int32 if the operation did not succeed.
+  __ bne(not_int32);
+
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm,
+                                               Register src1,
+                                               Register src2,
+                                               Register dst,
+                                               Register scratch,
+                                               Label* not_int32) {
+  // Get exponent alone in scratch.
+  STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u);
+  __ ExtractBitMask(scratch, src1, HeapNumber::kExponentMask);
+
+  // Substract the bias from the exponent.
+  __ addi(scratch, scratch, Operand(-HeapNumber::kExponentBias));
+
+  // src1: higher (exponent) part of the double value.
+  // src2: lower (mantissa) part of the double value.
+  // scratch: unbiased exponent.
+
+  // Fast cases. Check for obvious non 32-bit integer values.
+  // Negative exponent cannot yield 32-bit integers.
+  __ cmpi(scratch, Operand::Zero());
+  __ blt(not_int32);
+  // Exponent greater than 31 cannot yield 32-bit integers.
+  // Also, a positive value with an exponent equal to 31 is outside of the
+  // signed 32-bit integer range.
+  // Another way to put it is that if (exponent - signbit) > 30 then the
+  // number cannot be represented as an int32.
+  Register tmp = dst;
+  __ ExtractSignBit32(tmp, src1);
+  __ sub(tmp, scratch, tmp);
+  __ cmpi(tmp, Operand(30));
+  __ bgt(not_int32);
+  // - Check whether bits [21:0] in the mantissa are not null.
+  __ TestBitRange(src2, 21, 0, r0);
+  __ bne(not_int32, cr0);
+
+  // Otherwise the exponent needs to be big enough to shift left all the
+  // non zero bits left. So we need the (30 - exponent) last bits of the
+  // 31 higher bits of the mantissa to be null.
+  // Because bits [21:0] are null, we can check instead that the
+  // (32 - exponent) last bits of the 32 higher bits of the mantissa are null.
+
+  // Get the 32 higher bits of the mantissa in dst.
+  STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord == 20);
+  STATIC_ASSERT(HeapNumber::kNonMantissaBitsInTopWord == 12);
+  __ ExtractBitRange(dst, src2, 31, HeapNumber::kMantissaBitsInTopWord);
+  __ slwi(src1, src1, Operand(HeapNumber::kNonMantissaBitsInTopWord));
+  __ orx(dst, dst, src1);
+
+  // Create the mask and test the lower bits (of the higher bits).
+  __ subfic(scratch, scratch, Operand(32));
+  __ li(src2, Operand(1));
+  __ ShiftLeft(src1, src2, scratch);
+  __ addi(src1, src1, Operand(-1));
+  __ and_(r0, dst, src1, SetRC);
+  __ bne(not_int32, cr0);
+}
+
+
+void FloatingPointHelper::CallCCodeForDoubleOperation(
+    MacroAssembler* masm,
+    Token::Value op,
+    Register heap_number_result,
+    Register scratch) {
+  // d1 - first arg, d2 - second arg
+  // d1 return value
+
+  // Assert that heap_number_result is callee-saved.
+  // PowerPC doesn't preserve r8.. need to handle this specially
+  // We currently always use r8 to pass it.
+  ASSERT(heap_number_result.is(r8));
+  __ push(r8);
+
+  // Push the current return address before the C call. Return will be
+  // through pop() below.
+  __ mflr(r0);
+  __ push(r0);
+  __ PrepareCallCFunction(0, 2, scratch);
+
+  {
+    AllowExternalCallThatCantCauseGC scope(masm);
+    __ CallCFunction(
+        ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2);
+  }
+  // load saved r8 value, restore lr
+  __ pop(r0);
+  __ mtlr(r0);
+  __ pop(r8);
+
+  // Store answer in the overwritable heap number. Double returned in d1
+  __ stfd(d1, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
+
+  // Place heap_number_result in r3 and return to the pushed return address.
+  __ mr(r3, heap_number_result);
+  __ blr();
+}
+
+// Handle the case where the lhs and rhs are the same object.
+// Equality is almost reflexive (everything but NaN), so this is a test
+// for "identity and not NaN".
+static void EmitIdenticalObjectComparison(MacroAssembler* masm,
+                                          Label* slow,
+                                          Condition cond,
+                                          bool never_nan_nan) {
+  Label not_identical;
+  Label heap_number, return_equal;
+  __ cmp(r3, r4);
+  __ bne(&not_identical);
+
+  // The two objects are identical.  If we know that one of them isn't NaN then
+  // we now know they test equal.
+  if (cond != eq || !never_nan_nan) {
+    // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
+    // so we do the second best thing - test it ourselves.
+    // They are both equal and they are not both Smis so both of them are not
+    // Smis.  If it's not a heap number, then return equal.
+    if (cond == lt || cond == gt) {
+      __ CompareObjectType(r3, r7, r7, FIRST_SPEC_OBJECT_TYPE);
+      __ bge(slow);
+    } else {
+      __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE);
+      __ beq(&heap_number);
+      // Comparing JS objects with <=, >= is complicated.
+      if (cond != eq) {
+        __ cmpi(r7, Operand(FIRST_SPEC_OBJECT_TYPE));
+        __ bge(slow);
+        // Normally here we fall through to return_equal, but undefined is
+        // special: (undefined == undefined) == true, but
+        // (undefined <= undefined) == false!  See ECMAScript 11.8.5.
+        if (cond == le || cond == ge) {
+          __ cmpi(r7, Operand(ODDBALL_TYPE));
+          __ bne(&return_equal);
+          __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+          __ cmp(r3, r5);
+          __ bne(&return_equal);
+          if (cond == le) {
+            // undefined <= undefined should fail.
+            __ li(r3, Operand(GREATER));
+          } else  {
+            // undefined >= undefined should fail.
+            __ li(r3, Operand(LESS));
+          }
+          __ Ret();
+        }
+      }
+    }
+  }
+
+  __ bind(&return_equal);
+  if (cond == lt) {
+    __ li(r3, Operand(GREATER));  // Things aren't less than themselves.
+  } else if (cond == gt) {
+    __ li(r3, Operand(LESS));     // Things aren't greater than themselves.
+  } else {
+    __ li(r3, Operand(EQUAL));    // Things are <=, >=, ==, === themselves.
+  }
+  __ Ret();
+
+  if (cond != eq || !never_nan_nan) {
+    // For less and greater we don't have to check for NaN since the result of
+    // x < x is false regardless.  For the others here is some code to check
+    // for NaN.
+    if (cond != lt && cond != gt) {
+      __ bind(&heap_number);
+      // It is a heap number, so return non-equal if it's NaN and equal if it's
+      // not NaN.
+
+      // The representation of NaN values has all exponent bits (52..62) set,
+      // and not all mantissa bits (0..51) clear.
+      // Read top bits of double representation (second word of value).
+      __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+      // Test that exponent bits are all set.
+      STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u);
+      __ ExtractBitMask(r6, r5, HeapNumber::kExponentMask);
+      __ cmpli(r6, Operand(0x7ff));
+      __ bne(&return_equal);
+
+      // Shift out flag and all exponent bits, retaining only mantissa.
+      __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord));
+      // Or with all low-bits of mantissa.
+      __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
+      __ orx(r3, r6, r5);
+      __ cmpi(r3, Operand::Zero());
+      // For equal we already have the right value in r3:  Return zero (equal)
+      // if all bits in mantissa are zero (it's an Infinity) and non-zero if
+      // not (it's a NaN).  For <= and >= we need to load r0 with the failing
+      // value if it's a NaN.
+      if (cond != eq) {
+        Label not_equal;
+        __ bne(&not_equal);
+        // All-zero means Infinity means equal.
+        __ Ret();
+        __ bind(&not_equal);
+        if (cond == le) {
+          __ li(r3, Operand(GREATER));  // NaN <= NaN should fail.
+        } else {
+          __ li(r3, Operand(LESS));     // NaN >= NaN should fail.
+        }
+      }
+      __ Ret();
+    }
+    // No fall through here.
+  }
+
+  __ bind(&not_identical);
+}
+
+
+// See comment at call site.
+static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+                                    Register lhs,
+                                    Register rhs,
+                                    Label* lhs_not_nan,
+                                    Label* slow,
+                                    bool strict) {
+  ASSERT((lhs.is(r3) && rhs.is(r4)) ||
+         (lhs.is(r4) && rhs.is(r3)));
+
+  Label rhs_is_smi;
+  __ JumpIfSmi(rhs, &rhs_is_smi);
+
+  // Lhs is a Smi.  Check whether the rhs is a heap number.
+  __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE);
+  if (strict) {
+    // If rhs is not a number and lhs is a Smi then strict equality cannot
+    // succeed.  Return non-equal
+    // If rhs is r3 then there is already a non zero value in it.
+    Label skip;
+    __ beq(&skip);
+    if (!rhs.is(r3)) {
+      __ mov(r3, Operand(NOT_EQUAL));
+    }
+    __ Ret();
+    __ bind(&skip);
+  } else {
+    // Smi compared non-strictly with a non-Smi non-heap-number.  Call
+    // the runtime.
+    __ bne(slow);
+  }
+
+  // Lhs is a smi, rhs is a number.
+  // Convert lhs to a double in d7.
+  __ SmiToDoubleFPRegister(lhs, d7, r10);
+  // Load the double from rhs, tagged HeapNumber r3, to d6.
+  __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
+
+  // We now have both loaded as doubles but we can skip the lhs nan check
+  // since it's a smi.
+  __ b(lhs_not_nan);
+
+  __ bind(&rhs_is_smi);
+  // Rhs is a smi.  Check whether the non-smi lhs is a heap number.
+  __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE);
+  if (strict) {
+    // If lhs is not a number and rhs is a smi then strict equality cannot
+    // succeed.  Return non-equal.
+    // If lhs is r3 then there is already a non zero value in it.
+    Label skip;
+    __ beq(&skip);
+    if (!lhs.is(r3)) {
+      __ mov(r3, Operand(NOT_EQUAL));
+    }
+    __ Ret();
+    __ bind(&skip);
+  } else {
+    // Smi compared non-strictly with a non-smi non-heap-number.  Call
+    // the runtime.
+    __ bne(slow);
+  }
+
+  // Rhs is a smi, lhs is a heap number.
+  // Load the double from lhs, tagged HeapNumber r4, to d7.
+  __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
+  // Convert rhs to a double in d6.
+  __ SmiToDoubleFPRegister(rhs, d6, r10);
+  // Fall through to both_loaded_as_doubles.
+}
+
+// See comment at call site.
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+                                           Register lhs,
+                                           Register rhs) {
+    ASSERT((lhs.is(r3) && rhs.is(r4)) ||
+           (lhs.is(r4) && rhs.is(r3)));
+
+    // If either operand is a JS object or an oddball value, then they are
+    // not equal since their pointers are different.
+    // There is no test for undetectability in strict equality.
+    STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
+    Label first_non_object;
+    // Get the type of the first operand into r5 and compare it with
+    // FIRST_SPEC_OBJECT_TYPE.
+    __ CompareObjectType(rhs, r5, r5, FIRST_SPEC_OBJECT_TYPE);
+    __ blt(&first_non_object);
+
+    // Return non-zero (r3 is not zero)
+    Label return_not_equal;
+    __ bind(&return_not_equal);
+    __ Ret();
+
+    __ bind(&first_non_object);
+    // Check for oddballs: true, false, null, undefined.
+    __ cmpi(r5, Operand(ODDBALL_TYPE));
+    __ beq(&return_not_equal);
+
+    __ CompareObjectType(lhs, r6, r6, FIRST_SPEC_OBJECT_TYPE);
+    __ bge(&return_not_equal);
+
+    // Check for oddballs: true, false, null, undefined.
+    __ cmpi(r6, Operand(ODDBALL_TYPE));
+    __ beq(&return_not_equal);
+
+    // Now that we have the types we might as well check for symbol-symbol.
+    // Ensure that no non-strings have the symbol bit set.
+    STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
+    STATIC_ASSERT(kSymbolTag != 0);
+    __ and_(r5, r5, r6);
+    __ andi(r0, r5, Operand(kIsSymbolMask));
+    __ bne(&return_not_equal, cr0);
+}
+
+
+static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
+                                       Register lhs,
+                                       Register rhs,
+                                       Label* both_loaded_as_doubles,
+                                       Label* not_heap_numbers,
+                                       Label* slow) {
+  ASSERT((lhs.is(r3) && rhs.is(r4)) ||
+         (lhs.is(r4) && rhs.is(r3)));
+
+  __ CompareObjectType(rhs, r6, r5, HEAP_NUMBER_TYPE);
+  __ bne(not_heap_numbers);
+  __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset));
+  __ cmp(r5, r6);
+  __ bne(slow);  // First was a heap number, second wasn't.  Go slow case.
+
+  // Both are heap numbers.  Load them up then jump to the code we have
+  // for that.
+  __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
+  __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
+
+  __ b(both_loaded_as_doubles);
+}
+
+
+// Fast negative check for symbol-to-symbol equality.
+static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
+                                         Register lhs,
+                                         Register rhs,
+                                         Label* possible_strings,
+                                         Label* not_both_strings) {
+  ASSERT((lhs.is(r3) && rhs.is(r4)) ||
+         (lhs.is(r4) && rhs.is(r3)));
+
+  // r5 is object type of rhs.
+  // Ensure that no non-strings have the symbol bit set.
+  Label object_test;
+  STATIC_ASSERT(kSymbolTag != 0);
+  __ andi(r0, r5, Operand(kIsNotStringMask));
+  __ bne(&object_test, cr0);
+  __ andi(r0, r5, Operand(kIsSymbolMask));
+  __ beq(possible_strings, cr0);
+  __ CompareObjectType(lhs, r6, r6, FIRST_NONSTRING_TYPE);
+  __ bge(not_both_strings);
+  __ andi(r0, r6, Operand(kIsSymbolMask));
+  __ beq(possible_strings, cr0);
+
+  // Both are symbols.  We already checked they weren't the same pointer
+  // so they are not equal.
+  __ li(r3, Operand(NOT_EQUAL));
+  __ Ret();
+
+  __ bind(&object_test);
+  __ cmpi(r5, Operand(FIRST_SPEC_OBJECT_TYPE));
+  __ blt(not_both_strings);
+  __ CompareObjectType(lhs, r5, r6, FIRST_SPEC_OBJECT_TYPE);
+  __ blt(not_both_strings);
+  // If both objects are undetectable, they are equal. Otherwise, they
+  // are not equal, since they are different objects and an object is not
+  // equal to undefined.
+  __ LoadP(r6, FieldMemOperand(rhs, HeapObject::kMapOffset));
+  __ lbz(r5, FieldMemOperand(r5, Map::kBitFieldOffset));
+  __ lbz(r6, FieldMemOperand(r6, Map::kBitFieldOffset));
+  __ and_(r3, r5, r6);
+  __ andi(r3, r3, Operand(1 << Map::kIsUndetectable));
+  __ xori(r3, r3, Operand(1 << Map::kIsUndetectable));
+  __ Ret();
+}
+
+
+void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
+                                                         Register object,
+                                                         Register result,
+                                                         Register scratch1,
+                                                         Register scratch2,
+                                                         Register scratch3,
+                                                         bool object_is_smi,
+                                                         Label* not_found) {
+  // Use of registers. Register result is used as a temporary.
+  Register number_string_cache = result;
+  Register mask = scratch3;
+
+  // Load the number string cache.
+  __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
+
+  // Make the hash mask from the length of the number string cache. It
+  // contains two elements (number and string) for each cache entry.
+  __ LoadP(mask, FieldMemOperand(number_string_cache,
+                                 FixedArray::kLengthOffset));
+  // Divide length by two (length is a smi).
+  __ ShiftRightArithImm(mask, mask, kSmiTagSize + kSmiShiftSize + 1);
+  __ subi(mask, mask, Operand(1));  // Make mask.
+
+  // Calculate the entry in the number string cache. The hash value in the
+  // number string cache for smis is just the smi value, and the hash for
+  // doubles is the xor of the upper and lower words. See
+  // Heap::GetNumberStringCache.
+  Isolate* isolate = masm->isolate();
+  Label is_smi;
+  Label load_result_from_cache;
+  if (!object_is_smi) {
+    __ JumpIfSmi(object, &is_smi);
+
+    __ CheckMap(object,
+                scratch1,
+                Heap::kHeapNumberMapRootIndex,
+                not_found,
+                DONT_DO_SMI_CHECK);
+
+    STATIC_ASSERT(8 == kDoubleSize);
+    __ lwz(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
+    __ lwz(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
+    __ xor_(scratch1, scratch1, scratch2);
+    __ and_(scratch1, scratch1, mask);
+
+    // Calculate address of entry in string cache: each entry consists
+    // of two pointer sized fields.
+    __ ShiftLeftImm(scratch1, scratch1, Operand(kPointerSizeLog2 + 1));
+    __ add(scratch1, number_string_cache, scratch1);
+
+    Register probe = mask;
+    __ LoadP(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
+    __ JumpIfSmi(probe, not_found);
+    __ lfd(d0, FieldMemOperand(object, HeapNumber::kValueOffset));
+    __ lfd(d1, FieldMemOperand(probe, HeapNumber::kValueOffset));
+    __ fcmpu(d0, d1);
+    __ bne(not_found);  // The cache did not contain this value.
+    __ b(&load_result_from_cache);
+  }
+
+  __ bind(&is_smi);
+  Register scratch = scratch1;
+  __ SmiUntag(scratch, object);
+  __ and_(scratch, mask, scratch);
+  // Calculate address of entry in string cache: each entry consists
+  // of two pointer sized fields.
+  __ ShiftLeftImm(scratch, scratch, Operand(kPointerSizeLog2 + 1));
+  __ add(scratch, number_string_cache, scratch);
+
+  // Check if the entry is the smi we are looking for.
+  Register probe = mask;
+  __ LoadP(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
+  __ cmp(object, probe);
+  __ bne(not_found);
+
+  // Get the result from the cache.
+  __ bind(&load_result_from_cache);
+  __ LoadP(result,
+         FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
+  __ IncrementCounter(isolate->counters()->number_to_string_native(),
+                      1,
+                      scratch1,
+                      scratch2);
+}
+
+
+void NumberToStringStub::Generate(MacroAssembler* masm) {
+  Label runtime;
+
+  __ LoadP(r4, MemOperand(sp, 0));
+
+  // Generate code to lookup number in the number string cache.
+  GenerateLookupNumberStringCache(masm, r4, r3, r5, r6, r7, false, &runtime);
+  __ addi(sp, sp, Operand(1 * kPointerSize));
+  __ Ret();
+
+  __ bind(&runtime);
+  // Handle number to string in the runtime system if not found in the cache.
+  __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
+}
+
+
+// On entry lhs_ and rhs_ are the values to be compared.
+// On exit r3 is 0, positive or negative to indicate the result of
+// the comparison.
+void CompareStub::Generate(MacroAssembler* masm) {
+  ASSERT((lhs_.is(r3) && rhs_.is(r4)) ||
+         (lhs_.is(r4) && rhs_.is(r3)));
+
+  Label slow;  // Call builtin.
+  Label not_smis, both_loaded_as_doubles, lhs_not_nan;
+
+  if (include_smi_compare_) {
+    Label not_two_smis, smi_done;
+    __ orx(r5, r4, r3);
+    __ JumpIfNotSmi(r5, &not_two_smis);
+    __ SmiUntag(r4);
+    __ SmiUntag(r3);
+    __ sub(r3, r4, r3);
+    __ Ret();
+    __ bind(&not_two_smis);
+  } else if (FLAG_debug_code) {
+    __ orx(r5, r4, r3);
+    STATIC_ASSERT(kSmiTagMask < 0x8000);
+    __ andi(r0, r5, Operand(kSmiTagMask));
+    __ Assert(ne, "CompareStub: unexpected smi operands.", cr0);
+  }
+
+  // NOTICE! This code is only reached after a smi-fast-case check, so
+  // it is certain that at least one operand isn't a smi.
+
+  // Handle the case where the objects are identical.  Either returns the answer
+  // or goes to slow.  Only falls through if the objects were not identical.
+  EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
+
+  // If either is a Smi (we know that not both are), then they can only
+  // be strictly equal if the other is a HeapNumber.
+  STATIC_ASSERT(kSmiTag == 0);
+  ASSERT_EQ(0, Smi::FromInt(0));
+  __ and_(r5, lhs_, rhs_);
+  __ JumpIfNotSmi(r5, &not_smis);
+  // One operand is a smi.  EmitSmiNonsmiComparison generates code that can:
+  // 1) Return the answer.
+  // 2) Go to slow.
+  // 3) Fall through to both_loaded_as_doubles.
+  // 4) Jump to lhs_not_nan.
+  // In cases 3 and 4 we have found out we were dealing with a number-number
+  // comparison.  The double values of the numbers have been loaded
+  // into d7 and d6.
+  EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_);
+
+  __ bind(&both_loaded_as_doubles);
+  // The arguments have been converted to doubles and stored in d6 and d7
+  Isolate* isolate = masm->isolate();
+  __ bind(&lhs_not_nan);
+  Label no_nan;
+  __ fcmpu(d7, d6);
+
+  Label nan, equal, less_than;
+  __ bunordered(&nan);
+  __ beq(&equal);
+  __ blt(&less_than);
+  __ li(r3, Operand(GREATER));
+  __ Ret();
+  __ bind(&equal);
+  __ li(r3, Operand(EQUAL));
+  __ Ret();
+  __ bind(&less_than);
+  __ li(r3, Operand(LESS));
+  __ Ret();
+
+  __ bind(&nan);
+  // If one of the sides was a NaN then the v flag is set.  Load r3 with
+  // whatever it takes to make the comparison fail, since comparisons with NaN
+  // always fail.
+  if (cc_ == lt || cc_ == le) {
+    __ li(r3, Operand(GREATER));
+  } else {
+    __ li(r3, Operand(LESS));
+  }
+  __ Ret();
+
+  __ bind(&not_smis);
+  // At this point we know we are dealing with two different objects,
+  // and neither of them is a Smi.  The objects are in rhs_ and lhs_.
+  if (strict_) {
+    // This returns non-equal for some object types, or falls through if it
+    // was not lucky.
+    EmitStrictTwoHeapObjectCompare(masm, lhs_, rhs_);
+  }
+
+  Label check_for_symbols;
+  Label flat_string_check;
+  // Check for heap-number-heap-number comparison.  Can jump to slow case,
+  // or load both doubles into r3, r4, r5, r6 and jump to the code that handles
+  // that case.  If the inputs are not doubles then jumps to check_for_symbols.
+  // In this case r5 will contain the type of rhs_.  Never falls through.
+  EmitCheckForTwoHeapNumbers(masm,
+                             lhs_,
+                             rhs_,
+                             &both_loaded_as_doubles,
+                             &check_for_symbols,
+                             &flat_string_check);
+
+  __ bind(&check_for_symbols);
+  // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
+  // symbols.
+  if (cc_ == eq && !strict_) {
+    // Returns an answer for two symbols or two detectable objects.
+    // Otherwise jumps to string case or not both strings case.
+    // Assumes that r5 is the type of rhs_ on entry.
+    EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow);
+  }
+
+  // Check for both being sequential ASCII strings, and inline if that is the
+  // case.
+  __ bind(&flat_string_check);
+
+  __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r5, r6, &slow);
+
+  __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r5, r6);
+  if (cc_ == eq) {
+    StringCompareStub::GenerateFlatAsciiStringEquals(masm,
+                                                     lhs_,
+                                                     rhs_,
+                                                     r5,
+                                                     r6);
+  } else {
+    StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
+                                                       lhs_,
+                                                       rhs_,
+                                                       r5,
+                                                       r6,
+                                                       r7);
+  }
+  // Never falls through to here.
+
+  __ bind(&slow);
+
+  __ Push(lhs_, rhs_);
+  // Figure out which native to call and setup the arguments.
+  Builtins::JavaScript native;
+  if (cc_ == eq) {
+    native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
+  } else {
+    native = Builtins::COMPARE;
+    int ncr;  // NaN compare result
+    if (cc_ == lt || cc_ == le) {
+      ncr = GREATER;
+    } else {
+      ASSERT(cc_ == gt || cc_ == ge);  // remaining cases
+      ncr = LESS;
+    }
+    __ LoadSmiLiteral(r3, Smi::FromInt(ncr));
+    __ push(r3);
+  }
+
+  // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
+  // tagged as a small integer.
+  __ InvokeBuiltin(native, JUMP_FUNCTION);
+}
+
+
+// The stub expects its argument in the tos_ register and returns its result in
+// it, too: zero for false, and a non-zero value for true.
+void ToBooleanStub::Generate(MacroAssembler* masm) {
+  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
+  // we cannot call anything that could cause a GC from this stub.
+  Label patch;
+  const Register map = r22.is(tos_) ? r10 : r22;
+
+  // undefined -> false.
+  CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
+
+  // Boolean -> its value.
+  CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
+  CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
+
+  // 'null' -> false.
+  CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
+
+  if (types_.Contains(SMI)) {
+    // Smis: 0 -> false, all other -> true
+    Label not_smi;
+    __ JumpIfNotSmi(tos_,  &not_smi);
+    // tos_ contains the correct return value already
+    __ Ret();
+    __ bind(&not_smi);
+  } else if (types_.NeedsMap()) {
+    // If we need a map later and have a Smi -> patch.
+    __ JumpIfSmi(tos_, &patch);
+  }
+
+  if (types_.NeedsMap()) {
+    __ LoadP(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
+
+    if (types_.CanBeUndetectable()) {
+      Label not_undetectable;
+      __ lbz(ip, FieldMemOperand(map, Map::kBitFieldOffset));
+      STATIC_ASSERT((1 << Map::kIsUndetectable) < 0x8000);
+      __ andi(r0, ip, Operand(1 << Map::kIsUndetectable));
+      __ beq(&not_undetectable, cr0);
+      // Undetectable -> false.
+      __ li(tos_, Operand(0, RelocInfo::NONE));
+      __ Ret();
+      __ bind(&not_undetectable);
+    }
+  }
+
+  if (types_.Contains(SPEC_OBJECT)) {
+    // Spec object -> true.
+    Label not_js_object;
+    __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
+    // tos_ contains the correct non-zero return value already.
+    __ blt(&not_js_object);
+    __ Ret();
+    __ bind(&not_js_object);
+  }
+
+  if (types_.Contains(STRING)) {
+    // String value -> false iff empty.
+    Label not_string;
+    __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
+    __ bge(&not_string);
+    __ LoadP(tos_, FieldMemOperand(tos_, String::kLengthOffset));
+    __ Ret();  // the string length is OK as the return value
+    __ bind(&not_string);
+  }
+
+  if (types_.Contains(HEAP_NUMBER)) {
+    // Heap number -> false iff +0, -0, or NaN.
+    Label not_heap_number, nan_or_zero;
+    __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+    __ bne(&not_heap_number);
+
+    __ lfd(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
+    __ li(r0, Operand::Zero());
+    __ push(r0);
+#if !V8_TARGET_ARCH_PPC64
+    __ push(r0);
+#endif
+    __ lfd(d2, MemOperand(sp, 0));
+    __ addi(sp, sp, Operand(8));
+    __ fcmpu(d1, d2);
+    // "tos_" is a register, and contains a non zero value by default.
+    // Hence we only need to overwrite "tos_" with zero to return false for
+    // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
+    __ bunordered(&nan_or_zero);
+    __ beq(&nan_or_zero);
+    __ Ret();
+
+    __ bind(&nan_or_zero);
+    __ li(tos_, Operand::Zero());
+    __ Ret();
+
+    __ bind(&not_heap_number);
+  }
+
+  __ bind(&patch);
+  GenerateTypeTransition(masm);
+}
+
+
+void ToBooleanStub::CheckOddball(MacroAssembler* masm,
+                                 Type type,
+                                 Heap::RootListIndex value,
+                                 bool result) {
+  if (types_.Contains(type)) {
+    // If we see an expected oddball, return its ToBoolean value tos_.
+    Label different_value;
+    __ LoadRoot(ip, value);
+    __ cmp(tos_, ip);
+    __ bne(&different_value);
+    // The value of a root is never NULL, so we can avoid loading a non-null
+    // value into tos_ when we want to return 'true'.
+    if (!result) {
+      __ li(tos_, Operand(0, RelocInfo::NONE));
+    }
+    // Intel has some logic here not present on ARM
+    // unclear if it's needed or not
+    __ Ret();
+    __ bind(&different_value);
+  }
+}
+
+
+void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
+  if (!tos_.is(r6)) {
+    __ mr(r6, tos_);
+  }
+  __ LoadSmiLiteral(r5, Smi::FromInt(tos_.code()));
+  __ LoadSmiLiteral(r4, Smi::FromInt(types_.ToByte()));
+  __ Push(r6, r5, r4);
+  // Patch the caller to an appropriate specialized stub and return the
+  // operation result to the caller of the stub.
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
+      3,
+      1);
+}
+
+
+void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
+  // We don't allow a GC during a store buffer overflow so there is no need to
+  // store the registers in any particular way, but we do have to store and
+  // restore them.
+  __ mflr(r0);
+  __ MultiPush(kJSCallerSaved | r0.bit());
+  if (save_doubles_ == kSaveFPRegs) {
+    const int kNumRegs = DwVfpRegister::kNumVolatileRegisters;
+    __ subi(sp, sp, Operand(kDoubleSize * kNumRegs));
+    for (int i = 0; i < kNumRegs; i++) {
+      DwVfpRegister reg = DwVfpRegister::from_code(i);
+      __ stfd(reg, MemOperand(sp, i * kDoubleSize));
+    }
+  }
+  const int argument_count = 1;
+  const int fp_argument_count = 0;
+  const Register scratch = r4;
+
+  AllowExternalCallThatCantCauseGC scope(masm);
+  __ PrepareCallCFunction(argument_count, fp_argument_count, scratch);
+  __ mov(r3, Operand(ExternalReference::isolate_address()));
+  __ CallCFunction(
+      ExternalReference::store_buffer_overflow_function(masm->isolate()),
+      argument_count);
+  if (save_doubles_ == kSaveFPRegs) {
+    const int kNumRegs = DwVfpRegister::kNumVolatileRegisters;
+    for (int i = 0; i < kNumRegs; i++) {
+      DwVfpRegister reg = DwVfpRegister::from_code(i);
+      __ lfd(reg, MemOperand(sp, i * kDoubleSize));
+    }
+    __ addi(sp, sp, Operand(kDoubleSize * kNumRegs));
+  }
+  __ MultiPop(kJSCallerSaved | r0.bit());
+  __ mtlr(r0);
+  __ Ret();
+}
+
+
+void UnaryOpStub::PrintName(StringStream* stream) {
+  const char* op_name = Token::Name(op_);
+  const char* overwrite_name = NULL;  // Make g++ happy.
+  switch (mode_) {
+    case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
+    case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
+  }
+  stream->Add("UnaryOpStub_%s_%s_%s",
+              op_name,
+              overwrite_name,
+              UnaryOpIC::GetName(operand_type_));
+}
+
+
+// TODO(svenpanne): Use virtual functions instead of switch.
+void UnaryOpStub::Generate(MacroAssembler* masm) {
+  switch (operand_type_) {
+    case UnaryOpIC::UNINITIALIZED:
+      GenerateTypeTransition(masm);
+      break;
+    case UnaryOpIC::SMI:
+      GenerateSmiStub(masm);
+      break;
+    case UnaryOpIC::HEAP_NUMBER:
+      GenerateHeapNumberStub(masm);
+      break;
+    case UnaryOpIC::GENERIC:
+      GenerateGenericStub(masm);
+      break;
+  }
+}
+
+
+void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
+  __ mr(r6, r3);  // the operand
+  __ LoadSmiLiteral(r5, Smi::FromInt(op_));
+  __ LoadSmiLiteral(r4, Smi::FromInt(mode_));
+  __ LoadSmiLiteral(r3, Smi::FromInt(operand_type_));
+  __ Push(r6, r5, r4, r3);
+
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
+}
+
+
+// TODO(svenpanne): Use virtual functions instead of switch.
+void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
+  switch (op_) {
+    case Token::SUB:
+      GenerateSmiStubSub(masm);
+      break;
+    case Token::BIT_NOT:
+      GenerateSmiStubBitNot(masm);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
+  Label non_smi, slow;
+  GenerateSmiCodeSub(masm, &non_smi, &slow);
+  __ bind(&non_smi);
+  __ bind(&slow);
+  GenerateTypeTransition(masm);
+}
+
+
+void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
+  Label non_smi;
+  GenerateSmiCodeBitNot(masm, &non_smi);
+  __ bind(&non_smi);
+  GenerateTypeTransition(masm);
+}
+
+
+void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
+                                     Label* non_smi,
+                                     Label* slow) {
+  __ JumpIfNotSmi(r3, non_smi);
+
+  // The result of negating zero or the smallest negative smi is not a smi.
+  __ TestBitRange(r3, kBitsPerPointer - 2, 0, r0);
+  __ beq(slow, cr0);
+
+  // Return '- value'.
+  __ neg(r3, r3);
+  __ Ret();
+}
+
+
+void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
+                                        Label* non_smi) {
+  __ JumpIfNotSmi(r3, non_smi);
+
+  // Flip bits and revert inverted smi-tag.
+  ASSERT(kSmiTagMask == 1);
+  __ notx(r3, r3);
+  __ ClearRightImm(r3, r3, Operand(kSmiTagSize + kSmiShiftSize));
+  __ Ret();
+}
+
+
+// TODO(svenpanne): Use virtual functions instead of switch.
+void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
+  switch (op_) {
+    case Token::SUB:
+      GenerateHeapNumberStubSub(masm);
+      break;
+    case Token::BIT_NOT:
+      GenerateHeapNumberStubBitNot(masm);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
+  Label non_smi, slow, call_builtin;
+  GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
+  __ bind(&non_smi);
+  GenerateHeapNumberCodeSub(masm, &slow);
+  __ bind(&slow);
+  GenerateTypeTransition(masm);
+  __ bind(&call_builtin);
+  GenerateGenericCodeFallback(masm);
+}
+
+
+void UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) {
+  Label non_smi, slow;
+  GenerateSmiCodeBitNot(masm, &non_smi);
+  __ bind(&non_smi);
+  GenerateHeapNumberCodeBitNot(masm, &slow);
+  __ bind(&slow);
+  GenerateTypeTransition(masm);
+}
+
+void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
+                                            Label* slow) {
+  EmitCheckForHeapNumber(masm, r3, r4, r9, slow);
+  // r3 is a heap number.  Get a new heap number in r4.
+  if (mode_ == UNARY_OVERWRITE) {
+    __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+    __ xoris(r5, r5, Operand(HeapNumber::kSignMask >> 16));  // Flip sign.
+    __ stw(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+  } else {
+    Label slow_allocate_heapnumber, heapnumber_allocated;
+    __ AllocateHeapNumber(r4, r5, r6, r9, &slow_allocate_heapnumber);
+    __ b(&heapnumber_allocated);
+
+    __ bind(&slow_allocate_heapnumber);
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      __ push(r3);
+      __ CallRuntime(Runtime::kNumberAlloc, 0);
+      __ mr(r4, r3);
+      __ pop(r3);
+    }
+
+    __ bind(&heapnumber_allocated);
+    __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
+    __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+    __ stw(r6, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
+    __ mov(r0, Operand(HeapNumber::kSignMask));
+    __ xor_(r5, r5, r0);
+    __ stw(r5, FieldMemOperand(r4, HeapNumber::kExponentOffset));
+    __ mr(r3, r4);
+  }
+  __ Ret();
+}
+
+
+void UnaryOpStub::GenerateHeapNumberCodeBitNot(
+    MacroAssembler* masm, Label* slow) {
+  Label impossible;
+
+  EmitCheckForHeapNumber(masm, r3, r4, r9, slow);
+  // Convert the heap number in r3 to an untagged integer in r4.
+  __ ConvertToInt32(r3, r4, r5, r6, d0, slow);
+
+  // Do the bitwise operation and check if the result fits in a smi.
+  __ notx(r4, r4);
+
+#if !V8_TARGET_ARCH_PPC64
+  Label try_float;
+  __ JumpIfNotSmiCandidate(r4, r5, &try_float);
+#endif
+
+  // Tag the result as a smi and we're done.
+  __ SmiTag(r3, r4);
+  __ Ret();
+
+#if !V8_TARGET_ARCH_PPC64
+  // Try to store the result in a heap number.
+  __ bind(&try_float);
+  if (mode_ == UNARY_NO_OVERWRITE) {
+    Label slow_allocate_heapnumber, heapnumber_allocated;
+    // Allocate a new heap number without zapping r0, which we need if it fails.
+    __ AllocateHeapNumber(r5, r6, r7, r9, &slow_allocate_heapnumber);
+    __ b(&heapnumber_allocated);
+
+    __ bind(&slow_allocate_heapnumber);
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      __ push(r3);  // Push the heap number, not the untagged int32.
+      __ CallRuntime(Runtime::kNumberAlloc, 0);
+      __ mr(r5, r3);  // Move the new heap number into r5.
+      // Get the heap number into r3, now that the new heap number is in r5.
+      __ pop(r3);
+    }
+
+    // Convert the heap number in r3 to an untagged integer in r4.
+    // This can't go slow-case because it's the same number we already
+    // converted once again.
+    __ ConvertToInt32(r3, r4, r6, r7, d0, &impossible);
+    __ notx(r4, r4);
+
+    __ bind(&heapnumber_allocated);
+    __ mr(r3, r5);  // Move newly allocated heap number to r0.
+  }
+
+  // Convert the int32 in r4 to the heap number in r3.
+  FloatingPointHelper::ConvertIntToDouble(
+      masm, r4, d0);
+  __ stfd(d0, FieldMemOperand(r3, HeapNumber::kValueOffset));
+  __ Ret();
+
+  __ bind(&impossible);
+  if (FLAG_debug_code) {
+    __ stop("Incorrect assumption in bit-not stub");
+  }
+#endif
+}
+
+
+// TODO(svenpanne): Use virtual functions instead of switch.
+void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
+  switch (op_) {
+    case Token::SUB:
+      GenerateGenericStubSub(masm);
+      break;
+    case Token::BIT_NOT:
+      GenerateGenericStubBitNot(masm);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
+  Label non_smi, slow;
+  GenerateSmiCodeSub(masm, &non_smi, &slow);
+  __ bind(&non_smi);
+  GenerateHeapNumberCodeSub(masm, &slow);
+  __ bind(&slow);
+  GenerateGenericCodeFallback(masm);
+}
+
+
+void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
+  Label non_smi, slow;
+  GenerateSmiCodeBitNot(masm, &non_smi);
+  __ bind(&non_smi);
+  GenerateHeapNumberCodeBitNot(masm, &slow);
+  __ bind(&slow);
+  GenerateGenericCodeFallback(masm);
+}
+
+
+void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
+  // Handle the slow case by jumping to the JavaScript builtin.
+  __ push(r3);
+  switch (op_) {
+    case Token::SUB:
+      __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
+      break;
+    case Token::BIT_NOT:
+      __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
+  Label get_result;
+
+  __ Push(r4, r3);
+
+  __ LoadSmiLiteral(r5, Smi::FromInt(MinorKey()));
+  __ LoadSmiLiteral(r4, Smi::FromInt(op_));
+  __ LoadSmiLiteral(r3, Smi::FromInt(operands_type_));
+  __ Push(r5, r4, r3);
+
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
+                        masm->isolate()),
+      5,
+      1);
+}
+
+
+void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
+    MacroAssembler* masm) {
+  UNIMPLEMENTED();
+}
+
+
+void BinaryOpStub::Generate(MacroAssembler* masm) {
+  // Explicitly allow generation of nested stubs. It is safe here because
+  // generation code does not use any raw pointers.
+  AllowStubCallsScope allow_stub_calls(masm, true);
+
+  switch (operands_type_) {
+    case BinaryOpIC::UNINITIALIZED:
+      GenerateTypeTransition(masm);
+      break;
+    case BinaryOpIC::SMI:
+      GenerateSmiStub(masm);
+      break;
+    case BinaryOpIC::INT32:
+      GenerateInt32Stub(masm);
+      break;
+    case BinaryOpIC::HEAP_NUMBER:
+      GenerateHeapNumberStub(masm);
+      break;
+    case BinaryOpIC::ODDBALL:
+      GenerateOddballStub(masm);
+      break;
+    case BinaryOpIC::BOTH_STRING:
+      GenerateBothStringStub(masm);
+      break;
+    case BinaryOpIC::STRING:
+      GenerateStringStub(masm);
+      break;
+    case BinaryOpIC::GENERIC:
+      GenerateGeneric(masm);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void BinaryOpStub::PrintName(StringStream* stream) {
+  const char* op_name = Token::Name(op_);
+  const char* overwrite_name;
+  switch (mode_) {
+    case NO_OVERWRITE: overwrite_name = "Alloc"; break;
+    case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
+    case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
+    default: overwrite_name = "UnknownOverwrite"; break;
+  }
+  stream->Add("BinaryOpStub_%s_%s_%s",
+              op_name,
+              overwrite_name,
+              BinaryOpIC::GetName(operands_type_));
+}
+
+
+void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
+  Register left = r4;
+  Register right = r3;
+  Register scratch1 = r10;
+  Register scratch2 = r22;
+
+  ASSERT(right.is(r3));
+  STATIC_ASSERT(kSmiTag == 0);
+
+  Label not_smi_result;
+  switch (op_) {
+    case Token::ADD: {
+      Label undo_add, add_no_overflow;
+      // C = A+B; C overflows if A/B have same sign and C has diff sign than A
+      __ xor_(r0, left, right);
+      __ mr(scratch1, right);
+      __ add(right, left, right);  // Add optimistically.
+      __ TestSignBit(r0, r0);
+      __ bne(&add_no_overflow, cr0);
+      __ xor_(r0, right, scratch1);
+      __ TestSignBit(r0, r0);
+      __ bne(&undo_add, cr0);
+      __ bind(&add_no_overflow);
+      __ Ret();
+      __ bind(&undo_add);
+      __ mr(right, scratch1);  // Revert optimistic add.
+      break;
+    }
+    case Token::SUB: {
+      Label undo_sub, sub_no_overflow;
+      // C = A-B; C overflows if A/B have diff signs and C has diff sign than A
+      __ xor_(r0, left, right);
+      __ mr(scratch1, right);
+      __ sub(right, left, right);  // Subtract optimistically.
+      __ TestSignBit(r0, r0);
+      __ beq(&sub_no_overflow, cr0);
+      __ xor_(r0, right, left);
+      __ TestSignBit(r0, r0);
+      __ bne(&undo_sub, cr0);
+      __ bind(&sub_no_overflow);
+      __ Ret();
+      __ bind(&undo_sub);
+      __ mr(right, scratch1);  // Revert optimistic subtract.
+      break;
+    }
+    case Token::MUL: {
+      Label mul_zero, mul_neg_zero;
+#if V8_TARGET_ARCH_PPC64
+      // Remove tag from both operands.
+      __ SmiUntag(ip, right);
+      __ SmiUntag(r0, left);
+      // Do multiplication
+      // scratch1 = product (untagged)
+      // scratch2 = sign-extended higher 32 bits of product.
+      __ Mul(scratch1, r0, ip);
+      // Check for overflowing the smi range - no overflow if higher 33 bits of
+      // the result are identical.
+      __ TestIfInt32(scratch1, scratch2, ip);
+      __ bne(&not_smi_result);
+#else
+      // Remove tag from one of the operands. This way the multiplication result
+      // will be a smi if it fits the smi range.
+      __ SmiUntag(ip, right);
+      // Do multiplication
+      // scratch1 = lower 32 bits of product.
+      // scratch2 = higher 32 bits of product.
+      __ mullw(scratch1, left, ip);
+      __ mulhw(scratch2, left, ip);
+      // Check for overflowing the smi range - no overflow if higher 33 bits of
+      // the result are identical.
+      __ TestIfInt32(scratch2, scratch1, ip);
+      __ bne(&not_smi_result);
+#endif
+      // Go slow on zero result to handle -0.
+      __ cmpi(scratch1, Operand::Zero());
+      __ beq(&mul_zero);
+#if V8_TARGET_ARCH_PPC64
+      __ SmiTag(right, scratch1);
+#else
+      __ mr(right, scratch1);
+#endif
+      __ Ret();
+      __ bind(&mul_zero);
+      // We need -0 if we were multiplying a negative number with 0 to get 0.
+      // We know one of them was zero.
+      __ add(scratch2, right, left);
+      __ cmpi(scratch2, Operand::Zero());
+      __ blt(&mul_neg_zero);
+      __ LoadSmiLiteral(right, Smi::FromInt(0));
+      __ Ret();  // Return smi 0 if the non-zero one was positive.
+      __ bind(&mul_neg_zero);
+      // We fall through here if we multiplied a negative number with 0, because
+      // that would mean we should produce -0.
+      break;
+    }
+    case Token::DIV: {
+      Label check_neg_zero;
+      __ SmiUntag(ip, left);
+      __ SmiUntag(scratch2, right, SetRC);
+      __ Div(scratch1, ip, scratch2);
+      // Check for zero on the right hand side.
+      __ beq(&not_smi_result, cr0);
+      // Not Smi if remainder is non-zero.
+      __ Mul(scratch2, scratch2, scratch1);
+      __ cmp(ip, scratch2);
+      __ bne(&not_smi_result);
+      // If the result is 0, we need to check for the -0 case.
+      __ SmiTag(scratch2, scratch1, SetRC);
+      __ beq(&check_neg_zero, cr0);
+      // Check for Smi overflow
+      __ xor_(scratch1, scratch2, scratch1, SetRC);
+      __ blt(&not_smi_result, cr0);
+      __ mr(right, scratch2);
+      __ Ret();
+
+      // If divisor (right) is negative, we must produce -0.
+      __ bind(&check_neg_zero);
+      __ cmpi(right, Operand::Zero());
+      __ blt(&not_smi_result);
+      __ mr(right, scratch2);
+      __ Ret();
+      break;
+    }
+    case Token::MOD: {
+      Label check_neg_zero;
+      __ SmiUntag(ip, left);
+      __ SmiUntag(scratch2, right, SetRC);
+      __ Div(scratch1, ip, scratch2);
+      // Check for zero on the right hand side.
+      __ beq(&not_smi_result, cr0);
+      __ Mul(scratch1, scratch2, scratch1);
+      __ sub(scratch1, ip, scratch1, LeaveOE, SetRC);
+      // If the result is 0, we need to check for the -0 case.
+      __ beq(&check_neg_zero, cr0);
+#if !V8_TARGET_ARCH_PPC64
+      // Check that the signed result fits in a Smi.
+      __ JumpIfNotSmiCandidate(scratch1, scratch2, &not_smi_result);
+#endif
+      __ SmiTag(right, scratch1);
+      __ Ret();
+
+      // If dividend (left) is negative, we must produce -0.
+      __ bind(&check_neg_zero);
+      __ cmpi(left, Operand::Zero());
+      __ blt(&not_smi_result);
+      __ LoadSmiLiteral(right, Smi::FromInt(0));
+      __ Ret();
+      break;
+    }
+    case Token::BIT_OR:
+      __ orx(right, left, right);
+      __ Ret();
+      break;
+    case Token::BIT_AND:
+      __ and_(right, left, right);
+      __ Ret();
+      break;
+    case Token::BIT_XOR:
+      __ xor_(right, left, right);
+      __ Ret();
+      break;
+    case Token::SAR:
+      // Remove tags from right operand.
+      __ GetLeastBitsFromSmi(scratch1, right, 5);
+      __ ShiftRightArith(right, left, scratch1);
+      // Smi tag result.
+      __ ClearRightImm(right, right, Operand(kSmiTagSize + kSmiShiftSize));
+      __ Ret();
+      break;
+    case Token::SHR:
+      // Remove tags from operands. We can't do this on a 31 bit number
+      // because then the 0s get shifted into bit 30 instead of bit 31.
+      __ SmiUntag(scratch1, left);
+      __ GetLeastBitsFromSmi(scratch2, right, 5);
+      __ srw(scratch1, scratch1, scratch2);
+      // Unsigned shift is not allowed to produce a negative number.
+      __ JumpIfNotUnsignedSmiCandidate(scratch1, r0, &not_smi_result);
+      // Smi tag result.
+      __ SmiTag(right, scratch1);
+      __ Ret();
+      break;
+    case Token::SHL:
+      // Remove tags from operands.
+      __ SmiUntag(scratch1, left);
+      __ GetLeastBitsFromSmi(scratch2, right, 5);
+      __ ShiftLeft(scratch1, scratch1, scratch2);
+#if !V8_TARGET_ARCH_PPC64
+      // Check that the signed result fits in a Smi.
+      __ JumpIfNotSmiCandidate(scratch1, scratch2, &not_smi_result);
+#endif
+      __ SmiTag(right, scratch1);
+      __ Ret();
+      break;
+    default:
+      UNREACHABLE();
+  }
+  __ bind(&not_smi_result);
+}
+
+
+void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
+                                       bool smi_operands,
+                                       Label* not_numbers,
+                                       Label* gc_required) {
+  Register left = r4;
+  Register right = r3;
+  Register scratch1 = r10;
+  Register scratch2 = r22;
+  Register scratch3 = r7;
+
+  ASSERT(smi_operands || (not_numbers != NULL));
+  if (smi_operands) {
+    __ AssertSmi(left);
+    __ AssertSmi(right);
+  }
+
+  Register heap_number_map = r9;
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
+  switch (op_) {
+    case Token::ADD:
+    case Token::SUB:
+    case Token::MUL:
+    case Token::DIV:
+    case Token::MOD: {
+      // Load left and right operands into d1 and d2
+      // Allocate new heap number for result.
+      Register result = r8;
+      GenerateHeapResultAllocation(
+          masm, result, heap_number_map, scratch1, scratch2, gc_required);
+
+      // Load the operands.
+      if (smi_operands) {
+        FloatingPointHelper::LoadSmis(masm, scratch1, scratch2);
+      } else {
+        FloatingPointHelper::LoadOperands(masm,
+                                          heap_number_map,
+                                          scratch1,
+                                          scratch2,
+                                          not_numbers);
+      }
+
+      // Calculate the result.
+      // Using FP registers:
+      //   d1: Left value
+      //   d2: Right value
+      switch (op_) {
+        case Token::ADD:
+          __ fadd(d1, d1, d2);
+          break;
+        case Token::SUB:
+          __ fsub(d1, d1, d2);
+          break;
+        case Token::MUL:
+          __ fmul(d1, d1, d2);
+          break;
+        case Token::DIV:
+          __ fdiv(d1, d1, d2);
+          break;
+        case Token::MOD:
+          // Call the C function to handle the double operation.
+          FloatingPointHelper::CallCCodeForDoubleOperation(masm,
+                                                           op_,
+                                                           result,
+                                                           scratch1);
+          if (FLAG_debug_code) {
+            __ stop("Unreachable code.");
+          }
+          break;
+        default:
+          UNREACHABLE();
+      }
+      __ stfd(d1, FieldMemOperand(result, HeapNumber::kValueOffset));
+      __ mr(r3, result);
+      __ Ret();
+      break;
+    }
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND:
+    case Token::SAR:
+    case Token::SHR:
+    case Token::SHL: {
+      if (smi_operands) {
+        __ SmiUntag(r6, left);
+        __ SmiUntag(r5, right);
+      } else {
+        // Convert operands to 32-bit integers. Right in r5 and left in r6.
+        FloatingPointHelper::ConvertNumberToInt32(masm,
+                                                  left,
+                                                  r6,
+                                                  heap_number_map,
+                                                  scratch1,
+                                                  scratch2,
+                                                  scratch3,
+                                                  d0,
+                                                  not_numbers);
+        FloatingPointHelper::ConvertNumberToInt32(masm,
+                                                  right,
+                                                  r5,
+                                                  heap_number_map,
+                                                  scratch1,
+                                                  scratch2,
+                                                  scratch3,
+                                                  d0,
+                                                  not_numbers);
+      }
+
+      Label result_not_a_smi;
+      switch (op_) {
+        case Token::BIT_OR:
+          __ orx(r5, r6, r5);
+          break;
+        case Token::BIT_XOR:
+          __ xor_(r5, r6, r5);
+          break;
+        case Token::BIT_AND:
+          __ and_(r5, r6, r5);
+          break;
+        case Token::SAR:
+          // Use only the 5 least significant bits of the shift count.
+          __ GetLeastBitsFromInt32(r5, r5, 5);
+          __ sraw(r5, r6, r5);
+          break;
+        case Token::SHR:
+        {
+          // Use only the 5 least significant bits of the shift count.
+          __ GetLeastBitsFromInt32(r5, r5, 5);
+          // SHR is special because it is required to produce a positive answer.
+          // The code below for writing into heap numbers isn't capable of
+          // writing the register as an unsigned int so we go to slow case if we
+          // hit this case.
+#if V8_TARGET_ARCH_PPC64
+          const Condition cond = ne;
+          __ srw(r5, r6, r5);
+          __ TestSignBit32(r5, r0);
+#else
+          const Condition cond = lt;
+          __ srw(r5, r6, r5, SetRC);
+#endif
+          __ b(cond, &result_not_a_smi, cr0);
+          break;
+        }
+        case Token::SHL:
+          // Use only the 5 least significant bits of the shift count.
+          __ GetLeastBitsFromInt32(r5, r5, 5);
+          __ ShiftLeft(r5, r6, r5);
+          break;
+        default:
+          UNREACHABLE();
+      }
+
+#if !V8_TARGET_ARCH_PPC64
+      // Check that the *signed* result fits in a smi.
+      __ JumpIfNotSmiCandidate(r5, r6, &result_not_a_smi);
+#endif
+      __ SmiTag(r3, r5);
+      __ Ret();
+
+      // Allocate new heap number for result.
+      __ bind(&result_not_a_smi);
+      Register result = r8;
+      if (smi_operands) {
+        __ AllocateHeapNumber(
+            result, scratch1, scratch2, heap_number_map, gc_required);
+      } else {
+        GenerateHeapResultAllocation(
+            masm, result, heap_number_map, scratch1, scratch2, gc_required);
+      }
+
+      // r5: Answer as signed int32.
+      // r8: Heap number to write answer into.
+
+      // Nothing can go wrong now, so move the heap number to r3, which is the
+      // result.
+      __ mr(r3, r8);
+
+      // Convert the int32 in r5 to the heap number in r3. As
+      // mentioned above SHR needs to always produce a positive result.
+      if (op_ == Token::SHR) {
+        FloatingPointHelper::ConvertUnsignedIntToDouble(
+          masm, r5, d0);
+      } else {
+        FloatingPointHelper::ConvertIntToDouble(
+          masm, r5, d0);
+      }
+      __ stfd(d0, FieldMemOperand(r3, HeapNumber::kValueOffset));
+      __ Ret();
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+// Generate the smi code. If the operation on smis are successful this return is
+// generated. If the result is not a smi and heap number allocation is not
+// requested the code falls through. If number allocation is requested but a
+// heap number cannot be allocated the code jumps to the lable gc_required.
+void BinaryOpStub::GenerateSmiCode(
+    MacroAssembler* masm,
+    Label* use_runtime,
+    Label* gc_required,
+    SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
+  Label not_smis;
+
+  Register left = r4;
+  Register right = r3;
+  Register scratch1 = r10;
+
+  // Perform combined smi check on both operands.
+  __ orx(scratch1, left, right);
+  STATIC_ASSERT(kSmiTag == 0);
+  __ JumpIfNotSmi(scratch1, &not_smis);
+
+  // If the smi-smi operation results in a smi return is generated.
+  GenerateSmiSmiOperation(masm);
+
+  // If heap number results are possible generate the result in an allocated
+  // heap number.
+  if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) {
+    GenerateFPOperation(masm, true, use_runtime, gc_required);
+  }
+  __ bind(&not_smis);
+}
+
+
+void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
+  Label not_smis, call_runtime;
+
+  if (result_type_ == BinaryOpIC::UNINITIALIZED ||
+      result_type_ == BinaryOpIC::SMI) {
+    // Only allow smi results.
+    GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
+  } else {
+    // Allow heap number result and don't make a transition if a heap number
+    // cannot be allocated.
+    GenerateSmiCode(masm,
+                    &call_runtime,
+                    &call_runtime,
+                    ALLOW_HEAPNUMBER_RESULTS);
+  }
+
+  // Code falls through if the result is not returned as either a smi or heap
+  // number.
+  GenerateTypeTransition(masm);
+
+  __ bind(&call_runtime);
+  GenerateCallRuntime(masm);
+}
+
+
+void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
+  ASSERT(operands_type_ == BinaryOpIC::STRING);
+  ASSERT(op_ == Token::ADD);
+  // Try to add arguments as strings, otherwise, transition to the generic
+  // BinaryOpIC type.
+  GenerateAddStrings(masm);
+  GenerateTypeTransition(masm);
+}
+
+
+void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
+  Label call_runtime;
+  ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
+  ASSERT(op_ == Token::ADD);
+  // If both arguments are strings, call the string add stub.
+  // Otherwise, do a transition.
+
+  // Registers containing left and right operands respectively.
+  Register left = r4;
+  Register right = r3;
+
+  // Test if left operand is a string.
+  __ JumpIfSmi(left, &call_runtime);
+  __ CompareObjectType(left, r5, r5, FIRST_NONSTRING_TYPE);
+  __ bge(&call_runtime);
+
+  // Test if right operand is a string.
+  __ JumpIfSmi(right, &call_runtime);
+  __ CompareObjectType(right, r5, r5, FIRST_NONSTRING_TYPE);
+  __ bge(&call_runtime);
+
+  StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
+  GenerateRegisterArgsPush(masm);
+  __ TailCallStub(&string_add_stub);
+
+  __ bind(&call_runtime);
+  GenerateTypeTransition(masm);
+}
+
+
+void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
+  ASSERT(operands_type_ == BinaryOpIC::INT32);
+
+  Register left = r4;
+  Register right = r3;
+  Register scratch1 = r10;
+  Register scratch2 = r11;
+  DwVfpRegister double_scratch0 = d0;
+  DwVfpRegister double_scratch1 = d1;
+
+  Register heap_number_result = no_reg;
+  Register heap_number_map = r9;
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
+  Label call_runtime;
+  // Labels for type transition, used for wrong input or output types.
+  // Both label are currently actually bound to the same position. We use two
+  // different label to differentiate the cause leading to type transition.
+  Label transition;
+
+  // Smi-smi fast case.
+  Label skip;
+  __ orx(scratch1, left, right);
+  __ JumpIfNotSmi(scratch1, &skip);
+  GenerateSmiSmiOperation(masm);
+  // Fall through if the result is not a smi.
+  __ bind(&skip);
+
+  switch (op_) {
+    case Token::ADD:
+    case Token::SUB:
+    case Token::MUL:
+    case Token::DIV:
+    case Token::MOD: {
+      // Load both operands and check that they are 32-bit integer.
+      // Jump to type transition if they are not. The registers r3 and r4 (right
+      // and left) are preserved for the runtime call.
+      FloatingPointHelper::LoadNumberAsInt32Double(masm,
+                                                   right,
+                                                   d2,
+                                                   d8,
+                                                   heap_number_map,
+                                                   scratch1,
+                                                   scratch2,
+                                                   &transition);
+      FloatingPointHelper::LoadNumberAsInt32Double(masm,
+                                                   left,
+                                                   d1,
+                                                   d8,
+                                                   heap_number_map,
+                                                   scratch1,
+                                                   scratch2,
+                                                   &transition);
+
+      Label return_heap_number;
+      switch (op_) {
+        case Token::ADD:
+          __ fadd(d1, d1, d2);
+          break;
+        case Token::SUB:
+          __ fsub(d1, d1, d2);
+          break;
+        case Token::MUL:
+          __ fmul(d1, d1, d2);
+          break;
+        case Token::DIV:
+          __ fdiv(d1, d1, d2);
+          break;
+        case Token::MOD: {
+          Label pop_and_call_runtime;
+
+          // Allocate a heap number to store the result.
+          heap_number_result = r8;
+          GenerateHeapResultAllocation(masm,
+                                       heap_number_result,
+                                       heap_number_map,
+                                       scratch1,
+                                       scratch2,
+                                       &pop_and_call_runtime);
+
+          // Call the C function to handle the double operation.
+          FloatingPointHelper::CallCCodeForDoubleOperation(
+              masm, op_, heap_number_result, scratch1);
+          if (FLAG_debug_code) {
+            __ stop("Unreachable code.");
+          }
+
+          __ bind(&pop_and_call_runtime);
+          __ b(&call_runtime);
+          break;
+        }
+        default:
+          UNREACHABLE();
+      }
+
+      if (op_ != Token::DIV) {
+        // These operations produce an integer result.
+        // Try to return a smi if we can.
+        // Otherwise return a heap number if allowed, or jump to type
+        // transition.
+
+        __ EmitVFPTruncate(kRoundToZero,
+                           scratch1,
+                           d1,
+                           scratch2,
+                           d8);
+
+        // result does not fit in a 32-bit integer.
+        Label *not_int32 = ((result_type_ <= BinaryOpIC::INT32) ?
+                            &transition : &return_heap_number);
+        __ bne(not_int32);
+
+#if !V8_TARGET_ARCH_PPC64
+        // Check if the result fits in a smi.
+        // If not try to return a heap number.
+        __ JumpIfNotSmiCandidate(scratch1, scratch2, &return_heap_number);
+#endif
+        // Check for minus zero. Return heap number for minus zero.
+        Label not_zero;
+        __ cmpi(scratch1, Operand::Zero());
+        __ bne(&not_zero);
+
+        __ subi(sp, sp, Operand(8));
+        __ stfd(d1, MemOperand(sp, 0));
+#if V8_TARGET_ARCH_PPC64
+        __ ld(scratch2, MemOperand(sp, 0));
+#else
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+        __ lwz(scratch2, MemOperand(sp, 4));
+#else
+        __ lwz(scratch2, MemOperand(sp, 0));
+#endif
+#endif
+        __ addi(sp, sp, Operand(8));
+
+        __ TestSignBit(scratch2, r0);
+        __ bne(&return_heap_number, cr0);
+        __ bind(&not_zero);
+
+        // Tag the result and return.
+        __ SmiTag(r3, scratch1);
+        __ Ret();
+      } else {
+        // DIV just falls through to allocating a heap number.
+      }
+
+      __ bind(&return_heap_number);
+      // Return a heap number, or fall through to type transition or runtime
+      // call if we can't.
+      if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER
+                                               : BinaryOpIC::INT32)) {
+        heap_number_result = r8;
+        GenerateHeapResultAllocation(masm,
+                                     heap_number_result,
+                                     heap_number_map,
+                                     scratch1,
+                                     scratch2,
+                                     &call_runtime);
+        __ stfd(d1, FieldMemOperand(heap_number_result,
+                                    HeapNumber::kValueOffset));
+        __ mr(r3, heap_number_result);
+        __ Ret();
+      }
+
+      // A DIV operation expecting an integer result falls through
+      // to type transition.
+      break;
+    }
+
+    case Token::BIT_OR:
+    case Token::BIT_XOR:
+    case Token::BIT_AND:
+    case Token::SAR:
+    case Token::SHR:
+    case Token::SHL: {
+      Label return_heap_number;
+      Register scratch3 = r8;
+      // Convert operands to 32-bit integers. Right in r5 and left in r6. The
+      // registers r3 and r4 (right and left) are preserved for the runtime
+      // call.
+      FloatingPointHelper::LoadNumberAsInt32(masm,
+                                             left,
+                                             r6,
+                                             heap_number_map,
+                                             scratch1,
+                                             scratch2,
+                                             scratch3,
+                                             double_scratch0,
+                                             double_scratch1,
+                                             &transition);
+      FloatingPointHelper::LoadNumberAsInt32(masm,
+                                             right,
+                                             r5,
+                                             heap_number_map,
+                                             scratch1,
+                                             scratch2,
+                                             scratch3,
+                                             double_scratch0,
+                                             double_scratch1,
+                                             &transition);
+
+      // The ECMA-262 standard specifies that, for shift operations, only the
+      // 5 least significant bits of the shift value should be used.
+      switch (op_) {
+        case Token::BIT_OR:
+          __ orx(r5, r6, r5);
+          break;
+        case Token::BIT_XOR:
+          __ xor_(r5, r6, r5);
+          break;
+        case Token::BIT_AND:
+          __ and_(r5, r6, r5);
+          break;
+        case Token::SAR:
+          __ GetLeastBitsFromInt32(r5, r5, 5);
+          __ sraw(r5, r6, r5);
+          break;
+        case Token::SHR:
+        {
+          __ GetLeastBitsFromInt32(r5, r5, 5);
+          // SHR is special because it is required to produce a positive answer.
+          // We only get a negative result if the shift value (r5) is 0.
+          // This result cannot be respresented as a signed 32-bit integer, try
+          // to return a heap number if we can.
+#if V8_TARGET_ARCH_PPC64
+          const Condition cond = ne;
+          __ srw(r5, r6, r5);
+          __ TestSignBit32(r5, r0);
+#else
+          const Condition cond = lt;
+          __ srw(r5, r6, r5, SetRC);
+#endif
+          __ b(cond, ((result_type_ <= BinaryOpIC::INT32)
+                      ? &transition
+                      : &return_heap_number), cr0);
+          break;
+        }
+        case Token::SHL:
+          __ andi(r5, r5, Operand(0x1f));
+          __ ShiftLeft(r5, r6, r5);
+          break;
+        default:
+          UNREACHABLE();
+      }
+
+#if !V8_TARGET_ARCH_PPC64
+      // Check if the result fits in a smi.
+      // If not try to return a heap number. (We know the result is an int32.)
+      __ JumpIfNotSmiCandidate(r5, scratch1, &return_heap_number);
+#endif
+      // Tag the result and return.
+      __ SmiTag(r3, r5);
+      __ Ret();
+
+      __ bind(&return_heap_number);
+      heap_number_result = r8;
+      GenerateHeapResultAllocation(masm,
+                                   heap_number_result,
+                                   heap_number_map,
+                                   scratch1,
+                                   scratch2,
+                                   &call_runtime);
+
+      if (op_ != Token::SHR) {
+        // Convert the result to a floating point value.
+        FloatingPointHelper::ConvertIntToDouble(masm, r5, double_scratch0);
+      } else {
+        // The result must be interpreted as an unsigned 32-bit integer.
+        FloatingPointHelper::ConvertUnsignedIntToDouble(masm, r5,
+                                                        double_scratch0);
+      }
+
+      // Store the result.
+      __ stfd(double_scratch0, FieldMemOperand(heap_number_result,
+                                               HeapNumber::kValueOffset));
+      __ mr(r3, heap_number_result);
+      __ Ret();
+
+      break;
+    }
+
+    default:
+      UNREACHABLE();
+  }
+
+  // We never expect DIV to yield an integer result, so we always generate
+  // type transition code for DIV operations expecting an integer result: the
+  // code will fall through to this type transition.
+  if (transition.is_linked() ||
+      ((op_ == Token::DIV) && (result_type_ <= BinaryOpIC::INT32))) {
+    __ bind(&transition);
+    GenerateTypeTransition(masm);
+  }
+
+  __ bind(&call_runtime);
+  GenerateCallRuntime(masm);
+}
+
+
+void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
+  Label call_runtime;
+
+  if (op_ == Token::ADD) {
+    // Handle string addition here, because it is the only operation
+    // that does not do a ToNumber conversion on the operands.
+    GenerateAddStrings(masm);
+  }
+
+  // Convert oddball arguments to numbers.
+  Label check, done;
+  __ CompareRoot(r4, Heap::kUndefinedValueRootIndex);
+  __ bne(&check);
+  if (Token::IsBitOp(op_)) {
+    __ LoadSmiLiteral(r4, Smi::FromInt(0));
+  } else {
+    __ LoadRoot(r4, Heap::kNanValueRootIndex);
+  }
+  __ b(&done);
+  __ bind(&check);
+  __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
+  __ bne(&done);
+  if (Token::IsBitOp(op_)) {
+    __ LoadSmiLiteral(r3, Smi::FromInt(0));
+  } else {
+    __ LoadRoot(r3, Heap::kNanValueRootIndex);
+  }
+  __ bind(&done);
+
+  GenerateHeapNumberStub(masm);
+}
+
+
+void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
+  Label call_runtime;
+  GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
+
+  __ bind(&call_runtime);
+  GenerateCallRuntime(masm);
+}
+
+
+void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
+  Label call_runtime, call_string_add_or_runtime;
+
+  GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
+
+  GenerateFPOperation(masm, false, &call_string_add_or_runtime, &call_runtime);
+
+  __ bind(&call_string_add_or_runtime);
+  if (op_ == Token::ADD) {
+    GenerateAddStrings(masm);
+  }
+
+  __ bind(&call_runtime);
+  GenerateCallRuntime(masm);
+}
+
+
+void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
+  ASSERT(op_ == Token::ADD);
+  Label left_not_string, call_runtime;
+
+  Register left = r4;
+  Register right = r3;
+
+  // Check if left argument is a string.
+  __ JumpIfSmi(left, &left_not_string);
+  __ CompareObjectType(left, r5, r5, FIRST_NONSTRING_TYPE);
+  __ bge(&left_not_string);
+
+  StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
+  GenerateRegisterArgsPush(masm);
+  __ TailCallStub(&string_add_left_stub);
+
+  // Left operand is not a string, test right.
+  __ bind(&left_not_string);
+  __ JumpIfSmi(right, &call_runtime);
+  __ CompareObjectType(right, r5, r5, FIRST_NONSTRING_TYPE);
+  __ bge(&call_runtime);
+
+  StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
+  GenerateRegisterArgsPush(masm);
+  __ TailCallStub(&string_add_right_stub);
+
+  // At least one argument is not a string.
+  __ bind(&call_runtime);
+}
+
+
+void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
+  GenerateRegisterArgsPush(masm);
+  switch (op_) {
+    case Token::ADD:
+      __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
+      break;
+    case Token::SUB:
+      __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
+      break;
+    case Token::MUL:
+      __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
+      break;
+    case Token::DIV:
+      __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
+      break;
+    case Token::MOD:
+      __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
+      break;
+    case Token::BIT_OR:
+      __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
+      break;
+    case Token::BIT_AND:
+      __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION);
+      break;
+    case Token::BIT_XOR:
+      __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION);
+      break;
+    case Token::SAR:
+      __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION);
+      break;
+    case Token::SHR:
+      __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
+      break;
+    case Token::SHL:
+      __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void BinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm,
+                                                Register result,
+                                                Register heap_number_map,
+                                                Register scratch1,
+                                                Register scratch2,
+                                                Label* gc_required) {
+  // Code below will scratch result if allocation fails. To keep both arguments
+  // intact for the runtime call result cannot be one of these.
+  ASSERT(!result.is(r3) && !result.is(r4));
+
+  if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) {
+    Label skip_allocation, allocated;
+    Register overwritable_operand = mode_ == OVERWRITE_LEFT ? r4 : r3;
+    // If the overwritable operand is already an object, we skip the
+    // allocation of a heap number.
+    __ JumpIfNotSmi(overwritable_operand, &skip_allocation);
+    // Allocate a heap number for the result.
+    __ AllocateHeapNumber(
+        result, scratch1, scratch2, heap_number_map, gc_required);
+    __ b(&allocated);
+    __ bind(&skip_allocation);
+    // Use object holding the overwritable operand for result.
+    __ mr(result, overwritable_operand);
+    __ bind(&allocated);
+  } else {
+    ASSERT(mode_ == NO_OVERWRITE);
+    __ AllocateHeapNumber(
+        result, scratch1, scratch2, heap_number_map, gc_required);
+  }
+}
+
+
+void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
+  __ Push(r4, r3);
+}
+
+
+void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
+  // Untagged case: double input in d2, double result goes
+  //   into d2.
+  // Tagged case: tagged input on top of stack and in r3,
+  //   tagged result (heap number) goes into r3.
+
+  Label input_not_smi;
+  Label loaded;
+  Label calculate;
+  Label invalid_cache;
+  const Register scratch0 = r22;
+  const Register scratch1 = r10;
+  const Register cache_entry = r3;
+  const bool tagged = (argument_type_ == TAGGED);
+
+  if (tagged) {
+    // Argument is a number and is on stack and in r3.
+    // Load argument and check if it is a smi.
+    __ JumpIfNotSmi(r3, &input_not_smi);
+
+    // Input is a smi. Convert to double and load the low and high words
+    // of the double into r5, r6.
+    __ SmiToDoubleFPRegister(r3, d6, scratch0);
+    __ subi(sp, sp, Operand(8));
+    __ stfd(d6, MemOperand(sp, 0));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    __ lwz(r5, MemOperand(sp));
+    __ lwz(r6, MemOperand(sp, 4));
+#else
+    __ lwz(r5, MemOperand(sp, 4));
+    __ lwz(r6, MemOperand(sp));
+#endif
+    __ addi(sp, sp, Operand(8));
+    __ b(&loaded);
+
+    __ bind(&input_not_smi);
+    // Check if input is a HeapNumber.
+    __ CheckMap(r3,
+                r4,
+                Heap::kHeapNumberMapRootIndex,
+                &calculate,
+                DONT_DO_SMI_CHECK);
+    // Input is a HeapNumber. Load it to a double register and store the
+    // low and high words into r5, r6.
+    __ lwz(r6, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+    __ lwz(r5, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
+  } else {
+    // Input is untagged double in d2. Output goes to d2.
+    __ subi(sp, sp, Operand(8));
+    __ stfd(d2, MemOperand(sp, 0));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    __ lwz(r5, MemOperand(sp, 4));
+    __ lwz(r6, MemOperand(sp));
+#else
+    __ lwz(r5, MemOperand(sp));
+    __ lwz(r6, MemOperand(sp, 4));
+#endif
+    __ addi(sp, sp, Operand(8));
+  }
+    __ bind(&loaded);
+  // r5 = low 32 bits of double value
+  // r6 = high 32 bits of double value
+  // Compute hash (the shifts are arithmetic):
+  //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
+  __ xor_(r4, r5, r6);
+  __ srawi(scratch0, r4, 16);
+  __ xor_(r4, r4, scratch0);
+  __ srawi(scratch0, r4, 8);
+  __ xor_(r4, r4, scratch0);
+  ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
+  __ andi(r4, r4, Operand(TranscendentalCache::SubCache::kCacheSize - 1));
+
+  // r5 = low 32 bits of double value.
+  // r6 = high 32 bits of double value.
+  // r4 = TranscendentalCache::hash(double value).
+  Isolate* isolate = masm->isolate();
+  ExternalReference cache_array =
+      ExternalReference::transcendental_cache_array_address(isolate);
+  __ mov(cache_entry, Operand(cache_array));
+  // cache_entry points to cache array.
+  int cache_array_index
+      = type_ * sizeof(isolate->transcendental_cache()->caches_[0]);
+  __ LoadP(cache_entry, MemOperand(cache_entry, cache_array_index), r0);
+  // r3 points to the cache for the type type_.
+  // If NULL, the cache hasn't been initialized yet, so go through runtime.
+  __ cmpi(cache_entry, Operand(0, RelocInfo::NONE));
+  __ beq(&invalid_cache);
+
+#ifdef DEBUG
+  // Check that the layout of cache elements match expectations.
+  { TranscendentalCache::SubCache::Element test_elem[2];
+    char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
+    char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
+    char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
+    char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
+    char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
+    // Two uint_32's and a pointer.
+#if V8_TARGET_ARCH_PPC64
+    CHECK_EQ(16, static_cast<int>(elem2_start - elem_start));
+#else
+    CHECK_EQ(12, static_cast<int>(elem2_start - elem_start));
+#endif
+    CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start));
+    CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start));
+    CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start));
+  }
+#endif
+
+#if V8_TARGET_ARCH_PPC64
+  // Find the address of the r4'th entry in the cache, i.e., &r3[r4*16].
+  __ ShiftLeftImm(scratch0, r4, Operand(4));
+#else
+  // Find the address of the r4'th entry in the cache, i.e., &r3[r4*12].
+  __ ShiftLeftImm(scratch0, r4, Operand(1));
+  __ add(r4, r4, scratch0);
+  __ ShiftLeftImm(scratch0, r4, Operand(2));
+#endif
+  __ add(cache_entry, cache_entry, scratch0);
+  // Check if cache matches: Double value is stored in uint32_t[2] array.
+  __ lwz(r7, MemOperand(cache_entry, 0));
+  __ lwz(r8, MemOperand(cache_entry, 4));
+  __ LoadP(r9, MemOperand(cache_entry, 8));
+  __ cmp(r5, r7);
+  __ bne(&calculate);
+  __ cmp(r6, r8);
+  __ bne(&calculate);
+  // Cache hit. Load result, cleanup and return.
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(
+      counters->transcendental_cache_hit(), 1, scratch0, scratch1);
+  if (tagged) {
+    // Pop input value from stack and load result into r3.
+    __ pop();
+    __ mr(r3, r9);
+  } else {
+    // Load result into d2.
+    __ lfd(d2, FieldMemOperand(r9, HeapNumber::kValueOffset));
+  }
+  __ Ret();
+
+  __ bind(&calculate);
+  __ IncrementCounter(
+      counters->transcendental_cache_miss(), 1, scratch0, scratch1);
+  if (tagged) {
+    __ bind(&invalid_cache);
+    ExternalReference runtime_function =
+        ExternalReference(RuntimeFunction(), masm->isolate());
+    __ TailCallExternalReference(runtime_function, 1, 1);
+  } else {
+    Label no_update;
+    Label skip_cache;
+
+    // Call C function to calculate the result and update the cache.
+    // r3: precalculated cache entry address.
+    // r5 and r6: parts of the double value.
+    // Store r3, r5 and r6 on stack for later before calling C function.
+    __ Push(r6, r5, cache_entry);
+    GenerateCallCFunction(masm, scratch0);
+    __ GetCFunctionDoubleResult(d2);
+
+    // Try to update the cache. If we cannot allocate a
+    // heap number, we return the result without updating.
+    __ Pop(r6, r5, cache_entry);
+    __ LoadRoot(r8, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r9, scratch0, scratch1, r8, &no_update);
+    __ stfd(d2, FieldMemOperand(r9, HeapNumber::kValueOffset));
+    __ stw(r5, MemOperand(cache_entry, 0));
+    __ stw(r6, MemOperand(cache_entry, 4));
+    __ StoreP(r9, MemOperand(cache_entry, 8));
+    __ Ret();
+
+    __ bind(&invalid_cache);
+    // The cache is invalid. Call runtime which will recreate the
+    // cache.
+    __ LoadRoot(r8, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r3, scratch0, scratch1, r8, &skip_cache);
+    __ stfd(d2, FieldMemOperand(r3, HeapNumber::kValueOffset));
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      __ push(r3);
+      __ CallRuntime(RuntimeFunction(), 1);
+    }
+    __ lfd(d2, FieldMemOperand(r3, HeapNumber::kValueOffset));
+    __ Ret();
+
+    __ bind(&skip_cache);
+    // Call C function to calculate the result and answer directly
+    // without updating the cache.
+    GenerateCallCFunction(masm, scratch0);
+    __ GetCFunctionDoubleResult(d2);
+    __ bind(&no_update);
+
+    // We return the value in d2 without adding it to the cache, but
+    // we cause a scavenging GC so that future allocations will succeed.
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+
+      // Allocate an aligned object larger than a HeapNumber.
+      ASSERT(2 * kDoubleSize >= HeapNumber::kSize);
+      __ LoadSmiLiteral(scratch0, Smi::FromInt(2 * kDoubleSize));
+      __ push(scratch0);
+      __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
+    }
+    __ Ret();
+  }
+}
+
+
+void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
+                                                    Register scratch) {
+  Isolate* isolate = masm->isolate();
+
+  __ mflr(r0);
+  __ push(r0);
+  __ PrepareCallCFunction(0, 1, scratch);
+  __ fmr(d1, d2);
+  AllowExternalCallThatCantCauseGC scope(masm);
+  switch (type_) {
+    case TranscendentalCache::SIN:
+      __ CallCFunction(ExternalReference::math_sin_double_function(isolate),
+          0, 1);
+      break;
+    case TranscendentalCache::COS:
+      __ CallCFunction(ExternalReference::math_cos_double_function(isolate),
+          0, 1);
+      break;
+    case TranscendentalCache::TAN:
+      __ CallCFunction(ExternalReference::math_tan_double_function(isolate),
+          0, 1);
+      break;
+    case TranscendentalCache::LOG:
+      __ CallCFunction(ExternalReference::math_log_double_function(isolate),
+          0, 1);
+      break;
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+  __ pop(r0);
+  __ mtlr(r0);
+}
+
+
+Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
+  switch (type_) {
+    // Add more cases when necessary.
+    case TranscendentalCache::SIN: return Runtime::kMath_sin;
+    case TranscendentalCache::COS: return Runtime::kMath_cos;
+    case TranscendentalCache::TAN: return Runtime::kMath_tan;
+    case TranscendentalCache::LOG: return Runtime::kMath_log;
+    default:
+      UNIMPLEMENTED();
+      return Runtime::kAbort;
+  }
+}
+
+
+void StackCheckStub::Generate(MacroAssembler* masm) {
+  __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
+}
+
+
+void InterruptStub::Generate(MacroAssembler* masm) {
+  __ TailCallRuntime(Runtime::kInterrupt, 0, 1);
+}
+
+
+void MathPowStub::Generate(MacroAssembler* masm) {
+  const Register base = r4;
+  const Register exponent = r5;
+  const Register heapnumbermap = r8;
+  const Register heapnumber = r3;
+  const DoubleRegister double_base = d1;
+  const DoubleRegister double_exponent = d2;
+  const DoubleRegister double_result = d3;
+  const DoubleRegister double_scratch = d0;
+  const Register scratch = r22;
+  const Register scratch2 = r10;
+
+  Label call_runtime, done, int_exponent;
+  if (exponent_type_ == ON_STACK) {
+    Label base_is_smi, unpack_exponent;
+    // The exponent and base are supplied as arguments on the stack.
+    // This can only happen if the stub is called from non-optimized code.
+    // Load input parameters from stack to double registers.
+    __ LoadP(base, MemOperand(sp, 1 * kPointerSize));
+    __ LoadP(exponent, MemOperand(sp, 0 * kPointerSize));
+
+    __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
+
+    __ UntagAndJumpIfSmi(scratch, base, &base_is_smi);
+    __ LoadP(scratch, FieldMemOperand(base, JSObject::kMapOffset));
+    __ cmp(scratch, heapnumbermap);
+    __ bne(&call_runtime);
+
+    __ lfd(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
+    __ b(&unpack_exponent);
+
+    __ bind(&base_is_smi);
+    FloatingPointHelper::ConvertIntToDouble(masm, scratch, double_base);
+    __ bind(&unpack_exponent);
+
+    __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
+    __ LoadP(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
+    __ cmp(scratch, heapnumbermap);
+    __ bne(&call_runtime);
+
+    __ lfd(double_exponent,
+           FieldMemOperand(exponent, HeapNumber::kValueOffset));
+  } else if (exponent_type_ == TAGGED) {
+    // Base is already in double_base.
+    __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
+
+    __ lfd(double_exponent,
+           FieldMemOperand(exponent, HeapNumber::kValueOffset));
+  }
+
+  if (exponent_type_ != INTEGER) {
+    // Detect integer exponents stored as double.
+    __ EmitVFPTruncate(kRoundToZero,
+                       scratch,
+                       double_exponent,
+                       scratch2,
+                       double_scratch,
+                       kCheckForInexactConversion);
+    __ beq(&int_exponent);
+
+    if (exponent_type_ == ON_STACK) {
+      // Detect square root case.  Crankshaft detects constant +/-0.5 at
+      // compile time and uses DoMathPowHalf instead.  We then skip this check
+      // for non-constant cases of +/-0.5 as these hardly occur.
+      Label not_plus_half, not_minus_inf1, not_minus_inf2;
+
+      // Test for 0.5.
+      __ LoadDoubleLiteral(double_scratch, 0.5, scratch);
+      __ fcmpu(double_exponent, double_scratch);
+      __ bne(&not_plus_half);
+
+      // Calculates square root of base.  Check for the special case of
+      // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
+      __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch);
+      __ fcmpu(double_base, double_scratch);
+      __ bne(&not_minus_inf1);
+      __ fneg(double_result, double_scratch);
+      __ b(&done);
+      __ bind(&not_minus_inf1);
+
+      // Add +0 to convert -0 to +0.
+      __ fadd(double_scratch, double_base, kDoubleRegZero);
+      __ fsqrt(double_result, double_scratch);
+      __ b(&done);
+
+      __ bind(&not_plus_half);
+      __ LoadDoubleLiteral(double_scratch, -0.5, scratch);
+      __ fcmpu(double_exponent, double_scratch);
+      __ bne(&call_runtime);
+
+      // Calculates square root of base.  Check for the special case of
+      // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
+      __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch);
+      __ fcmpu(double_base, double_scratch);
+      __ bne(&not_minus_inf2);
+      __ fmr(double_result, kDoubleRegZero);
+      __ b(&done);
+      __ bind(&not_minus_inf2);
+
+      // Add +0 to convert -0 to +0.
+      __ fadd(double_scratch, double_base, kDoubleRegZero);
+      __ LoadDoubleLiteral(double_result, 1.0, scratch);
+      __ fsqrt(double_scratch, double_scratch);
+      __ fdiv(double_result, double_result, double_scratch);
+      __ b(&done);
+    }
+
+    __ mflr(r0);
+    __ push(r0);
+    {
+      AllowExternalCallThatCantCauseGC scope(masm);
+      __ PrepareCallCFunction(0, 2, scratch);
+      __ SetCallCDoubleArguments(double_base, double_exponent);
+      __ CallCFunction(
+          ExternalReference::power_double_double_function(masm->isolate()),
+          0, 2);
+    }
+    __ pop(r0);
+    __ mtlr(r0);
+    __ GetCFunctionDoubleResult(double_result);
+    __ b(&done);
+  }
+
+  // Calculate power with integer exponent.
+  __ bind(&int_exponent);
+
+  // Get two copies of exponent in the registers scratch and exponent.
+  if (exponent_type_ == INTEGER) {
+    __ mr(scratch, exponent);
+  } else {
+    // Exponent has previously been stored into scratch as untagged integer.
+    __ mr(exponent, scratch);
+  }
+  __ fmr(double_scratch, double_base);  // Back up base.
+  __ li(scratch2, Operand(1));
+  FloatingPointHelper::ConvertIntToDouble(masm, scratch2, double_result);
+
+  // Get absolute value of exponent.
+  Label positive_exponent;
+  __ cmpi(scratch, Operand::Zero());
+  __ bge(&positive_exponent);
+  __ neg(scratch, scratch);
+  __ bind(&positive_exponent);
+
+  Label while_true, no_carry, loop_end;
+  __ bind(&while_true);
+  __ andi(scratch2, scratch, Operand(1));
+  __ beq(&no_carry, cr0);
+  __ fmul(double_result, double_result, double_scratch);
+  __ bind(&no_carry);
+  __ ShiftRightArithImm(scratch, scratch, 1, SetRC);
+  __ beq(&loop_end, cr0);
+  __ fmul(double_scratch, double_scratch, double_scratch);
+  __ b(&while_true);
+  __ bind(&loop_end);
+
+  __ cmpi(exponent, Operand::Zero());
+  __ bge(&done);
+
+  __ li(scratch2, Operand(1));
+  FloatingPointHelper::ConvertIntToDouble(masm, scratch2, double_scratch);
+  __ fdiv(double_result, double_scratch, double_result);
+  // Test whether result is zero.  Bail out to check for subnormal result.
+  // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
+  __ fcmpu(double_result, kDoubleRegZero);
+  __ bne(&done);
+  // double_exponent may not containe the exponent value if the input was a
+  // smi.  We set it with exponent value before bailing out.
+  FloatingPointHelper::ConvertIntToDouble(masm, exponent, double_exponent);
+
+  // Returning or bailing out.
+  Counters* counters = masm->isolate()->counters();
+  if (exponent_type_ == ON_STACK) {
+    // The arguments are still on the stack.
+    __ bind(&call_runtime);
+    __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
+
+    // The stub is called from non-optimized code, which expects the result
+    // as heap number in exponent.
+    __ bind(&done);
+    __ AllocateHeapNumber(
+        heapnumber, scratch, scratch2, heapnumbermap, &call_runtime);
+    __ stfd(double_result,
+            FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
+    ASSERT(heapnumber.is(r3));
+    __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
+    __ Ret(2);
+  } else {
+    __ mflr(r0);
+    __ push(r0);
+    {
+      AllowExternalCallThatCantCauseGC scope(masm);
+      __ PrepareCallCFunction(0, 2, scratch);
+      __ SetCallCDoubleArguments(double_base, double_exponent);
+      __ CallCFunction(
+          ExternalReference::power_double_double_function(masm->isolate()),
+          0, 2);
+    }
+    __ pop(r0);
+    __ mtlr(r0);
+    __ GetCFunctionDoubleResult(double_result);
+
+    __ bind(&done);
+    __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
+    __ Ret();
+  }
+}
+
+
+bool CEntryStub::NeedsImmovableCode() {
+  return true;
+}
+
+
+bool CEntryStub::IsPregenerated() {
+  return (!save_doubles_ || ISOLATE->fp_stubs_generated()) &&
+          result_size_ == 1;
+}
+
+
+void CodeStub::GenerateStubsAheadOfTime() {
+  CEntryStub::GenerateAheadOfTime();
+  StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime();
+  RecordWriteStub::GenerateFixedRegStubsAheadOfTime();
+}
+
+
+void CodeStub::GenerateFPStubs() {
+  CEntryStub save_doubles(1, kSaveFPRegs);
+  Handle<Code> code = save_doubles.GetCode();
+  code->set_is_pregenerated(true);
+  StoreBufferOverflowStub stub(kSaveFPRegs);
+  stub.GetCode()->set_is_pregenerated(true);
+  code->GetIsolate()->set_fp_stubs_generated(true);
+}
+
+
+void CEntryStub::GenerateAheadOfTime() {
+  CEntryStub stub(1, kDontSaveFPRegs);
+  Handle<Code> code = stub.GetCode();
+  code->set_is_pregenerated(true);
+}
+
+
+void CEntryStub::GenerateCore(MacroAssembler* masm,
+                              Label* throw_normal_exception,
+                              Label* throw_termination_exception,
+                              Label* throw_out_of_memory_exception,
+                              bool do_gc,
+                              bool always_allocate) {
+  // r3: result parameter for PerformGC, if any
+  // r14: number of arguments including receiver  (C callee-saved)
+  // r15: pointer to builtin function  (C callee-saved)
+  // r16: pointer to the first argument (C callee-saved)
+  Isolate* isolate = masm->isolate();
+  Register isolate_reg = no_reg;
+
+  if (do_gc) {
+    // Passing r3.
+    __ PrepareCallCFunction(1, 0, r4);
+    __ CallCFunction(ExternalReference::perform_gc_function(isolate),
+        1, 0);
+  }
+
+  ExternalReference scope_depth =
+      ExternalReference::heap_always_allocate_scope_depth(isolate);
+  if (always_allocate) {
+    __ mov(r3, Operand(scope_depth));
+    __ lwz(r4, MemOperand(r3));
+    __ addi(r4, r4, Operand(1));
+    __ stw(r4, MemOperand(r3));
+  }
+
+  // PPC LINUX ABI:
+  // The #if below used to be !USE_SIMULATOR but needed
+  // to change to support nativesim=true builds
+#if defined(V8_HOST_ARCH_PPC64) || defined(V8_HOST_ARCH_PPC)
+  // Call C built-in on native hardware.
+#if defined(V8_TARGET_ARCH_PPC64)
+
+#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
+  if (result_size_ < 2) {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+    __ mr(r3, r14);
+#else
+    // r3 = argc << 32 (for alignment), r4 = argv
+    __ ShiftLeftImm(r3, r14, Operand(32));
+#endif
+    __ mr(r4, r16);
+    isolate_reg = r5;
+  } else {
+    ASSERT_EQ(2, result_size_);
+    // The return value is 16-byte non-scalar value.
+    // Use frame storage reserved by calling function to pass return
+    // buffer as implicit first argument.
+    __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+    __ mr(r4, r14);
+#else
+    // r4 = argc << 32 (for alignment), r5 = argv
+    __ ShiftLeftImm(r4, r14, Operand(32));
+#endif
+    __ mr(r5, r16);
+    isolate_reg = r6;
+  }
+#else
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  __ mr(r3, r14);
+#else
+  // r3 = argc << 32 (for alignment), r4 = argv
+  __ ShiftLeftImm(r3, r14, Operand(32));
+#endif
+  __ mr(r4, r16);
+  isolate_reg = r5;
+#endif
+
+#elif defined(_AIX)  // 32-bit AIX
+  // r3 = argc, r4 = argv
+  __ mr(r3, r14);
+  __ mr(r4, r16);
+  isolate_reg = r5;
+#else  // 32-bit linux
+  // Use frame storage reserved by calling function
+  // PPC passes C++ objects by reference not value
+  // This builds an object in the stack frame
+  __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
+  __ StoreP(r14, MemOperand(r3));
+  __ StoreP(r16, MemOperand(r3, kPointerSize));
+  isolate_reg = r4;
+#endif
+#else  // Simulated
+  // Call C built-in using simulator.
+  // r3 = argc, r4 = argv
+#if defined(V8_TARGET_ARCH_PPC64) && __BYTE_ORDER == __BIG_ENDIAN
+  __ ShiftLeftImm(r3, r14, Operand(32));
+#else
+  __ mr(r3, r14);
+#endif
+  __ mr(r4, r16);
+  isolate_reg = r5;
+#endif
+
+  __ mov(isolate_reg, Operand(ExternalReference::isolate_address()));
+
+#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
+  // Native AIX/PPC64 Linux use a function descriptor.
+  __ LoadP(ToRegister(2), MemOperand(r15, kPointerSize));  // TOC
+  __ LoadP(ip, MemOperand(r15, 0));  // Instruction address
+  Register target = ip;
+#elif ABI_TOC_ADDRESSABILITY_VIA_IP
+  Register target = ip;
+  __ Move(ip, r15);
+#else
+  Register target = r15;
+#endif
+
+  // To let the GC traverse the return address of the exit frames, we need to
+  // know where the return address is. The CEntryStub is unmovable, so
+  // we can store the address on the stack to be able to find it again and
+  // we never have to restore it, because it will not change.
+  // Compute the return address in lr to return to after the jump below. Pc is
+  // already at '+ 8' from the current instruction but return is after three
+  // instructions so add another 4 to pc to get the return address.
+  { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
+    Label here;
+    __ b(&here, SetLK);
+    __ bind(&here);
+    __ mflr(r8);
+
+// Constant used below is dependent on size of Call() macro instructions
+    __ addi(r0, r8, Operand(20));
+
+    __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
+    __ Call(target);
+  }
+
+  if (always_allocate) {
+    // It's okay to clobber r5 and r6 here. Don't mess with r3 and r4
+    // though (contain the result).
+    __ mov(r5, Operand(scope_depth));
+    __ lwz(r6, MemOperand(r5));
+    __ subi(r6, r6, Operand(1));
+    __ stw(r6, MemOperand(r5));
+  }
+
+  // check for failure result
+  Label failure_returned;
+  STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
+#if defined(V8_TARGET_ARCH_PPC64) && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
+  // If return value is on the stack, pop it to registers.
+  if (result_size_ > 1) {
+    ASSERT_EQ(2, result_size_);
+    __ LoadP(r4, MemOperand(r3, kPointerSize));
+    __ LoadP(r3, MemOperand(r3));
+  }
+#endif
+  // Lower 2 bits of r5 are 0 iff r3 has failure tag.
+  __ addi(r5, r3, Operand(1));
+  STATIC_ASSERT(kFailureTagMask < 0x8000);
+  __ andi(r0, r5, Operand(kFailureTagMask));
+  __ beq(&failure_returned, cr0);
+
+  // Exit C frame and return.
+  // r3:r4: result
+  // sp: stack pointer
+  // fp: frame pointer
+  //  Callee-saved register r14 still holds argc.
+  __ LeaveExitFrame(save_doubles_, r14);
+  __ blr();
+
+  // check if we should retry or throw exception
+  Label retry;
+  __ bind(&failure_returned);
+  STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
+  __ andi(r0, r3, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
+  __ beq(&retry, cr0);
+
+  // Special handling of out of memory exceptions.
+  Failure* out_of_memory = Failure::OutOfMemoryException();
+  __ cmpi(r3, Operand(reinterpret_cast<intptr_t>(out_of_memory)));
+  __ beq(throw_out_of_memory_exception);
+
+  // Retrieve the pending exception and clear the variable.
+  __ mov(r6, Operand(isolate->factory()->the_hole_value()));
+  __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
+                                       isolate)));
+  __ LoadP(r3, MemOperand(ip));
+  __ StoreP(r6, MemOperand(ip));
+
+  // Special handling of termination exceptions which are uncatchable
+  // by javascript code.
+  __ mov(r6, Operand(isolate->factory()->termination_exception()));
+  __ cmp(r3, r6);
+  __ beq(throw_termination_exception);
+
+  // Handle normal exception.
+  __ b(throw_normal_exception);
+
+  __ bind(&retry);  // pass last failure (r3) as parameter (r3) when retrying
+}
+
+
+void CEntryStub::Generate(MacroAssembler* masm) {
+  // Called from JavaScript; parameters are on stack as if calling JS function
+  // r3: number of arguments including receiver
+  // r4: pointer to builtin function
+  // fp: frame pointer  (restored after C call)
+  // sp: stack pointer  (restored as callee's sp after C call)
+  // cp: current context  (C callee-saved)
+
+  // Result returned in r3 or r3+r4 by default.
+
+  // NOTE: Invocations of builtins may return failure objects
+  // instead of a proper result. The builtin entry handles
+  // this by performing a garbage collection and retrying the
+  // builtin once.
+
+  // Compute the argv pointer in a callee-saved register.
+  __ ShiftLeftImm(r16, r3, Operand(kPointerSizeLog2));
+  __ add(r16, r16, sp);
+  __ subi(r16, r16, Operand(kPointerSize));
+
+  // Enter the exit frame that transitions from JavaScript to C++.
+  FrameScope scope(masm, StackFrame::MANUAL);
+
+  // Need at least one extra slot for return address location.
+  int arg_stack_space = 1;
+
+  // PPC LINUX ABI:
+  // The #if immediately below was !USE_SIMULATOR, but needed
+  // to change to support nativesim=true builds
+#if defined(V8_HOST_ARCH_PPC64) || defined(V8_HOST_ARCH_PPC)
+#if defined(V8_TARGET_ARCH_PPC64) && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
+  // Pass buffer for return value on stack if necessary
+  if (result_size_ > 1) {
+    ASSERT_EQ(2, result_size_);
+    arg_stack_space += 2;
+  }
+#elif !defined(_AIX)
+  // 32-bit linux
+  // Pass C++ objects by reference not value
+  arg_stack_space += 2;
+#endif
+#endif
+
+  __ EnterExitFrame(save_doubles_, arg_stack_space);
+
+  // Set up argc and the builtin function in callee-saved registers.
+  __ mr(r14, r3);
+  __ mr(r15, r4);
+
+  // r14: number of arguments (C callee-saved)
+  // r15: pointer to builtin function (C callee-saved)
+  // r16: pointer to first argument (C callee-saved)
+
+  Label throw_normal_exception;
+  Label throw_termination_exception;
+  Label throw_out_of_memory_exception;
+
+  // Call into the runtime system.
+  GenerateCore(masm,
+               &throw_normal_exception,
+               &throw_termination_exception,
+               &throw_out_of_memory_exception,
+               false,
+               false);
+
+  // Do space-specific GC and retry runtime call.
+  GenerateCore(masm,
+               &throw_normal_exception,
+               &throw_termination_exception,
+               &throw_out_of_memory_exception,
+               true,
+               false);
+
+  // Do full GC and retry runtime call one final time.
+  Failure* failure = Failure::InternalError();
+  __ mov(r3, Operand(reinterpret_cast<intptr_t>(failure)));
+  GenerateCore(masm,
+               &throw_normal_exception,
+               &throw_termination_exception,
+               &throw_out_of_memory_exception,
+               true,
+               true);
+
+  __ bind(&throw_out_of_memory_exception);
+  // Set external caught exception to false.
+  Isolate* isolate = masm->isolate();
+  ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
+                                    isolate);
+  __ li(r3, Operand(false, RelocInfo::NONE));
+  __ mov(r5, Operand(external_caught));
+  __ StoreP(r3, MemOperand(r5));
+
+  // Set pending exception and r0 to out of memory exception.
+  Failure* out_of_memory = Failure::OutOfMemoryException();
+  __ mov(r3, Operand(reinterpret_cast<intptr_t>(out_of_memory)));
+  __ mov(r5, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
+                                       isolate)));
+  __ StoreP(r3, MemOperand(r5));
+  // Fall through to the next label.
+
+  __ bind(&throw_termination_exception);
+  __ ThrowUncatchable(r3);
+
+  __ bind(&throw_normal_exception);
+  __ Throw(r3);
+}
+
+
+void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
+  // r3: code entry
+  // r4: function
+  // r5: receiver
+  // r6: argc
+  // [sp+0]: argv
+
+  Label invoke, handler_entry, exit;
+
+  // Called from C
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+
+  // PPC LINUX ABI:
+  // preserve LR in pre-reserved slot in caller's frame
+  __ mflr(r0);
+  __ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
+
+  // Save callee saved registers on the stack.
+  __ MultiPush(kCalleeSaved);
+
+  // Floating point regs FPR0 - FRP13 are volatile
+  // FPR14-FPR31 are non-volatile, but sub-calls will save them for us
+
+//  int offset_to_argv = kPointerSize * 22; // matches (22*4) above
+//  __ lwz(r7, MemOperand(sp, offset_to_argv));
+
+  // Push a frame with special values setup to mark it as an entry frame.
+  // r3: code entry
+  // r4: function
+  // r5: receiver
+  // r6: argc
+  // r7: argv
+  Isolate* isolate = masm->isolate();
+  __ li(r0, Operand(-1));  // Push a bad frame pointer to fail if it is used.
+  __ push(r0);
+  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
+  __ LoadSmiLiteral(r0, Smi::FromInt(marker));
+  __ push(r0);
+  __ push(r0);
+  // Save copies of the top frame descriptor on the stack.
+  __ mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
+  __ LoadP(r0, MemOperand(r8));
+  __ push(r0);
+
+  // Set up frame pointer for the frame to be pushed.
+  __ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
+
+  // If this is the outermost JS call, set js_entry_sp value.
+  Label non_outermost_js;
+  ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate);
+  __ mov(r8, Operand(ExternalReference(js_entry_sp)));
+  __ LoadP(r9, MemOperand(r8));
+  __ cmpi(r9, Operand::Zero());
+  __ bne(&non_outermost_js);
+  __ StoreP(fp, MemOperand(r8));
+  __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
+  Label cont;
+  __ b(&cont);
+  __ bind(&non_outermost_js);
+  __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
+  __ bind(&cont);
+  __ push(ip);  // frame-type
+
+  // Jump to a faked try block that does the invoke, with a faked catch
+  // block that sets the pending exception.
+  __ b(&invoke);
+
+  __ bind(&handler_entry);
+  handler_offset_ = handler_entry.pos();
+  // Caught exception: Store result (exception) in the pending exception
+  // field in the JSEnv and return a failure sentinel.  Coming in here the
+  // fp will be invalid because the PushTryHandler below sets it to 0 to
+  // signal the existence of the JSEntry frame.
+  __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
+                                       isolate)));
+
+  __ StoreP(r3, MemOperand(ip));
+  __ mov(r3, Operand(reinterpret_cast<intptr_t>(Failure::Exception())));
+  __ b(&exit);
+
+  // Invoke: Link this frame into the handler chain.  There's only one
+  // handler block in this code object, so its index is 0.
+  __ bind(&invoke);
+  // Must preserve r0-r4, r5-r7 are available. (needs update for PPC)
+  __ PushTryHandler(StackHandler::JS_ENTRY, 0);
+  // If an exception not caught by another handler occurs, this handler
+  // returns control to the code after the b(&invoke) above, which
+  // restores all kCalleeSaved registers (including cp and fp) to their
+  // saved values before returning a failure to C.
+
+  // Clear any pending exceptions.
+  __ mov(r8, Operand(isolate->factory()->the_hole_value()));
+  __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
+                                       isolate)));
+  __ StoreP(r8, MemOperand(ip));
+
+  // Invoke the function by calling through JS entry trampoline builtin.
+  // Notice that we cannot store a reference to the trampoline code directly in
+  // this stub, because runtime stubs are not traversed when doing GC.
+
+  // Expected registers by Builtins::JSEntryTrampoline
+  // r3: code entry
+  // r4: function
+  // r5: receiver
+  // r6: argc
+  // r7: argv
+  if (is_construct) {
+    ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
+                                      isolate);
+    __ mov(ip, Operand(construct_entry));
+  } else {
+    ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
+    __ mov(ip, Operand(entry));
+  }
+  __ LoadP(ip, MemOperand(ip));  // deref address
+
+  // Branch and link to JSEntryTrampoline.
+  // the address points to the start of the code object, skip the header
+  __ addi(r0, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ mtlr(r0);
+  __ bclr(BA, SetLK);  // make the call
+
+  // Unlink this frame from the handler chain.
+  __ PopTryHandler();
+
+  __ bind(&exit);  // r3 holds result
+  // Check if the current stack frame is marked as the outermost JS frame.
+  Label non_outermost_js_2;
+  __ pop(r8);
+  __ CmpSmiLiteral(r8, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME), r0);
+  __ bne(&non_outermost_js_2);
+  __ mov(r9, Operand::Zero());
+  __ mov(r8, Operand(ExternalReference(js_entry_sp)));
+  __ StoreP(r9, MemOperand(r8));
+  __ bind(&non_outermost_js_2);
+
+  // Restore the top frame descriptors from the stack.
+  __ pop(r6);
+  __ mov(ip,
+         Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
+  __ StoreP(r6, MemOperand(ip));
+
+  // Reset the stack to the callee saved registers.
+  __ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
+
+  // Restore callee-saved registers and return.
+#ifdef DEBUG
+  if (FLAG_debug_code) {
+    Label here;
+    __ b(&here, SetLK);
+    __ bind(&here);
+  }
+#endif
+
+  __ MultiPop(kCalleeSaved);
+
+  __ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
+  __ mtctr(r0);
+  __ bcr();
+}
+
+
+// Uses registers r3 to r7.
+// Expected input (depending on whether args are in registers or on the stack):
+// * object: r3 or at sp + 1 * kPointerSize.
+// * function: r4 or at sp.
+//
+// An inlined call site may have been generated before calling this stub.
+// In this case the offset to the inline site to patch is passed on the stack,
+// in the safepoint slot for register r7.
+// (See LCodeGen::DoInstanceOfKnownGlobal)
+void InstanceofStub::Generate(MacroAssembler* masm) {
+  // Call site inlining and patching implies arguments in registers.
+  ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck());
+  // ReturnTrueFalse is only implemented for inlined call sites.
+  ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck());
+
+  // Fixed register usage throughout the stub:
+  const Register object = r3;  // Object (lhs).
+  Register map = r6;  // Map of the object.
+  const Register function = r4;  // Function (rhs).
+  const Register prototype = r7;  // Prototype of the function.
+  const Register inline_site = r9;
+  const Register scratch = r5;
+  const Register scratch2 = r8;
+  Register scratch3 = no_reg;
+
+#if V8_TARGET_ARCH_PPC64
+  const int32_t kDeltaToLoadBoolResult = 9 * Assembler::kInstrSize;
+#else
+  const int32_t kDeltaToLoadBoolResult = 5 * Assembler::kInstrSize;
+#endif
+
+  Label slow, loop, is_instance, is_not_instance, not_js_object;
+
+  if (!HasArgsInRegisters()) {
+    __ LoadP(object, MemOperand(sp, 1 * kPointerSize));
+    __ LoadP(function, MemOperand(sp, 0));
+  }
+
+  // Check that the left hand is a JS object and load map.
+  __ JumpIfSmi(object, &not_js_object);
+  __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
+
+  // If there is a call site cache don't look in the global cache, but do the
+  // real lookup and update the call site cache.
+  if (!HasCallSiteInlineCheck()) {
+    Label miss;
+    __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
+    __ bne(&miss);
+    __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex);
+    __ bne(&miss);
+    __ LoadRoot(r3, Heap::kInstanceofCacheAnswerRootIndex);
+    __ Ret(HasArgsInRegisters() ? 0 : 2);
+
+    __ bind(&miss);
+  }
+
+  // Get the prototype of the function.
+  __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true);
+
+  // Check that the function prototype is a JS object.
+  __ JumpIfSmi(prototype, &slow);
+  __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
+
+  // Update the global instanceof or call site inlined cache with the current
+  // map and function. The cached answer will be set when it is known below.
+  if (!HasCallSiteInlineCheck()) {
+    __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
+    __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
+  } else {
+    ASSERT(HasArgsInRegisters());
+    // Patch the (relocated) inlined map check.
+
+    // The offset was stored in r7 safepoint slot.
+    // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal)
+    __ LoadFromSafepointRegisterSlot(scratch, r7);
+    __ mflr(inline_site);
+    __ sub(inline_site, inline_site, scratch);
+    // Get the map location in scratch and patch it.
+    __ GetRelocatedValueLocation(inline_site, scratch, scratch2);
+    __ StoreP(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset),
+              r0);
+  }
+
+  // Register mapping: r6 is object map and r7 is function prototype.
+  // Get prototype of object into r5.
+  __ LoadP(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
+
+  // We don't need map any more. Use it as a scratch register.
+  scratch3 = map;
+  map = no_reg;
+
+  // Loop through the prototype chain looking for the function prototype.
+  __ LoadRoot(scratch3, Heap::kNullValueRootIndex);
+  __ bind(&loop);
+  __ cmp(scratch, prototype);
+  __ beq(&is_instance);
+  __ cmp(scratch, scratch3);
+  __ beq(&is_not_instance);
+  __ LoadP(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
+  __ LoadP(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
+  __ b(&loop);
+
+  __ bind(&is_instance);
+  if (!HasCallSiteInlineCheck()) {
+    __ LoadSmiLiteral(r3, Smi::FromInt(0));
+    __ StoreRoot(r3, Heap::kInstanceofCacheAnswerRootIndex);
+  } else {
+    // Patch the call site to return true.
+    __ LoadRoot(r3, Heap::kTrueValueRootIndex);
+    __ addi(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
+    // Get the boolean result location in scratch and patch it.
+    __ PatchRelocatedValue(inline_site, scratch, r3);
+
+    if (!ReturnTrueFalseObject()) {
+      __ LoadSmiLiteral(r3, Smi::FromInt(0));
+    }
+  }
+  __ Ret(HasArgsInRegisters() ? 0 : 2);
+
+  __ bind(&is_not_instance);
+  if (!HasCallSiteInlineCheck()) {
+    __ LoadSmiLiteral(r3, Smi::FromInt(1));
+    __ StoreRoot(r3, Heap::kInstanceofCacheAnswerRootIndex);
+  } else {
+    // Patch the call site to return false.
+    __ LoadRoot(r3, Heap::kFalseValueRootIndex);
+    __ addi(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
+    // Get the boolean result location in scratch and patch it.
+    __ PatchRelocatedValue(inline_site, scratch, r3);
+
+    if (!ReturnTrueFalseObject()) {
+      __ LoadSmiLiteral(r3, Smi::FromInt(1));
+    }
+  }
+  __ Ret(HasArgsInRegisters() ? 0 : 2);
+
+  Label object_not_null, object_not_null_or_smi;
+  __ bind(&not_js_object);
+  // Before null, smi and string value checks, check that the rhs is a function
+  // as for a non-function rhs an exception needs to be thrown.
+  __ JumpIfSmi(function, &slow);
+  __ CompareObjectType(function, scratch3, scratch, JS_FUNCTION_TYPE);
+  __ bne(&slow);
+
+  // Null is not instance of anything.
+  __ Cmpi(scratch, Operand(masm->isolate()->factory()->null_value()), r0);
+  __ bne(&object_not_null);
+  __ LoadSmiLiteral(r3, Smi::FromInt(1));
+  __ Ret(HasArgsInRegisters() ? 0 : 2);
+
+  __ bind(&object_not_null);
+  // Smi values are not instances of anything.
+  __ JumpIfNotSmi(object, &object_not_null_or_smi);
+  __ LoadSmiLiteral(r3, Smi::FromInt(1));
+  __ Ret(HasArgsInRegisters() ? 0 : 2);
+
+  __ bind(&object_not_null_or_smi);
+  // String values are not instances of anything.
+  __ IsObjectJSStringType(object, scratch, &slow);
+  __ LoadSmiLiteral(r3, Smi::FromInt(1));
+  __ Ret(HasArgsInRegisters() ? 0 : 2);
+
+  // Slow-case.  Tail call builtin.
+  __ bind(&slow);
+  if (!ReturnTrueFalseObject()) {
+    if (HasArgsInRegisters()) {
+      __ Push(r3, r4);
+    }
+  __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
+  } else {
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      __ Push(r3, r4);
+      __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
+    }
+    Label true_value, done;
+    __ cmpi(r3, Operand::Zero());
+    __ beq(&true_value);
+
+    __ LoadRoot(r3, Heap::kFalseValueRootIndex);
+    __ b(&done);
+
+    __ bind(&true_value);
+    __ LoadRoot(r3, Heap::kTrueValueRootIndex);
+
+    __ bind(&done);
+    __ Ret(HasArgsInRegisters() ? 0 : 2);
+  }
+}
+
+
+Register InstanceofStub::left() { return r3; }
+
+
+Register InstanceofStub::right() { return r4; }
+
+
+void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
+  // The displacement is the offset of the last parameter (if any)
+  // relative to the frame pointer.
+  const int kDisplacement =
+      StandardFrameConstants::kCallerSPOffset - kPointerSize;
+
+  // Check that the key is a smi.
+  Label slow;
+  __ JumpIfNotSmi(r4, &slow);
+
+  // Check if the calling frame is an arguments adaptor frame.
+  Label adaptor;
+  __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kContextOffset));
+  STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
+  __ CmpSmiLiteral(r6, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+  __ beq(&adaptor);
+
+  // Check index against formal parameters count limit passed in
+  // through register r3. Use unsigned comparison to get negative
+  // check for free.
+  __ cmpl(r4, r3);
+  __ bge(&slow);
+
+  // Read the argument from the stack and return it.
+  __ sub(r6, r3, r4);
+  __ SmiToPtrArrayOffset(r6, r6);
+  __ add(r6, fp, r6);
+  __ LoadP(r3, MemOperand(r6, kDisplacement));
+  __ blr();
+
+  // Arguments adaptor case: Check index against actual arguments
+  // limit found in the arguments adaptor frame. Use unsigned
+  // comparison to get negative check for free.
+  __ bind(&adaptor);
+  __ LoadP(r3, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ cmpl(r4, r3);
+  __ bge(&slow);
+
+  // Read the argument from the adaptor frame and return it.
+  __ sub(r6, r3, r4);
+  __ SmiToPtrArrayOffset(r6, r6);
+  __ add(r6, r5, r6);
+  __ LoadP(r3, MemOperand(r6, kDisplacement));
+  __ blr();
+
+  // Slow-case: Handle non-smi or out-of-bounds access to arguments
+  // by calling the runtime system.
+  __ bind(&slow);
+  __ push(r4);
+  __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
+}
+
+
+void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
+  // sp[0] : number of parameters
+  // sp[1] : receiver displacement
+  // sp[2] : function
+
+  // Check if the calling frame is an arguments adaptor frame.
+  Label runtime;
+  __ LoadP(r6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(r5, MemOperand(r6, StandardFrameConstants::kContextOffset));
+  STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
+  __ CmpSmiLiteral(r5, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+  __ bne(&runtime);
+
+  // Patch the arguments.length and the parameters pointer in the current frame.
+  __ LoadP(r5, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ StoreP(r5, MemOperand(sp, 0 * kPointerSize));
+  __ SmiToPtrArrayOffset(r5, r5);
+  __ add(r6, r6, r5);
+  __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
+  __ StoreP(r6, MemOperand(sp, 1 * kPointerSize));
+
+  __ bind(&runtime);
+  __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
+}
+
+
+void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
+  // Stack layout:
+  //  sp[0] : number of parameters (tagged)
+  //  sp[1] : address of receiver argument
+  //  sp[2] : function
+  // Registers used over whole function:
+  //  r9 : allocated object (tagged)
+  //  r22 : mapped parameter count (tagged)
+
+  __ LoadP(r4, MemOperand(sp, 0 * kPointerSize));
+  // r4 = parameter count (tagged)
+
+  // Check if the calling frame is an arguments adaptor frame.
+  Label runtime;
+  Label adaptor_frame, try_allocate;
+  __ LoadP(r6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(r5, MemOperand(r6, StandardFrameConstants::kContextOffset));
+  STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
+  __ CmpSmiLiteral(r5, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+  __ beq(&adaptor_frame);
+
+  // No adaptor, parameter count = argument count.
+  __ mr(r5, r4);
+  __ b(&try_allocate);
+
+  // We have an adaptor frame. Patch the parameters pointer.
+  __ bind(&adaptor_frame);
+  __ LoadP(r5, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ SmiToPtrArrayOffset(r7, r5);
+  __ add(r6, r6, r7);
+  __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
+  __ StoreP(r6, MemOperand(sp, 1 * kPointerSize));
+
+  // r4 = parameter count (tagged)
+  // r5 = argument count (tagged)
+  // Compute the mapped parameter count = min(r4, r5) in r4.
+  Label skip;
+  __ cmp(r4, r5);
+  __ blt(&skip);
+  __ mr(r4, r5);
+  __ bind(&skip);
+
+  __ bind(&try_allocate);
+
+  // Compute the sizes of backing store, parameter map, and arguments object.
+  // 1. Parameter map, has 2 extra words containing context and backing store.
+  const int kParameterMapHeaderSize =
+      FixedArray::kHeaderSize + 2 * kPointerSize;
+  // If there are no mapped parameters, we do not need the parameter_map.
+  Label skip2, skip3;
+  __ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
+  __ bne(&skip2);
+  __ li(r22, Operand::Zero());
+  __ b(&skip3);
+  __ bind(&skip2);
+  __ SmiToPtrArrayOffset(r22, r4);
+  __ addi(r22, r22, Operand(kParameterMapHeaderSize));
+  __ bind(&skip3);
+
+  // 2. Backing store.
+  __ SmiToPtrArrayOffset(r7, r5);
+  __ add(r22, r22, r7);
+  __ addi(r22, r22, Operand(FixedArray::kHeaderSize));
+
+  // 3. Arguments object.
+  __ addi(r22, r22, Operand(Heap::kArgumentsObjectSize));
+
+  // Do the allocation of all three objects in one go.
+  __ AllocateInNewSpace(r22, r3, r6, r7, &runtime, TAG_OBJECT);
+
+  // r3 = address of new object(s) (tagged)
+  // r5 = argument count (tagged)
+  // Get the arguments boilerplate from the current native context into r4.
+  const int kNormalOffset =
+      Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
+  const int kAliasedOffset =
+      Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX);
+
+  __ LoadP(r7, MemOperand(r20,
+             Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset));
+  Label skip4, skip5;
+  __ cmpi(r4, Operand::Zero());
+  __ bne(&skip4);
+  __ LoadP(r7, MemOperand(r7, kNormalOffset));
+  __ b(&skip5);
+  __ bind(&skip4);
+  __ LoadP(r7, MemOperand(r7, kAliasedOffset));
+  __ bind(&skip5);
+
+  // r3 = address of new object (tagged)
+  // r4 = mapped parameter count (tagged)
+  // r5 = argument count (tagged)
+  // r7 = address of boilerplate object (tagged)
+  // Copy the JS object part.
+  for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
+    __ LoadP(r6, FieldMemOperand(r7, i));
+    __ StoreP(r6, FieldMemOperand(r3, i), r0);
+  }
+
+  // Set up the callee in-object property.
+  STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
+  __ LoadP(r6, MemOperand(sp, 2 * kPointerSize));
+  const int kCalleeOffset = JSObject::kHeaderSize +
+      Heap::kArgumentsCalleeIndex * kPointerSize;
+  __ StoreP(r6, FieldMemOperand(r3, kCalleeOffset), r0);
+
+  // Use the length (smi tagged) and set that as an in-object property too.
+  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
+  const int kLengthOffset = JSObject::kHeaderSize +
+      Heap::kArgumentsLengthIndex * kPointerSize;
+  __ StoreP(r5, FieldMemOperand(r3, kLengthOffset), r0);
+
+  // Set up the elements pointer in the allocated arguments object.
+  // If we allocated a parameter map, r7 will point there, otherwise
+  // it will point to the backing store.
+  __ addi(r7, r3, Operand(Heap::kArgumentsObjectSize));
+  __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
+
+  // r3 = address of new object (tagged)
+  // r4 = mapped parameter count (tagged)
+  // r5 = argument count (tagged)
+  // r7 = address of parameter map or backing store (tagged)
+  // Initialize parameter map. If there are no mapped arguments, we're done.
+  Label skip_parameter_map, skip6;
+  __ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
+  __ bne(&skip6);
+  // Move backing store address to r6, because it is
+  // expected there when filling in the unmapped arguments.
+  __ mr(r6, r7);
+  __ b(&skip_parameter_map);
+  __ bind(&skip6);
+
+  __ LoadRoot(r9, Heap::kNonStrictArgumentsElementsMapRootIndex);
+  __ StoreP(r9, FieldMemOperand(r7, FixedArray::kMapOffset), r0);
+  __ AddSmiLiteral(r9, r4, Smi::FromInt(2), r0);
+  __ StoreP(r9, FieldMemOperand(r7, FixedArray::kLengthOffset), r0);
+  __ StoreP(r20, FieldMemOperand(r7,
+                                 FixedArray::kHeaderSize + 0 * kPointerSize),
+            r0);
+  __ SmiToPtrArrayOffset(r9, r4);
+  __ add(r9, r7, r9);
+  __ addi(r9, r9, Operand(kParameterMapHeaderSize));
+  __ StoreP(r9, FieldMemOperand(r7,
+                                FixedArray::kHeaderSize + 1 * kPointerSize),
+            r0);
+
+  // Copy the parameter slots and the holes in the arguments.
+  // We need to fill in mapped_parameter_count slots. They index the context,
+  // where parameters are stored in reverse order, at
+  //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
+  // The mapped parameter thus need to get indices
+  //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
+  //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
+  // We loop from right to left.
+  Label parameters_loop, parameters_test;
+  __ mr(r9, r4);
+  __ LoadP(r22, MemOperand(sp, 0 * kPointerSize));
+  __ AddSmiLiteral(r22, r22, Smi::FromInt(Context::MIN_CONTEXT_SLOTS), r0);
+  __ sub(r22, r22, r4);
+  __ LoadRoot(r10, Heap::kTheHoleValueRootIndex);
+  __ SmiToPtrArrayOffset(r6, r9);
+  __ add(r6, r7, r6);
+  __ addi(r6, r6, Operand(kParameterMapHeaderSize));
+
+  // r9 = loop variable (tagged)
+  // r4 = mapping index (tagged)
+  // r6 = address of backing store (tagged)
+  // r7 = address of parameter map (tagged)
+  // r8 = temporary scratch (a.o., for address calculation)
+  // r10 = the hole value
+  __ b(&parameters_test);
+
+  __ bind(&parameters_loop);
+  __ SubSmiLiteral(r9, r9, Smi::FromInt(1), r0);
+  __ SmiToPtrArrayOffset(r8, r9);
+  __ addi(r8, r8, Operand(kParameterMapHeaderSize - kHeapObjectTag));
+  __ StorePX(r22, MemOperand(r8, r7));
+  __ subi(r8, r8, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
+  __ StorePX(r10, MemOperand(r8, r6));
+  __ AddSmiLiteral(r22, r22, Smi::FromInt(1), r0);
+  __ bind(&parameters_test);
+  __ CmpSmiLiteral(r9, Smi::FromInt(0), r0);
+  __ bne(&parameters_loop);
+
+  __ bind(&skip_parameter_map);
+  // r5 = argument count (tagged)
+  // r6 = address of backing store (tagged)
+  // r8 = scratch
+  // Copy arguments header and remaining slots (if there are any).
+  __ LoadRoot(r8, Heap::kFixedArrayMapRootIndex);
+  __ StoreP(r8, FieldMemOperand(r6, FixedArray::kMapOffset), r0);
+  __ StoreP(r5, FieldMemOperand(r6, FixedArray::kLengthOffset), r0);
+
+  Label arguments_loop, arguments_test;
+  __ mr(r22, r4);
+  __ LoadP(r7, MemOperand(sp, 1 * kPointerSize));
+  __ SmiToPtrArrayOffset(r8, r22);
+  __ sub(r7, r7, r8);
+  __ b(&arguments_test);
+
+  __ bind(&arguments_loop);
+  __ subi(r7, r7, Operand(kPointerSize));
+  __ LoadP(r9, MemOperand(r7, 0));
+  __ SmiToPtrArrayOffset(r8, r22);
+  __ add(r8, r6, r8);
+  __ StoreP(r9, FieldMemOperand(r8, FixedArray::kHeaderSize), r0);
+  __ AddSmiLiteral(r22, r22, Smi::FromInt(1), r0);
+
+  __ bind(&arguments_test);
+  __ cmp(r22, r5);
+  __ blt(&arguments_loop);
+
+  // Return and remove the on-stack parameters.
+  __ addi(sp, sp, Operand(3 * kPointerSize));
+  __ Ret();
+
+  // Do the runtime call to allocate the arguments object.
+  // r5 = argument count (tagged)
+  __ bind(&runtime);
+  __ StoreP(r5, MemOperand(sp, 0 * kPointerSize));  // Patch argument count.
+  __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
+}
+
+void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
+  // sp[0] : number of parameters
+  // sp[4] : receiver displacement
+  // sp[8] : function
+  // Check if the calling frame is an arguments adaptor frame.
+  Label adaptor_frame, try_allocate, runtime;
+  __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kContextOffset));
+  STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
+  __ CmpSmiLiteral(r6, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+  __ beq(&adaptor_frame);
+
+  // Get the length from the frame.
+  __ LoadP(r4, MemOperand(sp, 0));
+  __ b(&try_allocate);
+
+  // Patch the arguments.length and the parameters pointer.
+  __ bind(&adaptor_frame);
+  __ LoadP(r4, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ StoreP(r4, MemOperand(sp, 0));
+  __ SmiToPtrArrayOffset(r6, r4);
+  __ add(r6, r5, r6);
+  __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
+  __ StoreP(r6, MemOperand(sp, 1 * kPointerSize));
+
+  // Try the new space allocation. Start out with computing the size
+  // of the arguments object and the elements array in words.
+  Label add_arguments_object;
+  __ bind(&try_allocate);
+  __ cmpi(r4, Operand(0, RelocInfo::NONE));
+  __ beq(&add_arguments_object);
+  __ SmiUntag(r4);
+  __ addi(r4, r4, Operand(FixedArray::kHeaderSize / kPointerSize));
+  __ bind(&add_arguments_object);
+  __ addi(r4, r4, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
+
+  // Do the allocation of both objects in one go.
+  __ AllocateInNewSpace(r4,
+                        r3,
+                        r5,
+                        r6,
+                        &runtime,
+                        static_cast<AllocationFlags>(TAG_OBJECT |
+                                                     SIZE_IN_WORDS));
+
+  // Get the arguments boilerplate from the current native context.
+  __ LoadP(r7,
+           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset));
+  __ LoadP(r7, MemOperand(r7, Context::SlotOffset(
+      Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX)));
+
+  // Copy the JS object part.
+  __ CopyFields(r3, r7, r6.bit(), JSObject::kHeaderSize / kPointerSize);
+
+  // Get the length (smi tagged) and set that as an in-object property too.
+  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
+  __ LoadP(r4, MemOperand(sp, 0 * kPointerSize));
+  __ StoreP(r4, FieldMemOperand(r3, JSObject::kHeaderSize +
+                                Heap::kArgumentsLengthIndex * kPointerSize),
+            r0);
+
+  // If there are no actual arguments, we're done.
+  Label done;
+  __ cmpi(r4, Operand(0, RelocInfo::NONE));
+  __ beq(&done);
+
+  // Get the parameters pointer from the stack.
+  __ LoadP(r5, MemOperand(sp, 1 * kPointerSize));
+
+  // Set up the elements pointer in the allocated arguments object and
+  // initialize the header in the elements fixed array.
+  __ addi(r7, r3, Operand(Heap::kArgumentsObjectSizeStrict));
+  __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
+  __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
+  __ StoreP(r6, FieldMemOperand(r7, FixedArray::kMapOffset), r0);
+  __ StoreP(r4, FieldMemOperand(r7, FixedArray::kLengthOffset), r0);
+  // Untag the length for the loop.
+  __ SmiUntag(r4);
+
+  // Copy the fixed array slots.
+  Label loop;
+  // Set up r7 to point to the first array slot.
+  __ addi(r7, r7, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ bind(&loop);
+  // Pre-decrement r5 with kPointerSize on each iteration.
+  // Pre-decrement in order to skip receiver.
+  __ LoadPU(r6, MemOperand(r5, -kPointerSize));
+  // Post-increment r7 with kPointerSize on each iteration.
+  __ StoreP(r6, MemOperand(r7));
+  __ addi(r7, r7, Operand(kPointerSize));
+  __ subi(r4, r4, Operand(1));
+  __ cmpi(r4, Operand(0, RelocInfo::NONE));
+  __ bne(&loop);
+
+  // Return and remove the on-stack parameters.
+  __ bind(&done);
+  __ addi(sp, sp, Operand(3 * kPointerSize));
+  __ Ret();
+
+  // Do the runtime call to allocate the arguments object.
+  __ bind(&runtime);
+  __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
+}
+
+
+void RegExpExecStub::Generate(MacroAssembler* masm) {
+  // Just jump directly to runtime if native RegExp is not selected at compile
+  // time or if regexp entry in generated code is turned off runtime switch or
+  // at compilation.
+#ifdef V8_INTERPRETED_REGEXP
+  __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
+#else  // V8_INTERPRETED_REGEXP
+
+  // Stack frame on entry.
+  //  sp[0]: last_match_info (expected JSArray)
+  //  sp[4]: previous index
+  //  sp[8]: subject string
+  //  sp[12]: JSRegExp object
+
+  const int kLastMatchInfoOffset = 0 * kPointerSize;
+  const int kPreviousIndexOffset = 1 * kPointerSize;
+  const int kSubjectOffset = 2 * kPointerSize;
+  const int kJSRegExpOffset = 3 * kPointerSize;
+
+  Label runtime, invoke_regexp, br_over, encoding_type_UC16;
+
+  // Allocation of registers for this function. These are in callee save
+  // registers and will be preserved by the call to the native RegExp code, as
+  // this code is called using the normal C calling convention. When calling
+  // directly from generated code the native RegExp code will not do a GC and
+  // therefore the content of these registers are safe to use after the call.
+  Register subject = r26;
+  Register regexp_data = r27;
+  Register last_match_info_elements = r28;
+  Register code = r29;
+
+  // Ensure register assigments are consistent with callee save masks
+  ASSERT(subject.bit() & (kCalleeSaved & kRegExpCalleeSaved));
+  ASSERT(regexp_data.bit() & (kCalleeSaved & kRegExpCalleeSaved));
+  ASSERT(last_match_info_elements.bit() & (kCalleeSaved & kRegExpCalleeSaved));
+  ASSERT(code.bit() & (kCalleeSaved & kRegExpCalleeSaved));
+
+  // Ensure that a RegExp stack is allocated.
+  Isolate* isolate = masm->isolate();
+  ExternalReference address_of_regexp_stack_memory_address =
+      ExternalReference::address_of_regexp_stack_memory_address(isolate);
+  ExternalReference address_of_regexp_stack_memory_size =
+      ExternalReference::address_of_regexp_stack_memory_size(isolate);
+  __ mov(r3, Operand(address_of_regexp_stack_memory_size));
+  __ LoadP(r3, MemOperand(r3, 0));
+  __ cmpi(r3, Operand::Zero());
+  __ beq(&runtime);
+
+  // Check that the first argument is a JSRegExp object.
+  __ LoadP(r3, MemOperand(sp, kJSRegExpOffset));
+  STATIC_ASSERT(kSmiTag == 0);
+  __ JumpIfSmi(r3, &runtime);
+  __ CompareObjectType(r3, r4, r4, JS_REGEXP_TYPE);
+  __ bne(&runtime);
+
+  // Check that the RegExp has been compiled (data contains a fixed array).
+  __ LoadP(regexp_data, FieldMemOperand(r3, JSRegExp::kDataOffset));
+  if (FLAG_debug_code) {
+    STATIC_ASSERT(kSmiTagMask == 1);
+    __ andi(r0, regexp_data, Operand(kSmiTagMask));
+    __ Check(ne, "Unexpected type for RegExp data, FixedArray expected", cr0);
+    __ CompareObjectType(regexp_data, r3, r3, FIXED_ARRAY_TYPE);
+    __ Check(eq, "Unexpected type for RegExp data, FixedArray expected");
+  }
+
+  // regexp_data: RegExp data (FixedArray)
+  // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
+  __ LoadP(r3, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
+  // ASSERT(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu);
+  __ CmpSmiLiteral(r3, Smi::FromInt(JSRegExp::IRREGEXP), r0);
+  __ bne(&runtime);
+
+  // regexp_data: RegExp data (FixedArray)
+  // Check that the number of captures fit in the static offsets vector buffer.
+  __ LoadP(r5,
+         FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
+  // Calculate number of capture registers (number_of_captures + 1) * 2.
+  __ SmiToShortArrayOffset(r5, r5);
+  __ addi(r5, r5, Operand(2));
+  // Check that the static offsets vector buffer is large enough.
+  // STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize < 0xffffu);
+  __ cmpli(r5, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize));
+  __ bgt(&runtime);
+
+  // r5: Number of capture registers
+  // regexp_data: RegExp data (FixedArray)
+  // Check that the second argument is a string.
+  __ LoadP(subject, MemOperand(sp, kSubjectOffset));
+  __ JumpIfSmi(subject, &runtime);
+  Condition is_string = masm->IsObjectStringType(subject, r3);
+  __ b(NegateCondition(is_string), &runtime, cr0);
+  // Get the length of the string to r6.
+  __ LoadP(r6, FieldMemOperand(subject, String::kLengthOffset));
+
+  // r5: Number of capture registers
+  // r6: Length of subject string as a smi
+  // subject: Subject string
+  // regexp_data: RegExp data (FixedArray)
+  // Check that the third argument is a positive smi less than the subject
+  // string length. A negative value will be greater (unsigned comparison).
+  __ LoadP(r3, MemOperand(sp, kPreviousIndexOffset));
+  __ JumpIfNotSmi(r3, &runtime);
+  __ cmpl(r6, r3);
+  __ ble(&runtime);
+
+  // r5: Number of capture registers
+  // subject: Subject string
+  // regexp_data: RegExp data (FixedArray)
+  // Check that the fourth object is a JSArray object.
+  __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset));
+  __ JumpIfSmi(r3, &runtime);
+  __ CompareObjectType(r3, r4, r4, JS_ARRAY_TYPE);
+  __ bne(&runtime);
+  // Check that the JSArray is in fast case.
+  __ LoadP(last_match_info_elements,
+         FieldMemOperand(r3, JSArray::kElementsOffset));
+  __ LoadP(r3, FieldMemOperand(last_match_info_elements,
+                               HeapObject::kMapOffset));
+  __ CompareRoot(r3, Heap::kFixedArrayMapRootIndex);
+  __ bne(&runtime);
+  // Check that the last match info has space for the capture registers and the
+  // additional information.
+  __ LoadP(r3,
+         FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
+  __ addi(r5, r5, Operand(RegExpImpl::kLastMatchOverhead));
+  __ SmiUntag(r0, r3);
+  __ cmp(r5, r0);
+  __ bgt(&runtime);
+
+  // Reset offset for possibly sliced string.
+  __ li(r11, Operand::Zero());
+  // subject: Subject string
+  // regexp_data: RegExp data (FixedArray)
+  // Check the representation and encoding of the subject string.
+  Label seq_string;
+  __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
+  __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  // First check for flat string.  None of the following string type tests will
+  // succeed if subject is not a string or a short external string.
+  STATIC_ASSERT((kIsNotStringMask |
+                  kStringRepresentationMask |
+                  kShortExternalStringMask) == 0x93);
+  __ andi(r4, r3, Operand(kIsNotStringMask |
+                          kStringRepresentationMask |
+                          kShortExternalStringMask));
+  STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
+  __ beq(&seq_string, cr0);
+
+  // subject: Subject string
+  // regexp_data: RegExp data (FixedArray)
+  // r4: whether subject is a string and if yes, its string representation
+  // Check for flat cons string or sliced string.
+  // A flat cons string is a cons string where the second part is the empty
+  // string. In that case the subject string is just the first part of the cons
+  // string. Also in this case the first part of the cons string is known to be
+  // a sequential string or an external string.
+  // In the case of a sliced string its offset has to be taken into account.
+  Label cons_string, external_string, check_encoding;
+  STATIC_ASSERT(kConsStringTag < kExternalStringTag);
+  STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
+  STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
+  STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
+  STATIC_ASSERT(kExternalStringTag < 0xffffu);
+  __ cmpi(r4, Operand(kExternalStringTag));
+  __ blt(&cons_string);
+  __ beq(&external_string);
+
+  // Catch non-string subject or short external string.
+  STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
+  STATIC_ASSERT((kNotStringTag | kShortExternalStringTag) < 0xffffu);
+  __ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask));
+  __ bne(&runtime, cr0);
+
+  // String is sliced.
+  __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset));
+  __ SmiUntag(r11);
+  __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
+  // r11: offset of sliced string, smi-tagged.
+  __ b(&check_encoding);
+  // String is a cons string, check whether it is flat.
+  __ bind(&cons_string);
+  __ LoadP(r3, FieldMemOperand(subject, ConsString::kSecondOffset));
+  __ CompareRoot(r3, Heap::kEmptyStringRootIndex);
+  __ bne(&runtime);
+  __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
+  // Is first part of cons or parent of slice a flat string?
+  __ bind(&check_encoding);
+  __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
+  __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  STATIC_ASSERT(kSeqStringTag == 0);
+  STATIC_ASSERT(kStringRepresentationMask == 3);
+  __ andi(r0, r3, Operand(kStringRepresentationMask));
+  __ bne(&external_string, cr0);
+
+  __ bind(&seq_string);
+  // subject: Subject string
+  // regexp_data: RegExp data (FixedArray)
+  // r3: Instance type of subject string
+  STATIC_ASSERT(4 == kAsciiStringTag);
+  STATIC_ASSERT(kTwoByteStringTag == 0);
+  // Find the code object based on the assumptions above.
+  STATIC_ASSERT(kStringEncodingMask == 4);
+  __ ExtractBitMask(r6, r3, kStringEncodingMask, SetRC);
+  __ beq(&encoding_type_UC16, cr0);
+  __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset));
+  __ b(&br_over);
+  __ bind(&encoding_type_UC16);
+  __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
+  __ bind(&br_over);
+
+  // Check that the irregexp code has been generated for the actual string
+  // encoding. If it has, the field contains a code object otherwise it contains
+  // a smi (code flushing support).
+  __ JumpIfSmi(code, &runtime);
+
+  // r6: encoding of subject string (1 if ASCII, 0 if two_byte);
+  // code: Address of generated regexp code
+  // subject: Subject string
+  // regexp_data: RegExp data (FixedArray)
+  // Load used arguments before starting to push arguments for call to native
+  // RegExp code to avoid handling changing stack height.
+  __ LoadP(r4, MemOperand(sp, kPreviousIndexOffset));
+  __ SmiUntag(r4);
+
+  // r4: previous index
+  // r6: encoding of subject string (1 if ASCII, 0 if two_byte);
+  // code: Address of generated regexp code
+  // subject: Subject string
+  // regexp_data: RegExp data (FixedArray)
+  // All checks done. Now push arguments for native regexp code.
+  __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r3, r5);
+
+  // Isolates: note we add an additional parameter here (isolate pointer).
+  const int kRegExpExecuteArguments = 10;
+  const int kParameterRegisters = 8;
+  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
+
+  // Stack pointer now points to cell where return address is to be written.
+  // Arguments are before that on the stack or in registers.
+
+  // Argument 10 (in stack parameter area): Pass current isolate address.
+  __ mov(r3, Operand(ExternalReference::isolate_address()));
+  __ StoreP(r3, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize));
+
+  // Argument 9 is a dummy that reserves the space used for
+  // the return address added by the ExitFrame in native calls.
+
+  // Argument 8 (r10): Indicate that this is a direct call from JavaScript.
+  __ li(r10, Operand(1));
+
+  // Argument 7 (r9): Start (high end) of backtracking stack memory area.
+  __ mov(r3, Operand(address_of_regexp_stack_memory_address));
+  __ LoadP(r3, MemOperand(r3, 0));
+  __ mov(r5, Operand(address_of_regexp_stack_memory_size));
+  __ LoadP(r5, MemOperand(r5, 0));
+  __ add(r9, r3, r5);
+
+  // Argument 6 (r8): Set the number of capture registers to zero to force
+  // global egexps to behave as non-global.  This does not affect non-global
+  // regexps.
+  __ li(r8, Operand::Zero());
+
+  // Argument 5 (r7): static offsets vector buffer.
+  __ mov(r7,
+         Operand(ExternalReference::address_of_static_offsets_vector(isolate)));
+
+  // For arguments 4 (r6) and 3 (r5) get string length, calculate start of
+  // string data and calculate the shift of the index (0 for ASCII and 1 for
+  // two byte).
+  __ addi(r22, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
+  __ xori(r6, r6, Operand(1));
+  // Load the length from the original subject string from the previous stack
+  // frame. Therefore we have to use fp, which points exactly to two pointer
+  // sizes below the previous sp. (Because creating a new stack frame pushes
+  // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
+  __ LoadP(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
+  // If slice offset is not 0, load the length from the original sliced string.
+  // Argument 4, r6: End of string data
+  // Argument 3, r5: Start of string data
+  // Prepare start and end index of the input.
+  __ ShiftLeft(r11, r11, r6);
+  __ add(r11, r22, r11);
+  __ ShiftLeft(r5, r4, r6);
+  __ add(r5, r11, r5);
+
+  __ LoadP(r22, FieldMemOperand(subject, String::kLengthOffset));
+  __ SmiUntag(r22);
+  __ ShiftLeft(r6, r22, r6);
+  __ add(r6, r11, r6);
+
+  // Argument 2 (r4): Previous index.
+  // Already there
+
+  // Argument 1 (r3): Subject string.
+  __ mr(r3, subject);
+
+  // Locate the code entry and call it.
+  __ addi(code, code, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+
+#if ABI_USES_FUNCTION_DESCRIPTORS && defined(USE_SIMULATOR)
+  // Even Simulated AIX/PPC64 Linux uses a function descriptor for the
+  // RegExp routine.  Extract the instruction address here since
+  // DirectCEntryStub::GenerateCall will not do it for calls out to
+  // what it thinks is C code compiled for the simulator/host
+  // platform.
+  __ LoadP(code, MemOperand(code, 0));  // Instruction address
+#endif
+
+  DirectCEntryStub stub;
+  stub.GenerateCall(masm, code);
+
+  __ LeaveExitFrame(false, no_reg);
+
+  // r3: result
+  // subject: subject string (callee saved)
+  // regexp_data: RegExp data (callee saved)
+  // last_match_info_elements: Last match info elements (callee saved)
+
+  // Check the result.
+  Label success;
+
+  __ cmpi(r3, Operand(1));
+  // We expect exactly one result since we force the called regexp to behave
+  // as non-global.
+  __ beq(&success);
+  Label failure;
+  __ cmpi(r3, Operand(NativeRegExpMacroAssembler::FAILURE));
+  __ beq(&failure);
+  __ cmpi(r3, Operand(NativeRegExpMacroAssembler::EXCEPTION));
+  // If not exception it can only be retry. Handle that in the runtime system.
+  __ bne(&runtime);
+  // Result must now be exception. If there is no pending exception already a
+  // stack overflow (on the backtrack stack) was detected in RegExp code but
+  // haven't created the exception yet. Handle that in the runtime system.
+  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
+  __ mov(r4, Operand(isolate->factory()->the_hole_value()));
+  __ mov(r5, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
+                                       isolate)));
+  __ LoadP(r3, MemOperand(r5, 0));
+  __ cmp(r3, r4);
+  __ beq(&runtime);
+
+  __ StoreP(r4, MemOperand(r5, 0));  // Clear pending exception.
+
+  // Check if the exception is a termination. If so, throw as uncatchable.
+  __ CompareRoot(r3, Heap::kTerminationExceptionRootIndex);
+
+  Label termination_exception;
+  __ beq(&termination_exception);
+
+  __ Throw(r3);
+
+  __ bind(&termination_exception);
+  __ ThrowUncatchable(r3);
+
+  __ bind(&failure);
+  // For failure and exception return null.
+  __ mov(r3, Operand(masm->isolate()->factory()->null_value()));
+  __ addi(sp, sp, Operand(4 * kPointerSize));
+  __ Ret();
+
+  // Process the result from the native regexp code.
+  __ bind(&success);
+  __ LoadP(r4,
+         FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
+  // Calculate number of capture registers (number_of_captures + 1) * 2.
+  __ SmiToShortArrayOffset(r4, r4);
+  __ addi(r4, r4, Operand(2));
+
+  // r4: number of capture registers
+  // r26: subject string
+  // Store the capture count.
+  __ SmiTag(r5, r4);
+  __ StoreP(r5, FieldMemOperand(last_match_info_elements,
+                                RegExpImpl::kLastCaptureCountOffset), r0);
+  // Store last subject and last input.
+  __ StoreP(subject,
+            FieldMemOperand(last_match_info_elements,
+                            RegExpImpl::kLastSubjectOffset), r0);
+  __ mr(r5, subject);
+  __ RecordWriteField(last_match_info_elements,
+                      RegExpImpl::kLastSubjectOffset,
+                      r5,
+                      r10,
+                      kLRHasNotBeenSaved,
+                      kDontSaveFPRegs);
+  __ StoreP(subject,
+            FieldMemOperand(last_match_info_elements,
+                            RegExpImpl::kLastInputOffset), r0);
+  __ RecordWriteField(last_match_info_elements,
+                      RegExpImpl::kLastInputOffset,
+                      subject,
+                      r10,
+                      kLRHasNotBeenSaved,
+                      kDontSaveFPRegs);
+
+  // Get the static offsets vector filled by the native regexp code.
+  ExternalReference address_of_static_offsets_vector =
+      ExternalReference::address_of_static_offsets_vector(isolate);
+  __ mov(r5, Operand(address_of_static_offsets_vector));
+
+  // r4: number of capture registers
+  // r5: offsets vector
+  Label next_capture;
+  // Capture register counter starts from number of capture registers and
+  // counts down until wraping after zero.
+  __ addi(r3,
+          last_match_info_elements,
+          Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag -
+                  kPointerSize));
+  __ addi(r5, r5, Operand(-kIntSize));  // bias down for lwzu
+  __ mtctr(r4);
+  __ bind(&next_capture);
+  // Read the value from the static offsets vector buffer.
+  __ lwzu(r6, MemOperand(r5, kIntSize));
+  // Store the smi value in the last match info.
+  __ SmiTag(r6);
+  __ StorePU(r6, MemOperand(r3, kPointerSize));
+  __ bdnz(&next_capture);
+
+  // Return last match info.
+  __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset));
+  __ addi(sp, sp, Operand(4 * kPointerSize));
+  __ Ret();
+
+  // External string.  Short external strings have already been ruled out.
+  // r3: scratch
+  __ bind(&external_string);
+  __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
+  __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  if (FLAG_debug_code) {
+    // Assert that we do not have a cons or slice (indirect strings) here.
+    // Sequential strings have already been ruled out.
+    STATIC_ASSERT(kIsIndirectStringMask == 1);
+    __ andi(r0, r3, Operand(kIsIndirectStringMask));
+    __ Assert(eq, "external string expected, but not found", cr0);
+  }
+  __ LoadP(subject,
+         FieldMemOperand(subject, ExternalString::kResourceDataOffset));
+  // Move the pointer so that offset-wise, it looks like a sequential string.
+  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
+  __ subi(subject,
+         subject,
+         Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+  __ b(&seq_string);
+
+  // Do the runtime call to execute the regexp.
+  __ bind(&runtime);
+  __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
+#endif  // V8_INTERPRETED_REGEXP
+}
+
+
+void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
+  const int kMaxInlineLength = 100;
+  Label slowcase;
+  Label done;
+  Factory* factory = masm->isolate()->factory();
+
+  __ LoadP(r4, MemOperand(sp, kPointerSize * 2));
+  __ JumpIfNotSmi(r4, &slowcase);
+  __ CmplSmiLiteral(r4, Smi::FromInt(kMaxInlineLength), r0);
+  __ bgt(&slowcase);
+  // Allocate RegExpResult followed by FixedArray with size in ebx.
+  // JSArray:   [Map][empty properties][Elements][Length-smi][index][input]
+  // Elements:  [Map][Length][..elements..]
+  // Size of JSArray with two in-object properties and the header of a
+  // FixedArray.
+  int objects_size =
+      (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize;
+  __ SmiUntag(r8, r4);
+  __ addi(r5, r8, Operand(objects_size));
+  // Future optimization: defer tagging the result pointer for more
+  // efficient 64-bit memory accesses (due to alignment requirements
+  // on the memoperand offset).
+  __ AllocateInNewSpace(
+      r5,  // In: Size, in words.
+      r3,  // Out: Start of allocation (tagged).
+      r6,  // Scratch register.
+      r7,  // Scratch register.
+      &slowcase,
+      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
+  // r3: Start of allocated area, object-tagged.
+  // r4: Number of elements in array, as smi.
+  // r8: Number of elements, untagged.
+
+  // Set JSArray map to global.regexp_result_map().
+  // Set empty properties FixedArray.
+  // Set elements to point to FixedArray allocated right after the JSArray.
+  // Interleave operations for better latency.
+  __ LoadP(r5, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ addi(r6, r3, Operand(JSRegExpResult::kSize));
+  __ mov(r7, Operand(factory->empty_fixed_array()));
+  __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kNativeContextOffset));
+  __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
+  __ LoadP(r5, ContextOperand(r5, Context::REGEXP_RESULT_MAP_INDEX));
+  __ StoreP(r7, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0);
+  __ StoreP(r5, FieldMemOperand(r3, HeapObject::kMapOffset), r0);
+
+  // Set input, index and length fields from arguments.
+  __ LoadP(r4, MemOperand(sp, kPointerSize * 0));
+  __ LoadP(r5, MemOperand(sp, kPointerSize * 1));
+  __ LoadP(r9, MemOperand(sp, kPointerSize * 2));
+  __ StoreP(r4, FieldMemOperand(r3, JSRegExpResult::kInputOffset), r0);
+  __ StoreP(r5, FieldMemOperand(r3, JSRegExpResult::kIndexOffset), r0);
+  __ StoreP(r9, FieldMemOperand(r3, JSArray::kLengthOffset), r0);
+
+  // Fill out the elements FixedArray.
+  // r3: JSArray, tagged.
+  // r6: FixedArray, tagged.
+  // r8: Number of elements in array, untagged.
+
+  // Set map.
+  __ mov(r5, Operand(factory->fixed_array_map()));
+  __ StoreP(r5, FieldMemOperand(r6, HeapObject::kMapOffset), r0);
+  // Set FixedArray length.
+  __ SmiTag(r9, r8);
+  __ StoreP(r9, FieldMemOperand(r6, FixedArray::kLengthOffset), r0);
+  // Fill contents of fixed-array with undefined.
+  __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+  __ addi(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  // Fill fixed array elements with undefined.
+  // r3: JSArray, tagged.
+  // r5: undefined.
+  // r6: Start of elements in FixedArray.
+  // r8: Number of elements to fill.
+  Label loop;
+  __ cmpi(r8, Operand::Zero());
+  __ bind(&loop);
+  __ ble(&done);  // Jump if r8 is negative or zero.
+  __ subi(r8, r8, Operand(1));
+  __ ShiftLeftImm(ip, r8, Operand(kPointerSizeLog2));
+  __ StorePX(r5, MemOperand(ip, r6));
+  __ cmpi(r8, Operand::Zero());
+  __ b(&loop);
+
+  __ bind(&done);
+  __ addi(sp, sp, Operand(3 * kPointerSize));
+  __ Ret();
+
+  __ bind(&slowcase);
+  __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
+}
+
+
+static void GenerateRecordCallTarget(MacroAssembler* masm) {
+  // Cache the called function in a global property cell.  Cache states
+  // are uninitialized, monomorphic (indicated by a JSFunction), and
+  // megamorphic.
+  // r4 : the function to call
+  // r5 : cache cell for call target
+  Label initialize, done;
+  const Register scratch = r6;
+
+  ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
+            masm->isolate()->heap()->undefined_value());
+  ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
+            masm->isolate()->heap()->the_hole_value());
+
+  // Load the cache state into scratch.
+  __ LoadP(scratch, FieldMemOperand(r5, JSGlobalPropertyCell::kValueOffset));
+
+  // A monomorphic cache hit or an already megamorphic state: invoke the
+  // function without changing the state.
+  __ cmp(scratch, r4);
+  __ beq(&done);
+  __ CompareRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ beq(&done);
+
+  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
+  // megamorphic.
+  __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
+  __ beq(&initialize);
+  // MegamorphicSentinel is an immortal immovable object (undefined) so no
+  // write-barrier is needed.
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ StoreP(ip, FieldMemOperand(r5, JSGlobalPropertyCell::kValueOffset), r0);
+  __ b(&done);
+
+  // An uninitialized cache is patched with the function.
+  __ bind(&initialize);
+  __ StoreP(r4, FieldMemOperand(r5, JSGlobalPropertyCell::kValueOffset), r0);
+  // No need for a write barrier here - cells are rescanned.
+
+  __ bind(&done);
+}
+
+
+void CallFunctionStub::Generate(MacroAssembler* masm) {
+  // r4 : the function to call
+  // r5 : cache cell for call target
+  Label slow, non_function;
+
+  // The receiver might implicitly be the global object. This is
+  // indicated by passing the hole as the receiver to the call
+  // function stub.
+  if (ReceiverMightBeImplicit()) {
+    Label call;
+    // Get the receiver from the stack.
+    // function, receiver [, arguments]
+    __ LoadP(r7, MemOperand(sp, argc_ * kPointerSize), r0);
+    // Call as function is indicated with the hole.
+    __ CompareRoot(r7, Heap::kTheHoleValueRootIndex);
+    __ bne(&call);
+    // Patch the receiver on the stack with the global receiver object.
+    __ LoadP(r6,
+             MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+    __ LoadP(r6, FieldMemOperand(r6, GlobalObject::kGlobalReceiverOffset));
+    __ StoreP(r6, MemOperand(sp, argc_ * kPointerSize), r0);
+    __ bind(&call);
+  }
+
+  // Check that the function is really a JavaScript function.
+  // r4: pushed function (to be verified)
+  __ JumpIfSmi(r4, &non_function);
+  // Get the map of the function object.
+  __ CompareObjectType(r4, r6, r6, JS_FUNCTION_TYPE);
+  __ bne(&slow);
+
+  if (RecordCallTarget()) {
+    GenerateRecordCallTarget(masm);
+  }
+
+  // Fast-case: Invoke the function now.
+  // r4: pushed function
+  ParameterCount actual(argc_);
+
+  if (ReceiverMightBeImplicit()) {
+    Label call_as_function;
+    __ CompareRoot(r7, Heap::kTheHoleValueRootIndex);
+    __ beq(&call_as_function);
+    __ InvokeFunction(r4,
+                      actual,
+                      JUMP_FUNCTION,
+                      NullCallWrapper(),
+                      CALL_AS_METHOD);
+    __ bind(&call_as_function);
+  }
+  __ InvokeFunction(r4,
+                    actual,
+                    JUMP_FUNCTION,
+                    NullCallWrapper(),
+                    CALL_AS_FUNCTION);
+
+  // Slow-case: Non-function called.
+  __ bind(&slow);
+  if (RecordCallTarget()) {
+    // If there is a call target cache, mark it megamorphic in the
+    // non-function case.  MegamorphicSentinel is an immortal immovable
+    // object (undefined) so no write barrier is needed.
+    ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
+              masm->isolate()->heap()->undefined_value());
+    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+    __ StoreP(ip, FieldMemOperand(r5, JSGlobalPropertyCell::kValueOffset), r0);
+  }
+  // Check for function proxy.
+  STATIC_ASSERT(JS_FUNCTION_PROXY_TYPE < 0xffffu);
+  __ cmpi(r6, Operand(JS_FUNCTION_PROXY_TYPE));
+  __ bne(&non_function);
+  __ push(r4);  // put proxy as additional argument
+  __ li(r3, Operand(argc_ + 1));
+  __ li(r5, Operand::Zero());
+  __ GetBuiltinEntry(r6, Builtins::CALL_FUNCTION_PROXY);
+  __ SetCallKind(r8, CALL_AS_METHOD);
+  {
+    Handle<Code> adaptor =
+      masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
+    __ Jump(adaptor, RelocInfo::CODE_TARGET);
+  }
+
+  // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
+  // of the original receiver from the call site).
+  __ bind(&non_function);
+  __ StoreP(r4, MemOperand(sp, argc_ * kPointerSize), r0);
+  __ li(r3, Operand(argc_));  // Set up the number of arguments.
+  __ li(r5, Operand::Zero());
+  __ GetBuiltinEntry(r6, Builtins::CALL_NON_FUNCTION);
+  __ SetCallKind(r8, CALL_AS_METHOD);
+  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+          RelocInfo::CODE_TARGET);
+}
+
+
+void CallConstructStub::Generate(MacroAssembler* masm) {
+  // r3 : number of arguments
+  // r4 : the function to call
+  // r5 : cache cell for call target
+  Label slow, non_function_call;
+
+  // Check that the function is not a smi.
+  __ JumpIfSmi(r4, &non_function_call);
+  // Check that the function is a JSFunction.
+  __ CompareObjectType(r4, r6, r6, JS_FUNCTION_TYPE);
+  __ bne(&slow);
+
+  if (RecordCallTarget()) {
+    GenerateRecordCallTarget(masm);
+  }
+
+  // Jump to the function-specific construct stub.
+  __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r5, FieldMemOperand(r5, SharedFunctionInfo::kConstructStubOffset));
+  __ addi(r0, r5, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ Jump(r0);
+
+  // r3: number of arguments
+  // r4: called object
+  // r6: object type
+  Label do_call;
+  __ bind(&slow);
+  STATIC_ASSERT(JS_FUNCTION_PROXY_TYPE < 0xffffu);
+  __ cmpi(r6, Operand(JS_FUNCTION_PROXY_TYPE));
+  __ bne(&non_function_call);
+  __ GetBuiltinEntry(r6, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
+  __ b(&do_call);
+
+  __ bind(&non_function_call);
+  __ GetBuiltinEntry(r6, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
+  __ bind(&do_call);
+  // Set expected number of arguments to zero (not changing r3).
+  __ li(r5, Operand::Zero());
+  __ SetCallKind(r8, CALL_AS_METHOD);
+  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
+          RelocInfo::CODE_TARGET);
+}
+
+
+// Unfortunately you have to run without snapshots to see most of these
+// names in the profile since most compare stubs end up in the snapshot.
+void CompareStub::PrintName(StringStream* stream) {
+  ASSERT((lhs_.is(r3) && rhs_.is(r4)) ||
+         (lhs_.is(r4) && rhs_.is(r3)));
+  const char* cc_name;
+  switch (cc_) {
+    case lt: cc_name = "LT"; break;
+    case gt: cc_name = "GT"; break;
+    case le: cc_name = "LE"; break;
+    case ge: cc_name = "GE"; break;
+    case eq: cc_name = "EQ"; break;
+    case ne: cc_name = "NE"; break;
+    default: cc_name = "UnknownCondition"; break;
+  }
+  bool is_equality = cc_ == eq || cc_ == ne;
+  stream->Add("CompareStub_%s", cc_name);
+  stream->Add(lhs_.is(r3) ? "_r3" : "_r4");
+  stream->Add(rhs_.is(r3) ? "_r3" : "_r4");
+  if (strict_ && is_equality) stream->Add("_STRICT");
+  if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN");
+  if (!include_number_compare_) stream->Add("_NO_NUMBER");
+  if (!include_smi_compare_) stream->Add("_NO_SMI");
+}
+
+
+int CompareStub::MinorKey() {
+  // Encode the three parameters in a unique 16 bit value. To avoid duplicate
+  // stubs the never NaN NaN condition is only taken into account if the
+  // condition is equals.
+  ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
+  ASSERT((lhs_.is(r3) && rhs_.is(r4)) ||
+         (lhs_.is(r4) && rhs_.is(r3)));
+  return ConditionField::encode(static_cast<unsigned>(cc_))
+         | RegisterField::encode(lhs_.is(r3))
+         | StrictField::encode(strict_)
+         | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
+         | IncludeNumberCompareField::encode(include_number_compare_)
+         | IncludeSmiCompareField::encode(include_smi_compare_);
+}
+
+
+// StringCharCodeAtGenerator
+void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
+  Label flat_string;
+  Label ascii_string;
+  Label got_char_code;
+  Label sliced_string;
+
+  // If the receiver is a smi trigger the non-string case.
+  __ JumpIfSmi(object_, receiver_not_string_);
+
+  // Fetch the instance type of the receiver into result register.
+  __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
+  __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
+  // If the receiver is not a string trigger the non-string case.
+  __ andi(r0, result_, Operand(kIsNotStringMask));
+  __ bne(receiver_not_string_, cr0);
+
+  // If the index is non-smi trigger the non-smi case.
+  __ JumpIfNotSmi(index_, &index_not_smi_);
+  __ bind(&got_smi_index_);
+
+  // Check for index out of range.
+  __ LoadP(ip, FieldMemOperand(object_, String::kLengthOffset));
+  __ cmpl(ip, index_);
+  __ ble(index_out_of_range_);
+
+  __ SmiUntag(index_);
+
+  StringCharLoadGenerator::Generate(masm,
+                                    object_,
+                                    index_,
+                                    result_,
+                                    &call_runtime_);
+
+  __ SmiTag(result_, result_);
+  __ bind(&exit_);
+}
+
+
+void StringCharCodeAtGenerator::GenerateSlow(
+    MacroAssembler* masm,
+    const RuntimeCallHelper& call_helper) {
+  __ Abort("Unexpected fallthrough to CharCodeAt slow case");
+
+  // Index is not a smi.
+  __ bind(&index_not_smi_);
+  // If index is a heap number, try converting it to an integer.
+  __ CheckMap(index_,
+              result_,
+              Heap::kHeapNumberMapRootIndex,
+              index_not_number_,
+              DONT_DO_SMI_CHECK);
+  call_helper.BeforeCall(masm);
+  __ push(object_);
+  __ push(index_);  // Consumed by runtime conversion function.
+  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
+    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
+  } else {
+    ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
+    // NumberToSmi discards numbers that are not exact integers.
+    __ CallRuntime(Runtime::kNumberToSmi, 1);
+  }
+  // Save the conversion result before the pop instructions below
+  // have a chance to overwrite it.
+  __ Move(index_, r3);
+  __ pop(object_);
+  // Reload the instance type.
+  __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
+  __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
+  call_helper.AfterCall(masm);
+  // If index is still not a smi, it must be out of range.
+  __ JumpIfNotSmi(index_, index_out_of_range_);
+  // Otherwise, return to the fast path.
+  __ b(&got_smi_index_);
+
+  // Call runtime. We get here when the receiver is a string and the
+  // index is a number, but the code of getting the actual character
+  // is too complex (e.g., when the string needs to be flattened).
+  __ bind(&call_runtime_);
+  call_helper.BeforeCall(masm);
+  __ SmiTag(index_);
+  __ Push(object_, index_);
+  __ CallRuntime(Runtime::kStringCharCodeAt, 2);
+  __ Move(result_, r3);
+  call_helper.AfterCall(masm);
+  __ b(&exit_);
+
+  __ Abort("Unexpected fallthrough from CharCodeAt slow case");
+}
+
+
+// -------------------------------------------------------------------------
+// StringCharFromCodeGenerator
+
+  void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
+  // Fast case of Heap::LookupSingleCharacterStringFromCode.
+  ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
+  __ LoadSmiLiteral(r0, Smi::FromInt(~String::kMaxAsciiCharCode));
+  __ ori(r0, r0, Operand(kSmiTagMask));
+  __ and_(r0, code_, r0);
+  __ cmpi(r0, Operand::Zero());
+  __ bne(&slow_case_);
+
+  __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
+  // At this point code register contains smi tagged ASCII char code.
+  __ mr(r0, code_);
+  __ SmiToPtrArrayOffset(code_, code_);
+  __ add(result_, result_, code_);
+  __ mr(code_, r0);
+  __ LoadP(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
+  __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
+  __ beq(&slow_case_);
+  __ bind(&exit_);
+}
+
+
+void StringCharFromCodeGenerator::GenerateSlow(
+    MacroAssembler* masm,
+    const RuntimeCallHelper& call_helper) {
+  __ Abort("Unexpected fallthrough to CharFromCode slow case");
+
+  __ bind(&slow_case_);
+  call_helper.BeforeCall(masm);
+  __ push(code_);
+  __ CallRuntime(Runtime::kCharFromCode, 1);
+  __ Move(result_, r3);
+  call_helper.AfterCall(masm);
+  __ b(&exit_);
+
+  __ Abort("Unexpected fallthrough from CharFromCode slow case");
+}
+
+
+// -------------------------------------------------------------------------
+// StringCharAtGenerator
+
+void StringCharAtGenerator::GenerateFast(MacroAssembler* masm) {
+  char_code_at_generator_.GenerateFast(masm);
+  char_from_code_generator_.GenerateFast(masm);
+}
+
+
+void StringCharAtGenerator::GenerateSlow(
+    MacroAssembler* masm,
+    const RuntimeCallHelper& call_helper) {
+  char_code_at_generator_.GenerateSlow(masm, call_helper);
+  char_from_code_generator_.GenerateSlow(masm, call_helper);
+}
+
+
+void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
+                                          Register dest,
+                                          Register src,
+                                          Register count,
+                                          Register scratch,
+                                          bool ascii) {
+  Label loop;
+  __ bind(&loop);
+  // This loop just copies one character at a time, as it is only used for very
+  // short strings.
+  if (ascii) {
+    __ lbz(scratch, MemOperand(src));
+    __ stb(scratch, MemOperand(dest));
+    __ addi(src, src, Operand(1));
+    __ addi(dest, dest, Operand(1));
+  } else {
+    __ lhz(scratch, MemOperand(src));
+    __ sth(scratch, MemOperand(dest));
+    __ addi(src, src, Operand(2));
+    __ addi(dest, dest, Operand(2));
+  }
+  __ subi(count, count, Operand(1));
+  __ cmpi(count, Operand::Zero());
+  __ bgt(&loop);
+}
+
+
+enum CopyCharactersFlags {
+  COPY_ASCII = 1,
+  DEST_ALWAYS_ALIGNED = 2
+};
+
+
+// roohack - optimization opportunity here, stringcopy is important
+// and the current version below is very dumb
+void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
+                                              Register dest,
+                                              Register src,
+                                              Register count,
+                                              Register scratch1,
+                                              Register scratch2,
+                                              Register scratch3,
+                                              Register scratch4,
+                                              Register scratch5,
+                                              int flags) {
+  bool ascii = (flags & COPY_ASCII) != 0;
+  bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
+
+  if (dest_always_aligned && FLAG_debug_code) {
+    // Check that destination is actually word aligned if the flag says
+    // that it is.
+    __ andi(r0, dest, Operand(kPointerAlignmentMask));
+    __ Check(eq, "Destination of copy not aligned.", cr0);
+  }
+
+  // Nothing to do for zero characters.
+  Label done;
+  if (!ascii) {  // for non-ascii, double the length
+    __ add(count, count, count);
+  }
+  __ cmpi(count, Operand(0, RelocInfo::NONE));
+  __ beq(&done);
+
+  // Assume that you cannot read (or write) unaligned.
+  Label byte_loop;
+  __ add(count, dest, count);
+  Register limit = count;  // Read until src equals this.
+  // Copy bytes from src to dst until dst hits limit.
+  __ bind(&byte_loop);
+  __ cmp(dest, limit);
+  __ bge(&done);
+  __ lbz(scratch1, MemOperand(src));
+  __ addi(src, src, Operand(1));
+  __ stb(scratch1, MemOperand(dest));
+  __ addi(dest, dest, Operand(1));
+  __ b(&byte_loop);
+
+  __ bind(&done);
+}
+
+
+void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
+                                                        Register c1,
+                                                        Register c2,
+                                                        Register scratch1,
+                                                        Register scratch2,
+                                                        Register scratch3,
+                                                        Register scratch4,
+                                                        Register scratch5,
+                                                        Label* not_found) {
+  // Register scratch3 is the general scratch register in this function.
+  Register scratch = scratch3;
+
+  // Make sure that both characters are not digits as such strings has a
+  // different hash algorithm. Don't try to look for these in the symbol table.
+  Label not_array_index;
+  __ subi(scratch, c1, Operand(static_cast<intptr_t>('0')));
+  __ cmpli(scratch, Operand(static_cast<intptr_t>('9' - '0')));
+  __ bgt(&not_array_index);
+  __ subi(scratch, c2, Operand(static_cast<intptr_t>('0')));
+  __ cmpli(scratch, Operand(static_cast<intptr_t>('9' - '0')));
+  __ bgt(&not_array_index);
+
+  // If check failed combine both characters into single halfword.
+  // This is required by the contract of the method: code at the
+  // not_found branch expects this combination in c1 register
+#if __BYTE_ORDER == __BIG_ENDIAN
+  __ ShiftLeftImm(c1, c1, Operand(kBitsPerByte));
+  __ orx(c1, c1, c2);
+#else
+  __ ShiftLeftImm(r0, c2, Operand(kBitsPerByte));
+  __ orx(c1, c1, r0);
+#endif
+  __ b(not_found);
+
+  __ bind(&not_array_index);
+  // Calculate the two character string hash.
+  Register hash = scratch1;
+  StringHelper::GenerateHashInit(masm, hash, c1, scratch);
+  StringHelper::GenerateHashAddCharacter(masm, hash, c2, scratch);
+  StringHelper::GenerateHashGetHash(masm, hash, scratch);
+
+  // Collect the two characters in a register.
+  Register chars = c1;
+#if __BYTE_ORDER == __BIG_ENDIAN
+  __ ShiftLeftImm(c1, c1, Operand(kBitsPerByte));
+  __ orx(chars, c1, c2);
+#else
+  __ ShiftLeftImm(r0, c2, Operand(kBitsPerByte));
+  __ orx(chars, c1, r0);
+#endif
+
+  // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
+  // hash:  hash of two character string.
+
+  // Load symbol table
+  // Load address of first element of the symbol table.
+  Register symbol_table = c2;
+  __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
+
+  Register undefined = scratch4;
+  __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
+
+  // Calculate capacity mask from the symbol table capacity.
+  Register mask = scratch2;
+  __ LoadP(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset));
+  __ SmiUntag(mask);
+  __ subi(mask, mask, Operand(1));
+
+  // Calculate untagged address of the first element of the symbol table.
+  Register first_symbol_table_element = symbol_table;
+  __ addi(first_symbol_table_element, symbol_table,
+          Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag));
+
+  // Registers
+  // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
+  // hash:  hash of two character string
+  // mask:  capacity mask
+  // first_symbol_table_element: address of the first element of
+  //                             the symbol table
+  // undefined: the undefined object
+  // scratch: -
+
+  // Perform a number of probes in the symbol table.
+  const int kProbes = 4;
+  Label found_in_symbol_table;
+  Label next_probe[kProbes];
+  Register candidate = scratch5;  // Scratch register contains candidate.
+  for (int i = 0; i < kProbes; i++) {
+    // Calculate entry in symbol table.
+    if (i > 0) {
+      __ addi(candidate, hash, Operand(SymbolTable::GetProbeOffset(i)));
+    } else {
+      __ mr(candidate, hash);
+    }
+
+    __ and_(candidate, candidate, mask);
+
+    // Load the entry from the symble table.
+    STATIC_ASSERT(SymbolTable::kEntrySize == 1);
+    __ ShiftLeftImm(scratch, candidate, Operand(kPointerSizeLog2));
+    __ LoadPX(candidate, MemOperand(scratch, first_symbol_table_element));
+
+    // If entry is undefined no string with this hash can be found.
+    Label is_string;
+    __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE);
+    __ bne(&is_string);
+
+    __ cmp(undefined, candidate);
+    __ beq(not_found);
+    // Must be the hole (deleted entry).
+    if (FLAG_debug_code) {
+      __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+      __ cmp(ip, candidate);
+      __ Assert(eq, "oddball in symbol table is not undefined or the hole");
+    }
+    __ b(&next_probe[i]);
+
+    __ bind(&is_string);
+
+    // Check that the candidate is a non-external ASCII string.  The instance
+    // type is still in the scratch register from the CompareObjectType
+    // operation.
+    __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]);
+
+    // If length is not 2 the string is not a candidate.
+    __ LoadP(scratch, FieldMemOperand(candidate, String::kLengthOffset));
+    __ CmpSmiLiteral(scratch, Smi::FromInt(2), r0);
+    __ bne(&next_probe[i]);
+
+    // Check if the two characters match.
+    __ lhz(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize));
+    __ cmp(chars, scratch);
+    __ beq(&found_in_symbol_table);
+    __ bind(&next_probe[i]);
+  }
+
+  // No matching 2 character string found by probing.
+  __ b(not_found);
+
+  // Scratch register contains result when we fall through to here.
+  Register result = candidate;
+  __ bind(&found_in_symbol_table);
+  __ mr(r3, result);
+}
+
+
+void StringHelper::GenerateHashInit(MacroAssembler* masm,
+                                    Register hash,
+                                    Register character,
+                                    Register scratch) {
+  // hash = character + (character << 10);
+  __ LoadRoot(hash, Heap::kHashSeedRootIndex);
+  // Untag smi seed and add the character.
+  __ SmiUntag(scratch, hash);
+  __ add(hash, character, scratch);
+  // hash += hash << 10;
+  __ slwi(scratch, hash, Operand(10));
+  __ add(hash, hash, scratch);
+  // hash ^= hash >> 6;
+  __ srwi(scratch, hash, Operand(6));
+  __ xor_(hash, hash, scratch);
+}
+
+
+void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
+                                            Register hash,
+                                            Register character,
+                                            Register scratch) {
+  // hash += character;
+  __ add(hash, hash, character);
+  // hash += hash << 10;
+  __ slwi(scratch, hash, Operand(10));
+  __ add(hash, hash, scratch);
+  // hash ^= hash >> 6;
+  __ srwi(scratch, hash, Operand(6));
+  __ xor_(hash, hash, scratch);
+}
+
+
+void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
+                                       Register hash,
+                                       Register scratch) {
+  // hash += hash << 3;
+  __ slwi(scratch, hash, Operand(3));
+  __ add(hash, hash, scratch);
+  // hash ^= hash >> 11;
+  __ srwi(scratch, hash, Operand(11));
+  __ xor_(hash, hash, scratch);
+  // hash += hash << 15;
+  __ slwi(scratch, hash, Operand(15));
+  __ add(hash, hash, scratch);
+
+  __ mov(scratch, Operand(String::kHashBitMask));
+  __ and_(hash, hash, scratch, SetRC);
+
+  // if (hash == 0) hash = 27;
+  Label done;
+  __ bne(&done, cr0);
+  __ li(hash, Operand(StringHasher::kZeroHash));
+  __ bind(&done);
+}
+
+
+void SubStringStub::Generate(MacroAssembler* masm) {
+  Label runtime;
+
+  // Stack frame on entry.
+  //  lr: return address
+  //  sp[0]: to
+  //  sp[4]: from
+  //  sp[8]: string
+
+  // This stub is called from the native-call %_SubString(...), so
+  // nothing can be assumed about the arguments. It is tested that:
+  //  "string" is a sequential string,
+  //  both "from" and "to" are smis, and
+  //  0 <= from <= to <= string.length.
+  // If any of these assumptions fail, we call the runtime system.
+
+  const int kToOffset = 0 * kPointerSize;
+  const int kFromOffset = 1 * kPointerSize;
+  const int kStringOffset = 2 * kPointerSize;
+
+  __ LoadP(r5, MemOperand(sp, kToOffset));
+  __ LoadP(r6, MemOperand(sp, kFromOffset));
+
+  // If either to or from had the smi tag bit set, then fail to generic runtime
+  __ JumpIfNotSmi(r5, &runtime);
+  __ JumpIfNotSmi(r6, &runtime);
+  __ SmiUntag(r5);
+  __ SmiUntag(r6, SetRC);
+  // Both r5 and r6 are untagged integers.
+
+  // We want to bailout to runtime here if From is negative.
+  __ blt(&runtime, cr0);  // From < 0.
+
+  __ cmpl(r6, r5);
+  __ bgt(&runtime);  // Fail if from > to.
+  __ sub(r5, r5, r6);
+
+  // Make sure first argument is a string.
+  __ LoadP(r3, MemOperand(sp, kStringOffset));
+  __ JumpIfSmi(r3, &runtime);
+  Condition is_string = masm->IsObjectStringType(r3, r4);
+  __ b(NegateCondition(is_string), &runtime, cr0);
+
+  // Short-cut for the case of trivial substring.
+  Label return_r3;
+  // r3: original string
+  // r5: result string length
+  __ LoadP(r7, FieldMemOperand(r3, String::kLengthOffset));
+  __ SmiUntag(r0, r7);
+  __ cmpl(r5, r0);
+  // Return original string.
+  __ beq(&return_r3);
+  // Longer than original string's length or negative: unsafe arguments.
+  __ bgt(&runtime);
+  // Shorter than original string's length: an actual substring.
+
+  // Deal with different string types: update the index if necessary
+  // and put the underlying string into r8.
+  // r3: original string
+  // r4: instance type
+  // r5: length
+  // r6: from index (untagged)
+  Label underlying_unpacked, sliced_string, seq_or_external_string;
+  // If the string is not indirect, it can only be sequential or external.
+  STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
+  STATIC_ASSERT(kIsIndirectStringMask != 0);
+  __ andi(r0, r4, Operand(kIsIndirectStringMask));
+  __ beq(&seq_or_external_string, cr0);
+
+  __ andi(r0, r4, Operand(kSlicedNotConsMask));
+  __ bne(&sliced_string, cr0);
+  // Cons string.  Check whether it is flat, then fetch first part.
+  __ LoadP(r8, FieldMemOperand(r3, ConsString::kSecondOffset));
+  __ CompareRoot(r8, Heap::kEmptyStringRootIndex);
+  __ bne(&runtime);
+  __ LoadP(r8, FieldMemOperand(r3, ConsString::kFirstOffset));
+  // Update instance type.
+  __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset));
+  __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
+  __ b(&underlying_unpacked);
+
+  __ bind(&sliced_string);
+  // Sliced string.  Fetch parent and correct start index by offset.
+  __ LoadP(r8, FieldMemOperand(r3, SlicedString::kParentOffset));
+  __ LoadP(r7, FieldMemOperand(r3, SlicedString::kOffsetOffset));
+  __ SmiUntag(r4, r7);
+  __ add(r6, r6, r4);  // Add offset to index.
+  // Update instance type.
+  __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset));
+  __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
+  __ b(&underlying_unpacked);
+
+  __ bind(&seq_or_external_string);
+  // Sequential or external string.  Just move string to the expected register.
+  __ mr(r8, r3);
+
+  __ bind(&underlying_unpacked);
+
+  if (FLAG_string_slices) {
+    Label copy_routine;
+    // r8: underlying subject string
+    // r4: instance type of underlying subject string
+    // r5: length
+    // r6: adjusted start index (untagged)
+    __ cmpi(r5, Operand(SlicedString::kMinLength));
+    // Short slice.  Copy instead of slicing.
+    __ blt(&copy_routine);
+    // Allocate new sliced string.  At this point we do not reload the instance
+    // type including the string encoding because we simply rely on the info
+    // provided by the original string.  It does not matter if the original
+    // string's encoding is wrong because we always have to recheck encoding of
+    // the newly created string's parent anyways due to externalized strings.
+    Label two_byte_slice, set_slice_header;
+    STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
+    STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
+    __ andi(r0, r4, Operand(kStringEncodingMask));
+    __ beq(&two_byte_slice, cr0);
+    __ AllocateAsciiSlicedString(r3, r5, r9, r10, &runtime);
+    __ b(&set_slice_header);
+    __ bind(&two_byte_slice);
+    __ AllocateTwoByteSlicedString(r3, r5, r9, r10, &runtime);
+    __ bind(&set_slice_header);
+    __ SmiTag(r6);
+    __ StoreP(r8, FieldMemOperand(r3, SlicedString::kParentOffset), r0);
+    __ StoreP(r6, FieldMemOperand(r3, SlicedString::kOffsetOffset), r0);
+    __ b(&return_r3);
+
+    __ bind(&copy_routine);
+  }
+
+  // r8: underlying subject string
+  // r4: instance type of underlying subject string
+  // r5: length
+  // r6: adjusted start index (untagged)
+  Label two_byte_sequential, sequential_string, allocate_result;
+  STATIC_ASSERT(kExternalStringTag != 0);
+  STATIC_ASSERT(kSeqStringTag == 0);
+  __ andi(r0, r4, Operand(kExternalStringTag));
+  __ beq(&sequential_string, cr0);
+
+  // Handle external string.
+  // Rule out short external strings.
+  STATIC_CHECK(kShortExternalStringTag != 0);
+  __ andi(r0, r4, Operand(kShortExternalStringTag));
+  __ bne(&runtime, cr0);
+  __ LoadP(r8, FieldMemOperand(r8, ExternalString::kResourceDataOffset));
+  // r8 already points to the first character of underlying string.
+  __ b(&allocate_result);
+
+  __ bind(&sequential_string);
+  // Locate first character of underlying subject string.
+  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
+  __ addi(r8, r8, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+
+  __ bind(&allocate_result);
+  // Sequential acii string.  Allocate the result.
+  STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0);
+  __ andi(r0, r4, Operand(kStringEncodingMask));
+  __ beq(&two_byte_sequential, cr0);
+
+  // Allocate and copy the resulting ASCII string.
+  __ AllocateAsciiString(r3, r5, r7, r9, r10, &runtime);
+
+  // Locate first character of substring to copy.
+  __ add(r8, r8, r6);
+  // Locate first character of result.
+  __ addi(r4, r3, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+
+  // r3: result string
+  // r4: first character of result string
+  // r5: result string length
+  // r8: first character of substring to copy
+  STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
+  StringHelper::GenerateCopyCharactersLong(masm, r4, r8, r5, r6, r7, r9,
+       r10, r22, COPY_ASCII | DEST_ALWAYS_ALIGNED);
+  __ b(&return_r3);
+
+  // Allocate and copy the resulting two-byte string.
+  __ bind(&two_byte_sequential);
+  __ AllocateTwoByteString(r3, r5, r7, r9, r10, &runtime);
+
+  // Locate first character of substring to copy.
+  __ ShiftLeftImm(r4, r6, Operand(1));
+  __ add(r8, r8, r4);
+  // Locate first character of result.
+  __ addi(r4, r3, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+
+  // r3: result string.
+  // r4: first character of result.
+  // r5: result length.
+  // r8: first character of substring to copy.
+  STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
+  StringHelper::GenerateCopyCharactersLong(
+      masm, r4, r8, r5, r6, r7, r9, r10, r22, DEST_ALWAYS_ALIGNED);
+
+  __ bind(&return_r3);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->sub_string_native(), 1, r6, r7);
+  __ addi(sp, sp, Operand(3 * kPointerSize));
+  __ Ret();
+
+  // Just jump to runtime to create the sub string.
+  __ bind(&runtime);
+  __ TailCallRuntime(Runtime::kSubString, 3, 1);
+}
+
+
+void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+                                                      Register left,
+                                                      Register right,
+                                                      Register scratch1,
+                                                      Register scratch2) {
+  Register length = scratch1;
+
+  // Compare lengths.
+  Label strings_not_equal, check_zero_length;
+  __ LoadP(length, FieldMemOperand(left, String::kLengthOffset));
+  __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
+  __ cmp(length, scratch2);
+  __ beq(&check_zero_length);
+  __ bind(&strings_not_equal);
+  __ LoadSmiLiteral(r3, Smi::FromInt(NOT_EQUAL));
+  __ Ret();
+
+  // Check if the length is zero.
+  Label compare_chars;
+  __ bind(&check_zero_length);
+  STATIC_ASSERT(kSmiTag == 0);
+  __ cmpi(length, Operand::Zero());
+  __ bne(&compare_chars);
+  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
+  __ Ret();
+
+  // Compare characters.
+  __ bind(&compare_chars);
+  GenerateAsciiCharsCompareLoop(masm,
+                                left, right, length, scratch2,
+                                &strings_not_equal);
+
+  // Characters are equal.
+  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
+  __ Ret();
+}
+
+
+void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
+                                                        Register left,
+                                                        Register right,
+                                                        Register scratch1,
+                                                        Register scratch2,
+                                                        Register scratch3) {
+  Label skip, result_not_equal, compare_lengths;
+  // Find minimum length and length difference.
+  __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset));
+  __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
+  __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC);
+  Register length_delta = scratch3;
+  __ ble(&skip, cr0);
+  __ mr(scratch1, scratch2);
+  __ bind(&skip);
+  Register min_length = scratch1;
+  STATIC_ASSERT(kSmiTag == 0);
+  __ cmpi(min_length, Operand::Zero());
+  __ beq(&compare_lengths);
+
+  // Compare loop.
+  GenerateAsciiCharsCompareLoop(masm,
+                                left, right, min_length, scratch2,
+                                &result_not_equal);
+
+  // Compare lengths - strings up to min-length are equal.
+  __ bind(&compare_lengths);
+  ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
+  // Use length_delta as result if it's zero.
+  __ mr(r3, length_delta);
+  __ cmpi(r3, Operand::Zero());
+  __ bind(&result_not_equal);
+  // Conditionally update the result based either on length_delta or
+  // the last comparion performed in the loop above.
+  Label less_equal, equal;
+  __ ble(&less_equal);
+  __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
+  __ Ret();
+  __ bind(&less_equal);
+  __ beq(&equal);
+  __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
+  __ bind(&equal);
+  __ Ret();
+}
+
+
+void StringCompareStub::GenerateAsciiCharsCompareLoop(
+    MacroAssembler* masm,
+    Register left,
+    Register right,
+    Register length,
+    Register scratch1,
+    Label* chars_not_equal) {
+  // Change index to run from -length to -1 by adding length to string
+  // start. This means that loop ends when index reaches zero, which
+  // doesn't need an additional compare.
+  __ SmiUntag(length);
+  __ addi(scratch1, length,
+          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ add(left, left, scratch1);
+  __ add(right, right, scratch1);
+  __ subfic(length, length, Operand::Zero());
+  Register index = length;  // index = -length;
+
+  // Compare loop.
+  Label loop;
+  __ bind(&loop);
+  __ lbzx(scratch1, MemOperand(left, index));
+  __ lbzx(r0, MemOperand(right, index));
+  __ cmp(scratch1, r0);
+  __ bne(chars_not_equal);
+  __ addi(index, index, Operand(1));
+  __ cmpi(index, Operand::Zero());
+  __ bne(&loop);
+}
+
+
+void StringCompareStub::Generate(MacroAssembler* masm) {
+  Label runtime;
+
+  Counters* counters = masm->isolate()->counters();
+
+  // Stack frame on entry.
+  //  sp[0]: right string
+  //  sp[4]: left string
+  __ LoadP(r3, MemOperand(sp));  // Load right in r3, left in r4.
+  __ LoadP(r4, MemOperand(sp, kPointerSize));
+
+  Label not_same;
+  __ cmp(r3, r4);
+  __ bne(&not_same);
+  STATIC_ASSERT(EQUAL == 0);
+  STATIC_ASSERT(kSmiTag == 0);
+  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
+  __ IncrementCounter(counters->string_compare_native(), 1, r4, r5);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ Ret();
+
+  __ bind(&not_same);
+
+  // Check that both objects are sequential ASCII strings.
+  __ JumpIfNotBothSequentialAsciiStrings(r4, r3, r5, r6, &runtime);
+
+  // Compare flat ASCII strings natively. Remove arguments from stack first.
+  __ IncrementCounter(counters->string_compare_native(), 1, r5, r6);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  GenerateCompareFlatAsciiStrings(masm, r4, r3, r5, r6, r7);
+
+  // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
+  // tagged as a small integer.
+  __ bind(&runtime);
+  __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
+}
+
+
+void StringAddStub::Generate(MacroAssembler* masm) {
+  Label call_runtime, call_builtin;
+  Builtins::JavaScript builtin_id = Builtins::ADD;
+
+  Counters* counters = masm->isolate()->counters();
+
+  // Stack on entry:
+  // sp[0]: second argument (right).
+  // sp[4]: first argument (left).
+
+  // Load the two arguments.
+  __ LoadP(r3, MemOperand(sp, 1 * kPointerSize));  // First argument.
+  __ LoadP(r4, MemOperand(sp, 0 * kPointerSize));  // Second argument.
+
+  // Make sure that both arguments are strings if not known in advance.
+  if (flags_ == NO_STRING_ADD_FLAGS) {
+    __ JumpIfEitherSmi(r3, r4, &call_runtime);
+    // Load instance types.
+    __ LoadP(r7, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ LoadP(r8, FieldMemOperand(r4, HeapObject::kMapOffset));
+    __ lbz(r7, FieldMemOperand(r7, Map::kInstanceTypeOffset));
+    __ lbz(r8, FieldMemOperand(r8, Map::kInstanceTypeOffset));
+    STATIC_ASSERT(kStringTag == 0);
+    // If either is not a string, go to runtime.
+    __ andi(r0, r7, Operand(kIsNotStringMask));
+    __ bne(&call_runtime, cr0);
+    __ andi(r0, r8, Operand(kIsNotStringMask));
+    __ bne(&call_runtime, cr0);
+  } else {
+    // Here at least one of the arguments is definitely a string.
+    // We convert the one that is not known to be a string.
+    if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
+      ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
+      GenerateConvertArgument(
+          masm, 1 * kPointerSize, r3, r5, r6, r7, r8, &call_builtin);
+      builtin_id = Builtins::STRING_ADD_RIGHT;
+    } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) {
+      ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
+      GenerateConvertArgument(
+          masm, 0 * kPointerSize, r4, r5, r6, r7, r8, &call_builtin);
+      builtin_id = Builtins::STRING_ADD_LEFT;
+    }
+  }
+
+  // Both arguments are strings.
+  // r3: first string
+  // r4: second string
+  // r7: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // r8: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  {
+    Label first_not_empty, return_second, strings_not_empty;
+    // Check if either of the strings are empty. In that case return the other.
+    __ LoadP(r5, FieldMemOperand(r3, String::kLengthOffset));
+    __ LoadP(r6, FieldMemOperand(r4, String::kLengthOffset));
+    STATIC_ASSERT(kSmiTag == 0);
+    // Test if first string is empty.
+    __ CmpSmiLiteral(r5, Smi::FromInt(0), r0);
+    __ bne(&first_not_empty);
+    __ mr(r3, r4);  // If first is empty, return second.
+    __ b(&return_second);
+    STATIC_ASSERT(kSmiTag == 0);
+    __ bind(&first_not_empty);
+     // Else test if second string is empty.
+    __ CmpSmiLiteral(r6, Smi::FromInt(0), r0);
+    __ bne(&strings_not_empty);  // If either string was empty, return r3.
+
+    __ bind(&return_second);
+    __ IncrementCounter(counters->string_add_native(), 1, r5, r6);
+    __ addi(sp, sp, Operand(2 * kPointerSize));
+    __ Ret();
+
+    __ bind(&strings_not_empty);
+  }
+
+  __ SmiUntag(r5);
+  __ SmiUntag(r6);
+  // Both strings are non-empty.
+  // r3: first string
+  // r4: second string
+  // r5: length of first string
+  // r6: length of second string
+  // r7: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // r8: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // Look at the length of the result of adding the two strings.
+  Label string_add_flat_result, longer_than_two;
+  // Adding two lengths can't overflow.
+  STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
+  __ add(r9, r5, r6);
+  // Use the symbol table when adding two one character strings, as it
+  // helps later optimizations to return a symbol here.
+  __ cmpi(r9, Operand(2));
+  __ bne(&longer_than_two);
+
+  // Check that both strings are non-external ASCII strings.
+  if (flags_ != NO_STRING_ADD_FLAGS) {
+    __ LoadP(r7, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ LoadP(r8, FieldMemOperand(r4, HeapObject::kMapOffset));
+    __ lbz(r7, FieldMemOperand(r7, Map::kInstanceTypeOffset));
+    __ lbz(r8, FieldMemOperand(r8, Map::kInstanceTypeOffset));
+  }
+  __ JumpIfBothInstanceTypesAreNotSequentialAscii(r7, r8, r9, r10,
+                                                  &call_runtime);
+
+  // Get the two characters forming the sub string.
+  __ lbz(r5, FieldMemOperand(r3, SeqAsciiString::kHeaderSize));
+  __ lbz(r6, FieldMemOperand(r4, SeqAsciiString::kHeaderSize));
+
+  // Try to lookup two character string in symbol table. If it is not found
+  // just allocate a new one.
+  Label make_two_character_string;
+  StringHelper::GenerateTwoCharacterSymbolTableProbe(
+      masm, r5, r6, r9, r10, r7, r8, r22, &make_two_character_string);
+  __ IncrementCounter(counters->string_add_native(), 1, r5, r6);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ Ret();
+
+  __ bind(&make_two_character_string);
+  // Resulting string has length 2 and first chars of two strings
+  // are combined into single halfword in r5 register.
+  // So we can fill resulting string without two loops by a single
+  // halfword store instruction
+  __ li(r9, Operand(2));
+  __ AllocateAsciiString(r3, r9, r7, r8, r22, &call_runtime);
+  __ sth(r5, FieldMemOperand(r3, SeqAsciiString::kHeaderSize));
+  __ IncrementCounter(counters->string_add_native(), 1, r5, r6);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ Ret();
+
+  __ bind(&longer_than_two);
+  // Check if resulting string will be flat.
+  __ cmpi(r9, Operand(ConsString::kMinLength));
+  __ blt(&string_add_flat_result);
+  // Handle exceptionally long strings in the runtime system.
+  STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
+  ASSERT(IsPowerOf2(String::kMaxLength + 1));
+  // kMaxLength + 1 is representable as shifted literal, kMaxLength is not.
+  __ mov(r10, Operand(String::kMaxLength + 1));
+  __ cmpl(r9, r10);
+  __ bge(&call_runtime);
+
+  // If result is not supposed to be flat, allocate a cons string object.
+  // If both strings are ASCII the result is an ASCII cons string.
+  if (flags_ != NO_STRING_ADD_FLAGS) {
+    __ LoadP(r7, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ LoadP(r8, FieldMemOperand(r4, HeapObject::kMapOffset));
+    __ lbz(r7, FieldMemOperand(r7, Map::kInstanceTypeOffset));
+    __ lbz(r8, FieldMemOperand(r8, Map::kInstanceTypeOffset));
+  }
+  Label non_ascii, allocated, ascii_data;
+  STATIC_ASSERT(kTwoByteStringTag == 0);
+  __ andi(r0, r7, Operand(kStringEncodingMask));
+  __ beq(&non_ascii, cr0);
+  __ andi(r0, r8, Operand(kStringEncodingMask));
+  __ beq(&non_ascii, cr0);
+
+  // Allocate an ASCII cons string.
+  __ bind(&ascii_data);
+  __ AllocateAsciiConsString(r10, r9, r7, r8, &call_runtime);
+  __ bind(&allocated);
+  // Fill the fields of the cons string.
+  __ StoreP(r3, FieldMemOperand(r10, ConsString::kFirstOffset), r0);
+  __ StoreP(r4, FieldMemOperand(r10, ConsString::kSecondOffset), r0);
+  __ mr(r3, r10);
+  __ IncrementCounter(counters->string_add_native(), 1, r5, r6);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ Ret();
+
+  __ bind(&non_ascii);
+  // At least one of the strings is two-byte. Check whether it happens
+  // to contain only ASCII characters.
+  // r7: first instance type.
+  // r8: second instance type.
+  __ andi(r0, r7, Operand(kAsciiDataHintMask));
+  __ bne(&ascii_data, cr0);
+  __ andi(r0, r8, Operand(kAsciiDataHintMask));
+  __ bne(&ascii_data, cr0);
+  __ xor_(r7, r7, r8);
+  STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
+  __ andi(r7, r7, Operand(kAsciiStringTag | kAsciiDataHintTag));
+  __ cmpi(r7, Operand(kAsciiStringTag | kAsciiDataHintTag));
+  __ beq(&ascii_data);
+
+  // Allocate a two byte cons string.
+  __ AllocateTwoByteConsString(r10, r9, r7, r8, &call_runtime);
+  __ b(&allocated);
+
+  // We cannot encounter sliced strings or cons strings here since:
+  STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
+  // Handle creating a flat result from either external or sequential strings.
+  // Locate the first characters' locations.
+  // r3: first string
+  // r4: second string
+  // r5: length of first string
+  // r6: length of second string
+  // r7: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // r8: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
+  // r9: sum of lengths.
+  Label first_prepared, second_prepared, external_string1, external_string2;
+  __ bind(&string_add_flat_result);
+  if (flags_ != NO_STRING_ADD_FLAGS) {
+    __ LoadP(r7, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ LoadP(r8, FieldMemOperand(r4, HeapObject::kMapOffset));
+    __ lbz(r7, FieldMemOperand(r7, Map::kInstanceTypeOffset));
+    __ lbz(r8, FieldMemOperand(r8, Map::kInstanceTypeOffset));
+  }
+
+  // Check whether both strings have same encoding
+  __ xor_(r10, r7, r8);
+  __ andi(r0, r10, Operand(kStringEncodingMask));
+  __ bne(&call_runtime, cr0);
+
+  STATIC_ASSERT(kSeqStringTag == 0);
+  __ andi(r0, r7, Operand(kStringRepresentationMask));
+  __ bne(&external_string1, cr0);
+  STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
+  __ addi(r10, r3, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ b(&first_prepared);
+  // External string: rule out short external string and load string resource.
+  STATIC_ASSERT(kShortExternalStringTag != 0);
+  __ bind(&external_string1);
+  __ andi(r0, r7, Operand(kShortExternalStringMask));
+  __ bne(&call_runtime, cr0);
+  __ LoadP(r10, FieldMemOperand(r3, ExternalString::kResourceDataOffset));
+  __ bind(&first_prepared);
+
+  STATIC_ASSERT(kSeqStringTag == 0);
+  __ andi(r0, r8, Operand(kStringRepresentationMask));
+  __ bne(&external_string2, cr0);
+  STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
+  __ addi(r4, r4, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ b(&second_prepared);
+  // External string: rule out short external string and load string resource.
+  STATIC_ASSERT(kShortExternalStringTag != 0);
+  __ bind(&external_string2);
+  __ andi(r0, r8, Operand(kShortExternalStringMask));
+  __ bne(&call_runtime, cr0);
+  __ LoadP(r4, FieldMemOperand(r4, ExternalString::kResourceDataOffset));
+  __ bind(&second_prepared);
+
+  Label non_ascii_string_add_flat_result;
+  // r10: first character of first string
+  // r4: first character of second string
+  // r5: length of first string.
+  // r6: length of second string.
+  // r9: sum of lengths.
+  // Both strings have the same encoding.
+  STATIC_ASSERT(kTwoByteStringTag == 0);
+  __ andi(r0, r8, Operand(kStringEncodingMask));
+  __ beq(&non_ascii_string_add_flat_result, cr0);
+
+  __ AllocateAsciiString(r3, r9, r7, r8, r22, &call_runtime);
+  __ addi(r9, r3, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  // r3: result string.
+  // r10: first character of first string.
+  // r4: first character of second string.
+  // r5: length of first string.
+  // r6: length of second string.
+  // r9: first character of result.
+  StringHelper::GenerateCopyCharacters(masm, r9, r10, r5, r7, true);
+  // r9: next character of result.
+  StringHelper::GenerateCopyCharacters(masm, r9, r4, r6, r7, true);
+  __ IncrementCounter(counters->string_add_native(), 1, r5, r6);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ Ret();
+
+  __ bind(&non_ascii_string_add_flat_result);
+  __ AllocateTwoByteString(r3, r9, r7, r8, r22, &call_runtime);
+  __ addi(r9, r3, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+  // r3: result string.
+  // r10: first character of first string.
+  // r4: first character of second string.
+  // r5: length of first string.
+  // r6: length of second string.
+  // r9: first character of result.
+  StringHelper::GenerateCopyCharacters(masm, r9, r10, r5, r7, false);
+  // r9: next character of result.
+  StringHelper::GenerateCopyCharacters(masm, r9, r4, r6, r7, false);
+  __ IncrementCounter(counters->string_add_native(), 1, r5, r6);
+  __ addi(sp, sp, Operand(2 * kPointerSize));
+  __ Ret();
+
+  // Just jump to runtime to add the two strings.
+  __ bind(&call_runtime);
+  __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+
+  if (call_builtin.is_linked()) {
+    __ bind(&call_builtin);
+    __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+  }
+}
+
+
+void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
+                                            int stack_offset,
+                                            Register arg,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Register scratch3,
+                                            Register scratch4,
+                                            Label* slow) {
+  // First check if the argument is already a string.
+  Label not_string, done;
+  __ JumpIfSmi(arg, &not_string);
+  __ CompareObjectType(arg, scratch1, scratch1, FIRST_NONSTRING_TYPE);
+  __ blt(&done);
+
+  // Check the number to string cache.
+  Label not_cached;
+  __ bind(&not_string);
+  // Puts the cached result into scratch1.
+  NumberToStringStub::GenerateLookupNumberStringCache(masm,
+                                                      arg,
+                                                      scratch1,
+                                                      scratch2,
+                                                      scratch3,
+                                                      scratch4,
+                                                      false,
+                                                      &not_cached);
+  __ mr(arg, scratch1);
+  __ StoreP(arg, MemOperand(sp, stack_offset));
+  __ b(&done);
+
+  // Check if the argument is a safe string wrapper.
+  __ bind(&not_cached);
+  __ JumpIfSmi(arg, slow);
+  __ CompareObjectType(
+      arg, scratch1, scratch2, JS_VALUE_TYPE);  // map -> scratch1.
+  __ bne(slow);
+  __ lbz(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset));
+  __ andi(scratch2,
+          scratch2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
+  __ cmpi(scratch2,
+         Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
+  __ bne(slow);
+  __ LoadP(arg, FieldMemOperand(arg, JSValue::kValueOffset));
+  __ StoreP(arg, MemOperand(sp, stack_offset));
+
+  __ bind(&done);
+}
+
+
+void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
+  ASSERT(state_ == CompareIC::SMIS);
+  Label miss;
+  __ orx(r5, r4, r3);
+  __ JumpIfNotSmi(r5, &miss);
+
+  if (GetCondition() == eq) {
+    // For equality we do not care about the sign of the result.
+    // __ sub(r3, r3, r4, SetCC);
+     __ sub(r3, r3, r4);
+  } else {
+    // Untag before subtracting to avoid handling overflow.
+    __ SmiUntag(r4);
+    __ SmiUntag(r3);
+    __ sub(r3, r4, r3);
+  }
+  __ Ret();
+
+  __ bind(&miss);
+  GenerateMiss(masm);
+}
+
+
+void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
+  ASSERT(state_ == CompareIC::HEAP_NUMBERS);
+  Label generic_stub;
+  Label unordered, maybe_undefined1, maybe_undefined2;
+  Label miss;
+  Label equal, less_than;
+
+  __ and_(r5, r4, r3);
+  __ JumpIfSmi(r5, &generic_stub);
+
+  __ CompareObjectType(r3, r5, r5, HEAP_NUMBER_TYPE);
+  __ bne(&maybe_undefined1);
+  __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE);
+  __ bne(&maybe_undefined2);
+
+  // Inlining the double comparison and falling back to the general compare
+  // stub if NaN is involved
+
+  // Load left and right operand
+  // likely we can combine the constants to remove the sub
+  __ lfd(d0, FieldMemOperand(r4, HeapNumber::kValueOffset));
+  __ lfd(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
+
+  // Compare operands
+  __ fcmpu(d0, d1);
+
+  // Don't base result on status bits when a NaN is involved.
+  __ bunordered(&unordered);
+
+  // Return a result of -1, 0, or 1, based on status bits.
+  __ beq(&equal);
+  __ blt(&less_than);
+  //  assume greater than
+  __ li(r3, Operand(GREATER));
+  __ Ret();
+  __ bind(&equal);
+  __ li(r3, Operand(EQUAL));
+  __ Ret();
+  __ bind(&less_than);
+  __ li(r3, Operand(LESS));
+  __ Ret();
+
+  __ bind(&unordered);
+
+  CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r4, r3);
+  __ bind(&generic_stub);
+  __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
+
+  __ bind(&maybe_undefined1);
+  if (Token::IsOrderedRelationalCompareOp(op_)) {
+    __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
+    __ bne(&miss);
+    __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE);
+    __ bne(&maybe_undefined2);
+    __ b(&unordered);
+  }
+
+  __ bind(&maybe_undefined2);
+  if (Token::IsOrderedRelationalCompareOp(op_)) {
+    __ CompareRoot(r4, Heap::kUndefinedValueRootIndex);
+    __ beq(&unordered);
+  }
+
+  __ bind(&miss);
+  GenerateMiss(masm);
+}
+
+
+void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
+  ASSERT(state_ == CompareIC::SYMBOLS);
+  Label miss, not_equal;
+
+  // Registers containing left and right operands respectively.
+  Register left = r4;
+  Register right = r3;
+  Register tmp1 = r5;
+  Register tmp2 = r6;
+
+  // Check that both operands are heap objects.
+  __ JumpIfEitherSmi(left, right, &miss);
+
+  // Check that both operands are symbols.
+  __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
+  __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
+  __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
+  __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
+  STATIC_ASSERT(kSymbolTag != 0);
+  __ and_(tmp1, tmp1, tmp2);
+  __ andi(r0, tmp1, Operand(kIsSymbolMask));
+  __ beq(&miss, cr0);
+
+  // Symbols are compared by identity.
+  __ cmp(left, right);
+  __ bne(&not_equal);
+  // Make sure r3 is non-zero. At this point input operands are
+  // guaranteed to be non-zero.
+  ASSERT(right.is(r3));
+  STATIC_ASSERT(EQUAL == 0);
+  STATIC_ASSERT(kSmiTag == 0);
+  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
+  __ bind(&not_equal);
+  __ Ret();
+
+  __ bind(&miss);
+  GenerateMiss(masm);
+}
+
+
+void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
+  ASSERT(state_ == CompareIC::STRINGS);
+  Label miss, not_identical, is_symbol;
+
+  bool equality = Token::IsEqualityOp(op_);
+
+  // Registers containing left and right operands respectively.
+  Register left = r4;
+  Register right = r3;
+  Register tmp1 = r5;
+  Register tmp2 = r6;
+  Register tmp3 = r7;
+  Register tmp4 = r8;
+
+  // Check that both operands are heap objects.
+  __ JumpIfEitherSmi(left, right, &miss);
+
+  // Check that both operands are strings. This leaves the instance
+  // types loaded in tmp1 and tmp2.
+  __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
+  __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
+  __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
+  __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
+  STATIC_ASSERT(kNotStringTag != 0);
+  __ orx(tmp3, tmp1, tmp2);
+  __ andi(r0, tmp3, Operand(kIsNotStringMask));
+  __ bne(&miss, cr0);
+
+  // Fast check for identical strings.
+  __ cmp(left, right);
+  STATIC_ASSERT(EQUAL == 0);
+  STATIC_ASSERT(kSmiTag == 0);
+  __ bne(&not_identical);
+  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
+  __ Ret();
+  __ bind(&not_identical);
+
+  // Handle not identical strings.
+
+  // Check that both strings are symbols. If they are, we're done
+  // because we already know they are not identical.
+  if (equality) {
+    ASSERT(GetCondition() == eq);
+    STATIC_ASSERT(kSymbolTag != 0);
+    __ and_(tmp3, tmp1, tmp2);
+    __ andi(r0, tmp3, Operand(kIsSymbolMask));
+    __ beq(&is_symbol, cr0);
+    // Make sure r3 is non-zero. At this point input operands are
+    // guaranteed to be non-zero.
+    ASSERT(right.is(r3));
+    __ Ret();
+    __ bind(&is_symbol);
+  }
+
+  // Check that both strings are sequential ASCII.
+  Label runtime;
+  __ JumpIfBothInstanceTypesAreNotSequentialAscii(
+      tmp1, tmp2, tmp3, tmp4, &runtime);
+
+  // Compare flat ASCII strings. Returns when done.
+  if (equality) {
+    StringCompareStub::GenerateFlatAsciiStringEquals(
+        masm, left, right, tmp1, tmp2);
+  } else {
+    StringCompareStub::GenerateCompareFlatAsciiStrings(
+        masm, left, right, tmp1, tmp2, tmp3);
+  }
+
+  // Handle more complex cases in runtime.
+  __ bind(&runtime);
+  __ Push(left, right);
+  if (equality) {
+    __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
+  } else {
+    __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
+  }
+
+  __ bind(&miss);
+  GenerateMiss(masm);
+}
+
+
+void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
+  ASSERT(state_ == CompareIC::OBJECTS);
+  Label miss;
+  __ and_(r5, r4, r3);
+  __ JumpIfSmi(r5, &miss);
+
+  __ CompareObjectType(r3, r5, r5, JS_OBJECT_TYPE);
+  __ bne(&miss);
+  __ CompareObjectType(r4, r5, r5, JS_OBJECT_TYPE);
+  __ bne(&miss);
+
+  ASSERT(GetCondition() == eq);
+  __ sub(r3, r3, r4);
+  __ Ret();
+
+  __ bind(&miss);
+  GenerateMiss(masm);
+}
+
+
+void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
+  Label miss;
+  __ and_(r5, r4, r3);
+  __ JumpIfSmi(r5, &miss);
+  __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset));
+  __ Cmpi(r5, Operand(known_map_), r0);
+  __ bne(&miss);
+  __ Cmpi(r6, Operand(known_map_), r0);
+  __ bne(&miss);
+
+  __ sub(r3, r3, r4);
+  __ Ret();
+
+  __ bind(&miss);
+  GenerateMiss(masm);
+}
+
+
+
+void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
+  {
+    // Call the runtime system in a fresh internal frame.
+    ExternalReference miss =
+        ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate());
+
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(r4, r3);
+    __ mflr(r0);
+    __ push(r0);
+    __ Push(r4, r3);
+    __ LoadSmiLiteral(ip, Smi::FromInt(op_));
+    __ push(ip);
+    __ CallExternalReference(miss, 3);
+    // Compute the entry point of the rewritten stub.
+    __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+    // Restore registers.
+    __ pop(r0);
+    __ mtlr(r0);
+    __ pop(r3);
+    __ pop(r4);
+  }
+
+  __ Jump(r5);
+}
+
+// This stub is paired with DirectCEntryStub::GenerateCall
+void DirectCEntryStub::Generate(MacroAssembler* masm) {
+  // Retrieve return address
+  __ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
+  __ Jump(r0);
+}
+
+
+void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
+                                    ExternalReference function) {
+  __ mov(r6, Operand(function));
+  GenerateCall(masm, r6);
+}
+
+
+void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
+                                    Register target) {
+  Register scratch = r11;
+#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
+  Register dest = ip;
+  // Native AIX/PPC64 Linux use a function descriptor.
+  __ LoadP(ToRegister(2), MemOperand(target, kPointerSize));  // TOC
+  __ LoadP(ip, MemOperand(target, 0));  // Instruction address
+#elif ABI_TOC_ADDRESSABILITY_VIA_IP
+  Register dest = ip;
+  __ Move(ip, target);
+#else
+  Register dest = target;
+#endif
+
+  __ mov(r0, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
+                     RelocInfo::CODE_TARGET));
+
+  // Block the trampoline pool through the whole function to make sure the
+  // number of generated instructions is constant.
+  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
+
+  // Push return address (accessible to GC through exit frame pc).
+  Label start, here;
+  __ bind(&start);
+  __ b(&here, SetLK);
+  __ bind(&here);
+  __ mflr(scratch);
+  __ mtlr(r0);  // from above, so we know where to return
+  __ addi(scratch, scratch, Operand(6 * Assembler::kInstrSize));
+  __ StoreP(scratch, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
+  __ Jump(dest);  // Call the C++ function.
+  ASSERT_EQ(Assembler::kInstrSize +
+            (6 * Assembler::kInstrSize),
+            masm->SizeOfCodeGeneratedSince(&start));
+}
+
+
+void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+                                                        Label* miss,
+                                                        Label* done,
+                                                        Register receiver,
+                                                        Register properties,
+                                                        Handle<String> name,
+                                                        Register scratch0) {
+  // If names of slots in range from 1 to kProbes - 1 for the hash value are
+  // not equal to the name and kProbes-th slot is not used (its name is the
+  // undefined value), it guarantees the hash table doesn't contain the
+  // property. It's true even if some slots represent deleted properties
+  // (their names are the hole value).
+  for (int i = 0; i < kInlinedProbes; i++) {
+    // scratch0 points to properties hash.
+    // Compute the masked index: (hash + i + i * i) & mask.
+    Register index = scratch0;
+    // Capacity is smi 2^n.
+    __ LoadP(index, FieldMemOperand(properties, kCapacityOffset));
+    __ subi(index, index, Operand(1));
+    __ LoadSmiLiteral(ip, Smi::FromInt(name->Hash() +
+                                       StringDictionary::GetProbeOffset(i)));
+    __ and_(index, index, ip);
+
+    // Scale the index by multiplying by the entry size.
+    ASSERT(StringDictionary::kEntrySize == 3);
+    __ ShiftLeftImm(ip, index, Operand(1));
+    __ add(index, index, ip);  // index *= 3.
+
+    Register entity_name = scratch0;
+    // Having undefined at this place means the name is not contained.
+    Register tmp = properties;
+    __ SmiToPtrArrayOffset(ip, index);
+    __ add(tmp, properties, ip);
+    __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
+
+    ASSERT(!tmp.is(entity_name));
+    __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
+    __ cmp(entity_name, tmp);
+    __ beq(done);
+
+    if (i != kInlinedProbes - 1) {
+      // Load the hole ready for use below:
+      __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
+
+      // Stop if found the property.
+      __ Cmpi(entity_name, Operand(Handle<String>(name)), r0);
+      __ beq(miss);
+
+      Label the_hole;
+      __ cmp(entity_name, tmp);
+      __ beq(&the_hole);
+
+      // Check if the entry name is not a symbol.
+      __ LoadP(entity_name, FieldMemOperand(entity_name,
+                                            HeapObject::kMapOffset));
+      __ lbz(entity_name,
+              FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
+      __ andi(r0, entity_name, Operand(kIsSymbolMask));
+      __ beq(miss, cr0);
+
+      __ bind(&the_hole);
+
+      // Restore the properties.
+      __ LoadP(properties,
+             FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+    }
+  }
+
+  const int spill_mask =
+      (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() |
+       r5.bit() | r4.bit() | r3.bit());
+
+  __ mflr(r0);
+  __ MultiPush(spill_mask);
+
+  __ LoadP(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+  __ mov(r4, Operand(Handle<String>(name)));
+  StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
+  __ CallStub(&stub);
+  __ cmpi(r3, Operand::Zero());
+
+  __ MultiPop(spill_mask);  // MultiPop does not touch condition flags
+  __ mtlr(r0);
+
+  __ beq(done);
+  __ bne(miss);
+}
+
+
+// Probe the string dictionary in the |elements| register. Jump to the
+// |done| label if a property with the given name is found. Jump to
+// the |miss| label otherwise.
+// If lookup was successful |scratch2| will be equal to elements + 4 * index.
+void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
+                                                        Label* miss,
+                                                        Label* done,
+                                                        Register elements,
+                                                        Register name,
+                                                        Register scratch1,
+                                                        Register scratch2) {
+  ASSERT(!elements.is(scratch1));
+  ASSERT(!elements.is(scratch2));
+  ASSERT(!name.is(scratch1));
+  ASSERT(!name.is(scratch2));
+
+  // Assert that name contains a string.
+  __ AssertString(name);
+
+  // Compute the capacity mask.
+  __ LoadP(scratch1, FieldMemOperand(elements, kCapacityOffset));
+  __ SmiUntag(scratch1);  // convert smi to int
+  __ subi(scratch1, scratch1, Operand(1));
+
+  // Generate an unrolled loop that performs a few probes before
+  // giving up. Measurements done on Gmail indicate that 2 probes
+  // cover ~93% of loads from dictionaries.
+  for (int i = 0; i < kInlinedProbes; i++) {
+    // Compute the masked index: (hash + i + i * i) & mask.
+    __ lwz(scratch2, FieldMemOperand(name, String::kHashFieldOffset));
+    if (i > 0) {
+      // Add the probe offset (i + i * i) left shifted to avoid right shifting
+      // the hash in a separate instruction. The value hash + i + i * i is right
+      // shifted in the following and instruction.
+      ASSERT(StringDictionary::GetProbeOffset(i) <
+             1 << (32 - String::kHashFieldSlot));
+      __ addi(scratch2, scratch2, Operand(
+                  StringDictionary::GetProbeOffset(i) << String::kHashShift));
+    }
+    __ srwi(scratch2, scratch2, Operand(String::kHashShift));
+    __ and_(scratch2, scratch1, scratch2);
+
+    // Scale the index by multiplying by the element size.
+    ASSERT(StringDictionary::kEntrySize == 3);
+    // scratch2 = scratch2 * 3.
+    __ ShiftLeftImm(ip, scratch2, Operand(1));
+    __ add(scratch2, scratch2, ip);
+
+    // Check if the key is identical to the name.
+    __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2));
+    __ add(scratch2, elements, ip);
+    __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset));
+    __ cmp(name, ip);
+    __ beq(done);
+  }
+
+  const int spill_mask =
+      (r0.bit() | r9.bit() | r8.bit() | r7.bit() |
+       r6.bit() | r5.bit() | r4.bit() | r3.bit()) &
+      ~(scratch1.bit() | scratch2.bit());
+
+  __ mflr(r0);
+  __ MultiPush(spill_mask);
+  if (name.is(r3)) {
+    ASSERT(!elements.is(r4));
+    __ mr(r4, name);
+    __ mr(r3, elements);
+  } else {
+    __ mr(r3, elements);
+    __ mr(r4, name);
+  }
+  StringDictionaryLookupStub stub(POSITIVE_LOOKUP);
+  __ CallStub(&stub);
+  __ cmpi(r3, Operand::Zero());
+  __ mr(scratch2, r5);
+  __ MultiPop(spill_mask);
+  __ mtlr(r0);
+
+  __ bne(done);
+  __ beq(miss);
+}
+
+
+void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
+  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
+  // we cannot call anything that could cause a GC from this stub.
+  // Registers:
+  //  result: StringDictionary to probe
+  //  r4: key
+  //  : StringDictionary to probe.
+  //  index_: will hold an index of entry if lookup is successful.
+  //          might alias with result_.
+  // Returns:
+  //  result_ is zero if lookup failed, non zero otherwise.
+
+  Register result = r3;
+  Register dictionary = r3;
+  Register key = r4;
+  Register index = r5;
+  Register mask = r6;
+  Register hash = r7;
+  Register undefined = r8;
+  Register entry_key = r9;
+  Register scratch = r9;
+
+  Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
+
+  __ LoadP(mask, FieldMemOperand(dictionary, kCapacityOffset));
+  __ SmiUntag(mask);
+  __ subi(mask, mask, Operand(1));
+
+  __ lwz(hash, FieldMemOperand(key, String::kHashFieldOffset));
+
+  __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
+
+  for (int i = kInlinedProbes; i < kTotalProbes; i++) {
+    // Compute the masked index: (hash + i + i * i) & mask.
+    // Capacity is smi 2^n.
+    if (i > 0) {
+      // Add the probe offset (i + i * i) left shifted to avoid right shifting
+      // the hash in a separate instruction. The value hash + i + i * i is right
+      // shifted in the following and instruction.
+      ASSERT(StringDictionary::GetProbeOffset(i) <
+             1 << (32 - String::kHashFieldSlot));
+      __ addi(index, hash, Operand(
+                  StringDictionary::GetProbeOffset(i) << String::kHashShift));
+    } else {
+      __ mr(index, hash);
+    }
+    __ srwi(r0, index, Operand(String::kHashShift));
+    __ and_(index, mask, r0);
+
+    // Scale the index by multiplying by the entry size.
+    ASSERT(StringDictionary::kEntrySize == 3);
+    __ ShiftLeftImm(scratch, index, Operand(1));
+    __ add(index, index, scratch);  // index *= 3.
+
+    ASSERT_EQ(kSmiTagSize, 1);
+    __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2));
+    __ add(index, dictionary, scratch);
+    __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset));
+
+    // Having undefined at this place means the name is not contained.
+    __ cmp(entry_key, undefined);
+    __ beq(&not_in_dictionary);
+
+    // Stop if found the property.
+    __ cmp(entry_key, key);
+    __ beq(&in_dictionary);
+
+    if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
+      // Check if the entry name is not a symbol.
+      __ LoadP(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
+      __ lbz(entry_key,
+              FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
+      __ andi(r0, entry_key, Operand(kIsSymbolMask));
+      __ beq(&maybe_in_dictionary, cr0);
+    }
+  }
+
+  __ bind(&maybe_in_dictionary);
+  // If we are doing negative lookup then probing failure should be
+  // treated as a lookup success. For positive lookup probing failure
+  // should be treated as lookup failure.
+  if (mode_ == POSITIVE_LOOKUP) {
+    __ li(result, Operand::Zero());
+    __ Ret();
+  }
+
+  __ bind(&in_dictionary);
+  __ li(result, Operand(1));
+  __ Ret();
+
+  __ bind(&not_in_dictionary);
+  __ li(result, Operand::Zero());
+  __ Ret();
+}
+
+
+struct AheadOfTimeWriteBarrierStubList {
+  Register object, value, address;
+  RememberedSetAction action;
+};
+
+#define REG(Name) { kRegister_ ## Name ## _Code }
+
+static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
+  // Used in RegExpExecStub.
+  { REG(r28), REG(r26), REG(r10), EMIT_REMEMBERED_SET },
+  { REG(r28), REG(r5), REG(r10), EMIT_REMEMBERED_SET },
+  // Used in CompileArrayPushCall.
+  // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
+  // Also used in KeyedStoreIC::GenerateGeneric.
+  { REG(r6), REG(r7), REG(r8), EMIT_REMEMBERED_SET },
+  // Used in CompileStoreGlobal.
+  { REG(r7), REG(r4), REG(r5), OMIT_REMEMBERED_SET },
+  // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
+  { REG(r4), REG(r5), REG(r6), EMIT_REMEMBERED_SET },
+  { REG(r6), REG(r5), REG(r4), EMIT_REMEMBERED_SET },
+  // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
+  { REG(r5), REG(r4), REG(r6), EMIT_REMEMBERED_SET },
+  { REG(r6), REG(r4), REG(r5), EMIT_REMEMBERED_SET },
+  // KeyedStoreStubCompiler::GenerateStoreFastElement.
+  { REG(r6), REG(r5), REG(r7), EMIT_REMEMBERED_SET },
+  { REG(r5), REG(r6), REG(r7), EMIT_REMEMBERED_SET },
+  // ElementsTransitionGenerator::GenerateMapChangeElementTransition
+  // and ElementsTransitionGenerator::GenerateSmiToDouble
+  // and ElementsTransitionGenerator::GenerateDoubleToObject
+  { REG(r5), REG(r6), REG(r22), EMIT_REMEMBERED_SET },
+  { REG(r5), REG(r6), REG(r22), OMIT_REMEMBERED_SET },
+  // ElementsTransitionGenerator::GenerateDoubleToObject
+  { REG(r9), REG(r5), REG(r3), EMIT_REMEMBERED_SET },
+  { REG(r5), REG(r9), REG(r22), EMIT_REMEMBERED_SET },
+  // StoreArrayLiteralElementStub::Generate
+  { REG(r8), REG(r3), REG(r9), EMIT_REMEMBERED_SET },
+  // FastNewClosureStub::Generate
+  { REG(r5), REG(r7), REG(r4), EMIT_REMEMBERED_SET },
+  // Null termination.
+  { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
+};
+
+#undef REG
+
+
+bool RecordWriteStub::IsPregenerated() {
+  for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
+       !entry->object.is(no_reg);
+       entry++) {
+    if (object_.is(entry->object) &&
+        value_.is(entry->value) &&
+        address_.is(entry->address) &&
+        remembered_set_action_ == entry->action &&
+        save_fp_regs_mode_ == kDontSaveFPRegs) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+bool StoreBufferOverflowStub::IsPregenerated() {
+  return save_doubles_ == kDontSaveFPRegs || ISOLATE->fp_stubs_generated();
+}
+
+
+void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() {
+  StoreBufferOverflowStub stub1(kDontSaveFPRegs);
+  stub1.GetCode()->set_is_pregenerated(true);
+}
+
+
+void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() {
+  for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
+       !entry->object.is(no_reg);
+       entry++) {
+    RecordWriteStub stub(entry->object,
+                         entry->value,
+                         entry->address,
+                         entry->action,
+                         kDontSaveFPRegs);
+    stub.GetCode()->set_is_pregenerated(true);
+  }
+}
+
+
+bool CodeStub::CanUseFPRegisters() {
+  return true;
+}
+
+
+// Takes the input in 3 registers: address_ value_ and object_.  A pointer to
+// the value has just been written into the object, now this stub makes sure
+// we keep the GC informed.  The word in the object where the value has been
+// written is in the address register.
+void RecordWriteStub::Generate(MacroAssembler* masm) {
+  Label skip_to_incremental_noncompacting;
+  Label skip_to_incremental_compacting;
+  const int crBit = Assembler::encode_crbit(cr2, CR_LT);
+
+  // The first two branch instructions are generated with labels so as to
+  // get the offset fixed up correctly by the bind(Label*) call.  We patch
+  // it back and forth between branch condition True and False
+  // when we start and stop incremental heap marking.
+  // See RecordWriteStub::Patch for details.
+
+  // Clear the bit, branch on True for NOP action initially
+  __ crxor(crBit, crBit, crBit);
+  __ blt(&skip_to_incremental_noncompacting, cr2);
+  __ blt(&skip_to_incremental_compacting, cr2);
+
+  if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
+    __ RememberedSetHelper(object_,
+                           address_,
+                           value_,
+                           save_fp_regs_mode_,
+                           MacroAssembler::kReturnAtEnd);
+  }
+  __ Ret();
+
+  __ bind(&skip_to_incremental_noncompacting);
+  GenerateIncremental(masm, INCREMENTAL);
+
+  __ bind(&skip_to_incremental_compacting);
+  GenerateIncremental(masm, INCREMENTAL_COMPACTION);
+
+  // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
+  // Will be checked in IncrementalMarking::ActivateGeneratedStub.
+  // patching not required on PPC as the initial path is effectively NOP
+}
+
+
+void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
+  regs_.Save(masm);
+
+  if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
+    Label dont_need_remembered_set;
+
+    __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0));
+    __ JumpIfNotInNewSpace(regs_.scratch0(),  // Value.
+                           regs_.scratch0(),
+                           &dont_need_remembered_set);
+
+    __ CheckPageFlag(regs_.object(),
+                     regs_.scratch0(),
+                     1 << MemoryChunk::SCAN_ON_SCAVENGE,
+                     ne,
+                     &dont_need_remembered_set);
+
+    // First notify the incremental marker if necessary, then update the
+    // remembered set.
+    CheckNeedsToInformIncrementalMarker(
+        masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode);
+    InformIncrementalMarker(masm, mode);
+    regs_.Restore(masm);
+    __ RememberedSetHelper(object_,
+                           address_,
+                           value_,
+                           save_fp_regs_mode_,
+                           MacroAssembler::kReturnAtEnd);
+
+    __ bind(&dont_need_remembered_set);
+  }
+
+  CheckNeedsToInformIncrementalMarker(
+      masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
+  InformIncrementalMarker(masm, mode);
+  regs_.Restore(masm);
+  __ Ret();
+}
+
+
+void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) {
+  regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_);
+  int argument_count = 3;
+  __ PrepareCallCFunction(argument_count, regs_.scratch0());
+  Register address =
+      r3.is(regs_.address()) ? regs_.scratch0() : regs_.address();
+  ASSERT(!address.is(regs_.object()));
+  ASSERT(!address.is(r3));
+  __ mr(address, regs_.address());
+  __ mr(r3, regs_.object());
+  if (mode == INCREMENTAL_COMPACTION) {
+    __ mr(r4, address);
+  } else {
+    ASSERT(mode == INCREMENTAL);
+    __ LoadP(r4, MemOperand(address, 0));
+  }
+  __ mov(r5, Operand(ExternalReference::isolate_address()));
+
+  AllowExternalCallThatCantCauseGC scope(masm);
+  if (mode == INCREMENTAL_COMPACTION) {
+    __ CallCFunction(
+        ExternalReference::incremental_evacuation_record_write_function(
+            masm->isolate()),
+        argument_count);
+  } else {
+    ASSERT(mode == INCREMENTAL);
+    __ CallCFunction(
+        ExternalReference::incremental_marking_record_write_function(
+            masm->isolate()),
+        argument_count);
+  }
+  regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_);
+}
+
+
+void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
+    MacroAssembler* masm,
+    OnNoNeedToInformIncrementalMarker on_no_need,
+    Mode mode) {
+  Label on_black;
+  Label need_incremental;
+  Label need_incremental_pop_scratch;
+
+  ASSERT((~Page::kPageAlignmentMask & 0xffff) == 0);
+  __ lis(r0, Operand((~Page::kPageAlignmentMask >> 16)));
+  __ and_(regs_.scratch0(), regs_.object(), r0);
+  __ LoadP(regs_.scratch1(),
+         MemOperand(regs_.scratch0(),
+                    MemoryChunk::kWriteBarrierCounterOffset));
+  __ subi(regs_.scratch1(), regs_.scratch1(), Operand(1));
+  __ StoreP(regs_.scratch1(),
+            MemOperand(regs_.scratch0(),
+                       MemoryChunk::kWriteBarrierCounterOffset));
+  __ cmpi(regs_.scratch1(), Operand::Zero());  // PPC, we could do better here
+  __ blt(&need_incremental);
+
+  // Let's look at the color of the object:  If it is not black we don't have
+  // to inform the incremental marker.
+  __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black);
+
+  regs_.Restore(masm);
+  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
+    __ RememberedSetHelper(object_,
+                           address_,
+                           value_,
+                           save_fp_regs_mode_,
+                           MacroAssembler::kReturnAtEnd);
+  } else {
+    __ Ret();
+  }
+
+  __ bind(&on_black);
+
+  // Get the value from the slot.
+  __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0));
+
+  if (mode == INCREMENTAL_COMPACTION) {
+    Label ensure_not_white;
+
+    __ CheckPageFlag(regs_.scratch0(),  // Contains value.
+                     regs_.scratch1(),  // Scratch.
+                     MemoryChunk::kEvacuationCandidateMask,
+                     eq,
+                     &ensure_not_white);
+
+    __ CheckPageFlag(regs_.object(),
+                     regs_.scratch1(),  // Scratch.
+                     MemoryChunk::kSkipEvacuationSlotsRecordingMask,
+                     eq,
+                     &need_incremental);
+
+    __ bind(&ensure_not_white);
+  }
+
+  // We need extra registers for this, so we push the object and the address
+  // register temporarily.
+  __ Push(regs_.object(), regs_.address());
+  __ EnsureNotWhite(regs_.scratch0(),  // The value.
+                    regs_.scratch1(),  // Scratch.
+                    regs_.object(),  // Scratch.
+                    regs_.address(),  // Scratch.
+                    &need_incremental_pop_scratch);
+  __ Pop(regs_.object(), regs_.address());
+
+  regs_.Restore(masm);
+  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
+    __ RememberedSetHelper(object_,
+                           address_,
+                           value_,
+                           save_fp_regs_mode_,
+                           MacroAssembler::kReturnAtEnd);
+  } else {
+    __ Ret();
+  }
+
+  __ bind(&need_incremental_pop_scratch);
+  __ Pop(regs_.object(), regs_.address());
+
+  __ bind(&need_incremental);
+
+  // Fall through when we need to inform the incremental marker.
+}
+
+
+void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3    : element value to store
+  //  -- r4    : array literal
+  //  -- r5    : map of array literal
+  //  -- r6    : element index as smi
+  //  -- r7    : array literal index in function as smi
+  // -----------------------------------
+
+  Label element_done;
+  Label double_elements;
+  Label smi_element;
+  Label slow_elements;
+  Label fast_elements;
+
+  __ CheckFastElements(r5, r8, &double_elements);
+  // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS
+  __ JumpIfSmi(r3, &smi_element);
+  __ CheckFastSmiElements(r5, r8, &fast_elements);
+
+  // Store into the array literal requires a elements transition. Call into
+  // the runtime.
+  __ bind(&slow_elements);
+  // call.
+  __ Push(r4, r6, r3);
+  __ LoadP(r8, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  __ LoadP(r8, FieldMemOperand(r8, JSFunction::kLiteralsOffset));
+  __ Push(r8, r7);
+  __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
+
+  // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
+  __ bind(&fast_elements);
+  __ LoadP(r8, FieldMemOperand(r4, JSObject::kElementsOffset));
+  __ SmiToPtrArrayOffset(r9, r6);
+  __ add(r9, r8, r9);
+#if V8_TARGET_ARCH_PPC64
+  // add due to offset alignment requirements of StorePU
+  __ addi(r9, r9, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ StoreP(r3, MemOperand(r9));
+#else
+  __ StorePU(r3, MemOperand(r9, FixedArray::kHeaderSize - kHeapObjectTag));
+#endif
+  // Update the write barrier for the array store.
+  __ RecordWrite(r8, r9, r3, kLRHasNotBeenSaved, kDontSaveFPRegs,
+                 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  __ Ret();
+
+  // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS,
+  // and value is Smi.
+  __ bind(&smi_element);
+  __ LoadP(r8, FieldMemOperand(r4, JSObject::kElementsOffset));
+  __ SmiToPtrArrayOffset(r9, r6);
+  __ add(r9, r8, r9);
+  __ StoreP(r3, FieldMemOperand(r9, FixedArray::kHeaderSize), r0);
+  __ Ret();
+
+  // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
+  __ bind(&double_elements);
+  __ LoadP(r8, FieldMemOperand(r4, JSObject::kElementsOffset));
+  __ StoreNumberToDoubleElements(r3, r6, r4,
+                                 // Overwrites all regs after this.
+                                 r8, r9, r10, r22, r5,
+                                 &slow_elements);
+  __ Ret();
+}
+
+
+void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
+  if (entry_hook_ != NULL) {
+    ProfileEntryHookStub stub;
+    __ mflr(r0);
+    __ push(r0);
+    __ CallStub(&stub);
+    __ pop(r0);
+    __ mtlr(r0);
+  }
+}
+
+
+void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
+  // The entry hook is a "push lr" instruction, followed by a call.
+  const int32_t kReturnAddressDistanceFromFunctionStart =
+      Assembler::kCallTargetAddressOffset + 2 * Assembler::kInstrSize;
+
+  // Save live volatile registers.
+  __ mflr(r3);
+  __ Push(r3, r30, r4);
+  const int32_t kNumSavedRegs = 3;
+
+  // Compute the function's address for the first argument.
+  __ subi(r3, r3, Operand(kReturnAddressDistanceFromFunctionStart));
+
+  // The caller's return address is above the saved temporaries.
+  // Grab that for the second argument to the hook.
+  __ addi(r4, sp, Operand(kNumSavedRegs * kPointerSize));
+
+  // Align the stack if necessary.
+  int frame_alignment = masm->ActivationFrameAlignment();
+  if (frame_alignment > kPointerSize) {
+    __ mr(r30, sp);
+    ASSERT(IsPowerOf2(frame_alignment));
+    ASSERT(-frame_alignment == -8);
+    __ ClearRightImm(sp, sp, Operand(3));
+  }
+
+#if !defined(USE_SIMULATOR)
+  __ mov(ip, Operand(reinterpret_cast<intptr_t>(&entry_hook_)));
+  __ LoadP(ip, MemOperand(ip));
+
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  // Function descriptor
+  __ LoadP(ToRegister(2), MemOperand(ip, kPointerSize));
+  __ LoadP(ip, MemOperand(ip, 0));
+#elif ABI_TOC_ADDRESSABILITY_VIA_IP
+  // ip already set.
+#endif
+
+  // PPC LINUX ABI:
+  __ addi(sp, sp, Operand(-kNumRequiredStackFrameSlots * kPointerSize));
+#else
+  // Under the simulator we need to indirect the entry hook through a
+  // trampoline function at a known address.
+  Address trampoline_address = reinterpret_cast<Address>(
+      reinterpret_cast<intptr_t>(EntryHookTrampoline));
+  ApiFunction dispatcher(trampoline_address);
+  __ mov(ip, Operand(ExternalReference(&dispatcher,
+                                       ExternalReference::BUILTIN_CALL,
+                                       masm->isolate())));
+#endif
+  __ Call(ip);
+
+// For the most part this is true only when USE_SIMULATOR is true
+// The exception is when built with nativesim=true, then we need
+// Real PPC calling support plus simulation
+#if defined(V8_HOST_ARCH_PPC64) || defined(V8_HOST_ARCH_PPC)
+  __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize));
+#endif
+
+  // Restore the stack pointer if needed.
+  if (frame_alignment > kPointerSize) {
+    __ mr(sp, r30);
+  }
+
+  __ Pop(r0, r30, r4);
+  __ mtlr(r0);
+  __ Ret();
+}
+
+#undef __
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/code-stubs-ppc.h b/src/ppc/code-stubs-ppc.h
new file mode 100644
index 0000000..0b24a73
--- /dev/null
+++ b/src/ppc/code-stubs-ppc.h
@@ -0,0 +1,884 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_CODE_STUBS_PPC_H_
+#define V8_PPC_CODE_STUBS_PPC_H_
+
+#include "ic-inl.h"
+
+namespace v8 {
+namespace internal {
+
+// Compute a transcendental math function natively, or call the
+// TranscendentalCache runtime function.
+class TranscendentalCacheStub: public CodeStub {
+ public:
+  enum ArgumentType {
+    TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits,
+    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
+  };
+
+  TranscendentalCacheStub(TranscendentalCache::Type type,
+                          ArgumentType argument_type)
+      : type_(type), argument_type_(argument_type) { }
+  void Generate(MacroAssembler* masm);
+ private:
+  TranscendentalCache::Type type_;
+  ArgumentType argument_type_;
+  void GenerateCallCFunction(MacroAssembler* masm, Register scratch);
+
+  Major MajorKey() { return TranscendentalCache; }
+  int MinorKey() { return type_ | argument_type_; }
+  Runtime::FunctionId RuntimeFunction();
+};
+
+
+class StoreBufferOverflowStub: public CodeStub {
+ public:
+  explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
+      : save_doubles_(save_fp) { }
+
+  void Generate(MacroAssembler* masm);
+
+  virtual bool IsPregenerated();
+  static void GenerateFixedRegStubsAheadOfTime();
+  virtual bool SometimesSetsUpAFrame() { return false; }
+
+ private:
+  SaveFPRegsMode save_doubles_;
+
+  Major MajorKey() { return StoreBufferOverflow; }
+  int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
+};
+
+
+class UnaryOpStub: public CodeStub {
+ public:
+  UnaryOpStub(Token::Value op,
+              UnaryOverwriteMode mode,
+              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
+      : op_(op),
+        mode_(mode),
+        operand_type_(operand_type) {
+  }
+
+ private:
+  Token::Value op_;
+  UnaryOverwriteMode mode_;
+
+  // Operand type information determined at runtime.
+  UnaryOpIC::TypeInfo operand_type_;
+
+  virtual void PrintName(StringStream* stream);
+
+  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
+  class OpBits: public BitField<Token::Value, 1, 7> {};
+  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
+
+  Major MajorKey() { return UnaryOp; }
+  int MinorKey() {
+    return ModeBits::encode(mode_)
+           | OpBits::encode(op_)
+           | OperandTypeInfoBits::encode(operand_type_);
+  }
+
+  // Note: A lot of the helper functions below will vanish when we use virtual
+  // function instead of switch more often.
+  void Generate(MacroAssembler* masm);
+
+  void GenerateTypeTransition(MacroAssembler* masm);
+
+  void GenerateSmiStub(MacroAssembler* masm);
+  void GenerateSmiStubSub(MacroAssembler* masm);
+  void GenerateSmiStubBitNot(MacroAssembler* masm);
+  void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
+  void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
+
+  void GenerateHeapNumberStub(MacroAssembler* masm);
+  void GenerateHeapNumberStubSub(MacroAssembler* masm);
+  void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
+  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
+  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
+
+  void GenerateGenericStub(MacroAssembler* masm);
+  void GenerateGenericStubSub(MacroAssembler* masm);
+  void GenerateGenericStubBitNot(MacroAssembler* masm);
+  void GenerateGenericCodeFallback(MacroAssembler* masm);
+
+  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
+
+  virtual InlineCacheState GetICState() {
+    return UnaryOpIC::ToState(operand_type_);
+  }
+
+  virtual void FinishCode(Handle<Code> code) {
+    code->set_unary_op_type(operand_type_);
+  }
+};
+
+
+class BinaryOpStub: public CodeStub {
+ public:
+  BinaryOpStub(Token::Value op, OverwriteMode mode)
+      : op_(op),
+        mode_(mode),
+        operands_type_(BinaryOpIC::UNINITIALIZED),
+        result_type_(BinaryOpIC::UNINITIALIZED) {
+    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
+  }
+
+  BinaryOpStub(
+      int key,
+      BinaryOpIC::TypeInfo operands_type,
+      BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
+      : op_(OpBits::decode(key)),
+        mode_(ModeBits::decode(key)),
+        operands_type_(operands_type),
+        result_type_(result_type) { }
+
+ private:
+  enum SmiCodeGenerateHeapNumberResults {
+    ALLOW_HEAPNUMBER_RESULTS,
+    NO_HEAPNUMBER_RESULTS
+  };
+
+  Token::Value op_;
+  OverwriteMode mode_;
+
+  // Operand type information determined at runtime.
+  BinaryOpIC::TypeInfo operands_type_;
+  BinaryOpIC::TypeInfo result_type_;
+
+  virtual void PrintName(StringStream* stream);
+
+  // Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
+  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
+  class OpBits: public BitField<Token::Value, 2, 7> {};
+  class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
+  class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
+
+  Major MajorKey() { return BinaryOp; }
+  int MinorKey() {
+    return OpBits::encode(op_)
+           | ModeBits::encode(mode_)
+           | OperandTypeInfoBits::encode(operands_type_)
+           | ResultTypeInfoBits::encode(result_type_);
+  }
+
+  void Generate(MacroAssembler* masm);
+  void GenerateGeneric(MacroAssembler* masm);
+  void GenerateSmiSmiOperation(MacroAssembler* masm);
+  void GenerateFPOperation(MacroAssembler* masm,
+                           bool smi_operands,
+                           Label* not_numbers,
+                           Label* gc_required);
+  void GenerateSmiCode(MacroAssembler* masm,
+                       Label* use_runtime,
+                       Label* gc_required,
+                       SmiCodeGenerateHeapNumberResults heapnumber_results);
+  void GenerateLoadArguments(MacroAssembler* masm);
+  void GenerateReturn(MacroAssembler* masm);
+  void GenerateUninitializedStub(MacroAssembler* masm);
+  void GenerateSmiStub(MacroAssembler* masm);
+  void GenerateInt32Stub(MacroAssembler* masm);
+  void GenerateHeapNumberStub(MacroAssembler* masm);
+  void GenerateOddballStub(MacroAssembler* masm);
+  void GenerateStringStub(MacroAssembler* masm);
+  void GenerateBothStringStub(MacroAssembler* masm);
+  void GenerateGenericStub(MacroAssembler* masm);
+  void GenerateAddStrings(MacroAssembler* masm);
+  void GenerateCallRuntime(MacroAssembler* masm);
+
+  void GenerateHeapResultAllocation(MacroAssembler* masm,
+                                    Register result,
+                                    Register heap_number_map,
+                                    Register scratch1,
+                                    Register scratch2,
+                                    Label* gc_required);
+  void GenerateRegisterArgsPush(MacroAssembler* masm);
+  void GenerateTypeTransition(MacroAssembler* masm);
+  void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
+
+  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
+
+  virtual InlineCacheState GetICState() {
+    return BinaryOpIC::ToState(operands_type_);
+  }
+
+  virtual void FinishCode(Handle<Code> code) {
+    code->set_binary_op_type(operands_type_);
+    code->set_binary_op_result_type(result_type_);
+  }
+
+  friend class CodeGenerator;
+};
+
+
+class StringHelper : public AllStatic {
+ public:
+  // Generate code for copying characters using a simple loop. This should only
+  // be used in places where the number of characters is small and the
+  // additional setup and checking in GenerateCopyCharactersLong adds too much
+  // overhead. Copying of overlapping regions is not supported.
+  // Dest register ends at the position after the last character written.
+  static void GenerateCopyCharacters(MacroAssembler* masm,
+                                     Register dest,
+                                     Register src,
+                                     Register count,
+                                     Register scratch,
+                                     bool ascii);
+
+  // Generate code for copying a large number of characters. This function
+  // is allowed to spend extra time setting up conditions to make copying
+  // faster. Copying of overlapping regions is not supported.
+  // Dest register ends at the position after the last character written.
+  static void GenerateCopyCharactersLong(MacroAssembler* masm,
+                                         Register dest,
+                                         Register src,
+                                         Register count,
+                                         Register scratch1,
+                                         Register scratch2,
+                                         Register scratch3,
+                                         Register scratch4,
+                                         Register scratch5,
+                                         int flags);
+
+
+  // Probe the symbol table for a two character string. If the string is
+  // not found by probing a jump to the label not_found is performed. This jump
+  // does not guarantee that the string is not in the symbol table. If the
+  // string is found the code falls through with the string in register r0.
+  // Contents of both c1 and c2 registers are modified. At the exit c1 is
+  // guaranteed to contain halfword with low and high bytes equal to
+  // initial contents of c1 and c2 respectively.
+  static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
+                                                   Register c1,
+                                                   Register c2,
+                                                   Register scratch1,
+                                                   Register scratch2,
+                                                   Register scratch3,
+                                                   Register scratch4,
+                                                   Register scratch5,
+                                                   Label* not_found);
+
+  // Generate string hash.
+  static void GenerateHashInit(MacroAssembler* masm,
+                               Register hash,
+                               Register character,
+                               Register scratch);
+
+  static void GenerateHashAddCharacter(MacroAssembler* masm,
+                                       Register hash,
+                                       Register character,
+                                       Register scratch);
+
+  static void GenerateHashGetHash(MacroAssembler* masm,
+                                  Register hash,
+                                  Register scratch);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
+};
+
+
+// Flag that indicates how to generate code for the stub StringAddStub.
+enum StringAddFlags {
+  NO_STRING_ADD_FLAGS = 0,
+  // Omit left string check in stub (left is definitely a string).
+  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
+  // Omit right string check in stub (right is definitely a string).
+  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
+  // Omit both string checks in stub.
+  NO_STRING_CHECK_IN_STUB =
+      NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
+};
+
+
+class StringAddStub: public CodeStub {
+ public:
+  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
+
+ private:
+  Major MajorKey() { return StringAdd; }
+  int MinorKey() { return flags_; }
+
+  void Generate(MacroAssembler* masm);
+
+  void GenerateConvertArgument(MacroAssembler* masm,
+                               int stack_offset,
+                               Register arg,
+                               Register scratch1,
+                               Register scratch2,
+                               Register scratch3,
+                               Register scratch4,
+                               Label* slow);
+
+  const StringAddFlags flags_;
+};
+
+
+class SubStringStub: public CodeStub {
+ public:
+  SubStringStub() {}
+
+ private:
+  Major MajorKey() { return SubString; }
+  int MinorKey() { return 0; }
+
+  void Generate(MacroAssembler* masm);
+};
+
+
+
+class StringCompareStub: public CodeStub {
+ public:
+  StringCompareStub() { }
+
+  // Compares two flat ASCII strings and returns result in r0.
+  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
+                                              Register left,
+                                              Register right,
+                                              Register scratch1,
+                                              Register scratch2,
+                                              Register scratch3);
+
+  // Compares two flat ASCII strings for equality and returns result
+  // in r0.
+  static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+                                            Register left,
+                                            Register right,
+                                            Register scratch1,
+                                            Register scratch2);
+
+ private:
+  virtual Major MajorKey() { return StringCompare; }
+  virtual int MinorKey() { return 0; }
+  virtual void Generate(MacroAssembler* masm);
+
+  static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
+                                            Register left,
+                                            Register right,
+                                            Register length,
+                                            Register scratch1,
+                                            Label* chars_not_equal);
+};
+
+
+class NumberToStringStub: public CodeStub {
+ public:
+  NumberToStringStub() { }
+
+  // Generate code to do a lookup in the number string cache. If the number in
+  // the register object is found in the cache the generated code falls through
+  // with the result in the result register. The object and the result register
+  // can be the same. If the number is not found in the cache the code jumps to
+  // the label not_found with only the content of register object unchanged.
+  static void GenerateLookupNumberStringCache(MacroAssembler* masm,
+                                              Register object,
+                                              Register result,
+                                              Register scratch1,
+                                              Register scratch2,
+                                              Register scratch3,
+                                              bool object_is_smi,
+                                              Label* not_found);
+
+ private:
+  Major MajorKey() { return NumberToString; }
+  int MinorKey() { return 0; }
+
+  void Generate(MacroAssembler* masm);
+};
+
+
+class RecordWriteStub: public CodeStub {
+ public:
+  RecordWriteStub(Register object,
+                  Register value,
+                  Register address,
+                  RememberedSetAction remembered_set_action,
+                  SaveFPRegsMode fp_mode)
+      : object_(object),
+        value_(value),
+        address_(address),
+        remembered_set_action_(remembered_set_action),
+        save_fp_regs_mode_(fp_mode),
+        regs_(object,   // An input reg.
+              address,  // An input reg.
+              value) {  // One scratch reg.
+  }
+
+  enum Mode {
+    STORE_BUFFER_ONLY,
+    INCREMENTAL,
+    INCREMENTAL_COMPACTION
+  };
+
+  virtual bool IsPregenerated();
+  static void GenerateFixedRegStubsAheadOfTime();
+  virtual bool SometimesSetsUpAFrame() { return false; }
+
+  static void PatchBranchIntoNop(MacroAssembler* masm, int pos) {
+    masm->instr_at_put(pos, (masm->instr_at(pos) & ~kBOfieldMask) | BT);
+    // roohack ASSERT(Assembler::IsTstImmediate(masm->instr_at(pos)));
+  }
+
+  static void PatchNopIntoBranch(MacroAssembler* masm, int pos) {
+    masm->instr_at_put(pos, (masm->instr_at(pos) & ~kBOfieldMask) | BF);
+    // roohack ASSERT(Assembler::IsBranch(masm->instr_at(pos)));
+  }
+
+  static Mode GetMode(Code* stub) {
+    Instr first_instruction = Assembler::instr_at(stub->instruction_start() +
+                                                   Assembler::kInstrSize);
+    Instr second_instruction = Assembler::instr_at(stub->instruction_start() +
+                                                   (Assembler::kInstrSize*2));
+
+    if (BF == (first_instruction & kBOfieldMask)) {
+      return INCREMENTAL;
+    }
+
+    // roohack ASSERT(Assembler::IsTstImmediate(first_instruction));
+
+    if (BF == (second_instruction & kBOfieldMask)) {
+      return INCREMENTAL_COMPACTION;
+    }
+
+    // roohack ASSERT(Assembler::IsTstImmediate(second_instruction));
+
+    return STORE_BUFFER_ONLY;
+  }
+
+  static void Patch(Code* stub, Mode mode) {
+    MacroAssembler masm(NULL,
+                        stub->instruction_start(),
+                        stub->instruction_size());
+    switch (mode) {
+      case STORE_BUFFER_ONLY:
+        ASSERT(GetMode(stub) == INCREMENTAL ||
+               GetMode(stub) == INCREMENTAL_COMPACTION);
+
+        PatchBranchIntoNop(&masm, Assembler::kInstrSize);
+        PatchBranchIntoNop(&masm, Assembler::kInstrSize*2);
+        break;
+      case INCREMENTAL:
+        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
+        PatchNopIntoBranch(&masm, Assembler::kInstrSize);
+        break;
+      case INCREMENTAL_COMPACTION:
+        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
+        PatchNopIntoBranch(&masm, Assembler::kInstrSize*2);
+        break;
+    }
+    ASSERT(GetMode(stub) == mode);
+    CPU::FlushICache(stub->instruction_start()+Assembler::kInstrSize,
+                      2 * Assembler::kInstrSize);
+  }
+
+ private:
+  // This is a helper class for freeing up 3 scratch registers.  The input is
+  // two registers that must be preserved and one scratch register provided by
+  // the caller.
+  class RegisterAllocation {
+   public:
+    RegisterAllocation(Register object,
+                       Register address,
+                       Register scratch0)
+        : object_(object),
+          address_(address),
+          scratch0_(scratch0) {
+      ASSERT(!AreAliased(scratch0, object, address, no_reg));
+      scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_);
+    }
+
+    void Save(MacroAssembler* masm) {
+      ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
+      // We don't have to save scratch0_ because it was given to us as
+      // a scratch register.
+      masm->push(scratch1_);
+    }
+
+    void Restore(MacroAssembler* masm) {
+      masm->pop(scratch1_);
+    }
+
+    // If we have to call into C then we need to save and restore all caller-
+    // saved registers that were not already preserved.  The scratch registers
+    // will be restored by other means so we don't bother pushing them here.
+    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
+      masm->mflr(r0);
+      masm->push(r0);
+      masm->MultiPush(kJSCallerSaved & ~scratch1_.bit());
+      if (mode == kSaveFPRegs) {
+        // Save all volatile VFP registers except d0.
+        const int kNumRegs = DwVfpRegister::kNumVolatileRegisters - 1;
+        masm->subi(sp, sp, Operand(kDoubleSize * kNumRegs));
+        for (int i = kNumRegs; i > 0; i--) {
+          DwVfpRegister reg = DwVfpRegister::from_code(i);
+          masm->stfd(reg, MemOperand(sp, (i - 1) * kDoubleSize));
+        }
+      }
+    }
+
+    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
+                                           SaveFPRegsMode mode) {
+      if (mode == kSaveFPRegs) {
+        // Restore all VFP registers except d0.
+        const int kNumRegs = DwVfpRegister::kNumVolatileRegisters - 1;
+        for (int i = kNumRegs; i > 0; i--) {
+          DwVfpRegister reg = DwVfpRegister::from_code(i);
+          masm->lfd(reg, MemOperand(sp, (i - 1) * kDoubleSize));
+        }
+        masm->addi(sp, sp, Operand(kDoubleSize * kNumRegs));
+      }
+      masm->MultiPop(kJSCallerSaved & ~scratch1_.bit());
+      masm->pop(r0);
+      masm->mtlr(r0);
+    }
+
+    inline Register object() { return object_; }
+    inline Register address() { return address_; }
+    inline Register scratch0() { return scratch0_; }
+    inline Register scratch1() { return scratch1_; }
+
+   private:
+    Register object_;
+    Register address_;
+    Register scratch0_;
+    Register scratch1_;
+
+    Register GetRegThatIsNotOneOf(Register r1,
+                                  Register r2,
+                                  Register r3) {
+      for (int i = 0; i < Register::kNumAllocatableRegisters; i++) {
+        Register candidate = Register::FromAllocationIndex(i);
+        if (candidate.is(r1)) continue;
+        if (candidate.is(r2)) continue;
+        if (candidate.is(r3)) continue;
+        return candidate;
+      }
+      UNREACHABLE();
+      return no_reg;
+    }
+    friend class RecordWriteStub;
+  };
+
+  enum OnNoNeedToInformIncrementalMarker {
+    kReturnOnNoNeedToInformIncrementalMarker,
+    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
+  };
+
+  void Generate(MacroAssembler* masm);
+  void GenerateIncremental(MacroAssembler* masm, Mode mode);
+  void CheckNeedsToInformIncrementalMarker(
+      MacroAssembler* masm,
+      OnNoNeedToInformIncrementalMarker on_no_need,
+      Mode mode);
+  void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
+
+  Major MajorKey() { return RecordWrite; }
+
+  int MinorKey() {
+    return ObjectBits::encode(object_.code()) |
+        ValueBits::encode(value_.code()) |
+        AddressBits::encode(address_.code()) |
+        RememberedSetActionBits::encode(remembered_set_action_) |
+        SaveFPRegsModeBits::encode(save_fp_regs_mode_);
+  }
+
+  void Activate(Code* code) {
+    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
+  }
+
+  class ObjectBits: public BitField<int, 0, 5> {};
+  class ValueBits: public BitField<int, 5, 5> {};
+  class AddressBits: public BitField<int, 10, 5> {};
+  class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {};
+  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {};
+
+  Register object_;
+  Register value_;
+  Register address_;
+  RememberedSetAction remembered_set_action_;
+  SaveFPRegsMode save_fp_regs_mode_;
+  Label slow_;
+  RegisterAllocation regs_;
+};
+
+
+// Enter C code from generated RegExp code in a way that allows
+// the C code to fix the return address in case of a GC.
+class RegExpCEntryStub: public CodeStub {
+ public:
+  RegExpCEntryStub() {}
+  virtual ~RegExpCEntryStub() {}
+  void Generate(MacroAssembler* masm);
+
+ private:
+  Major MajorKey() { return RegExpCEntry; }
+  int MinorKey() { return 0; }
+
+  bool NeedsImmovableCode() { return true; }
+};
+
+
+// Trampoline stub to call into native code. To call safely into native code
+// in the presence of compacting GC (which can move code objects) we need to
+// keep the code which called into native pinned in the memory. Currently the
+// simplest approach is to generate such stub early enough so it can never be
+// moved by GC
+class DirectCEntryStub: public CodeStub {
+ public:
+  DirectCEntryStub() {}
+  void Generate(MacroAssembler* masm);
+  void GenerateCall(MacroAssembler* masm, ExternalReference function);
+  void GenerateCall(MacroAssembler* masm, Register target);
+
+ private:
+  Major MajorKey() { return DirectCEntry; }
+  int MinorKey() { return 0; }
+
+  bool NeedsImmovableCode() { return true; }
+};
+
+
+class FloatingPointHelper : public AllStatic {
+ public:
+  enum Destination {
+    kFPRegisters,
+    kCoreRegisters
+  };
+
+
+  // Loads smis from r0 and r1 (right and left in binary operations) into
+  // floating point registers. Depending on the destination the values ends up
+  // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is
+  // floating point registers VFP3 must be supported. If core registers are
+  // requested when VFP3 is supported d6 and d7 will be scratched.
+  static void LoadSmis(MacroAssembler* masm,
+                       Register scratch1,
+                       Register scratch2);
+
+  // Loads objects from r0 and r1 (right and left in binary operations) into
+  // floating point registers. Depending on the destination the values ends up
+  // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is
+  // floating point registers VFP3 must be supported. If core registers are
+  // requested when VFP3 is supported d6 and d7 will still be scratched. If
+  // either r0 or r1 is not a number (not smi and not heap number object) the
+  // not_number label is jumped to with r0 and r1 intact.
+  static void LoadOperands(MacroAssembler* masm,
+                           Register heap_number_map,
+                           Register scratch1,
+                           Register scratch2,
+                           Label* not_number);
+
+  // Convert the smi or heap number in object to an int32 using the rules
+  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
+  // and brought into the range -2^31 .. +2^31 - 1.
+  static void ConvertNumberToInt32(MacroAssembler* masm,
+                                   Register object,
+                                   Register dst,
+                                   Register heap_number_map,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Register scratch3,
+                                   DwVfpRegister double_scratch,
+                                   Label* not_int32);
+
+  // Converts the integer (untagged smi) in |src| to a double, storing
+  // the result to |double_dst|
+  static void ConvertIntToDouble(MacroAssembler* masm,
+                                 Register src,
+                                 DwVfpRegister double_dst);
+
+  // Converts the unsigned integer (untagged smi) in |src| to
+  // a double, storing the result to |double_dst|
+  static void ConvertUnsignedIntToDouble(MacroAssembler* masm,
+                                         Register src,
+                                         DwVfpRegister double_dst);
+
+  // Converts the integer (untagged smi) in |src| to
+  // a float, storing the result in |dst|
+  // Warning: The value in |int_scrach| will be changed in the process!
+  static void ConvertIntToFloat(MacroAssembler* masm,
+                                const DwVfpRegister dst,
+                                const Register src,
+                                const Register int_scratch);
+
+  /*
+  // Converts the double in |double_value| to an integer, storing the
+  // result in |int_dst|.
+  // Warning: The value in |double_value| will be changed in the process!
+  static void ConvertDoubleToInt(MacroAssembler* masm,
+                                 DwVfpRegister double_value,
+                                 Register int_dst,
+                                 Register scratch1,
+                                 DwVfpRegister double_scratch);
+
+  // Converts the double in |double_value| to an unsigned integer,
+  // storing the result in |int_dst|.
+  // Warning: The value in |double_value| will be changed in the process!
+  static void ConvertDoubleToUnsignedInt(MacroAssembler* masm,
+                                         DwVfpRegister double_value,
+                                         Register int_dst,
+                                         Register scratch1,
+                                         DwVfpRegister double_scratch);
+  */
+
+  // Load the number from object into double_dst in the double format.
+  // Control will jump to not_int32 if the value cannot be exactly represented
+  // by a 32-bit integer.
+  // Floating point value in the 32-bit integer range that are not exact integer
+  // won't be loaded.
+  static void LoadNumberAsInt32Double(MacroAssembler* masm,
+                                      Register object,
+                                      DwVfpRegister double_dst,
+                                      DwVfpRegister double_scratch,
+                                      Register heap_number_map,
+                                      Register scratch1,
+                                      Register scratch2,
+                                      Label* not_int32);
+
+  // Loads the number from object into dst as a 32-bit integer.
+  // Control will jump to not_int32 if the object cannot be exactly represented
+  // by a 32-bit integer.
+  // Floating point value in the 32-bit integer range that are not exact integer
+  // won't be converted.
+  // scratch3 is not used when VFP3 is supported.
+  static void LoadNumberAsInt32(MacroAssembler* masm,
+                                Register object,
+                                Register dst,
+                                Register heap_number_map,
+                                Register scratch1,
+                                Register scratch2,
+                                Register scratch3,
+                                DwVfpRegister double_scratch0,
+                                DwVfpRegister double_scratch1,
+                                Label* not_int32);
+
+  // Generate non VFP3 code to check if a double can be exactly represented by a
+  // 32-bit integer. This does not check for 0 or -0, which need
+  // to be checked for separately.
+  // Control jumps to not_int32 if the value is not a 32-bit integer, and falls
+  // through otherwise.
+  // src1 and src2 will be cloberred.
+  //
+  // Expected input:
+  // - src1: higher (exponent) part of the double value.
+  // - src2: lower (mantissa) part of the double value.
+  // Output status:
+  // - dst: 32 higher bits of the mantissa. (mantissa[51:20])
+  // - src2: contains 1.
+  // - other registers are clobbered.
+  static void DoubleIs32BitInteger(MacroAssembler* masm,
+                                   Register src1,
+                                   Register src2,
+                                   Register dst,
+                                   Register scratch,
+                                   Label* not_int32);
+
+  // Generates code to call a C function to do a double operation using core
+  // registers. (Used when VFP3 is not supported.)
+  // This code never falls through, but returns with a heap number containing
+  // the result in r0.
+  // Register heapnumber_result must be a heap number in which the
+  // result of the operation will be stored.
+  // Requires the following layout on entry:
+  // r0: Left value (least significant part of mantissa).
+  // r1: Left value (sign, exponent, top of mantissa).
+  // r2: Right value (least significant part of mantissa).
+  // r3: Right value (sign, exponent, top of mantissa).
+  static void CallCCodeForDoubleOperation(MacroAssembler* masm,
+                                          Token::Value op,
+                                          Register heap_number_result,
+                                          Register scratch);
+
+ private:
+  static void LoadNumber(MacroAssembler* masm,
+                         Register object,
+                         DwVfpRegister dst,
+                         Register heap_number_map,
+                         Register scratch1,
+                         Register scratch2,
+                         Label* not_number);
+};
+
+
+class StringDictionaryLookupStub: public CodeStub {
+ public:
+  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
+
+  explicit StringDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
+
+  void Generate(MacroAssembler* masm);
+
+  static void GenerateNegativeLookup(MacroAssembler* masm,
+                                     Label* miss,
+                                     Label* done,
+                                     Register receiver,
+                                     Register properties,
+                                     Handle<String> name,
+                                     Register scratch0);
+
+  static void GeneratePositiveLookup(MacroAssembler* masm,
+                                     Label* miss,
+                                     Label* done,
+                                     Register elements,
+                                     Register name,
+                                     Register r0,
+                                     Register r1);
+
+  virtual bool SometimesSetsUpAFrame() { return false; }
+
+ private:
+  static const int kInlinedProbes = 4;
+  static const int kTotalProbes = 20;
+
+  static const int kCapacityOffset =
+      StringDictionary::kHeaderSize +
+      StringDictionary::kCapacityIndex * kPointerSize;
+
+  static const int kElementsStartOffset =
+      StringDictionary::kHeaderSize +
+      StringDictionary::kElementsStartIndex * kPointerSize;
+
+  Major MajorKey() { return StringDictionaryLookup; }
+
+  int MinorKey() {
+    return LookupModeBits::encode(mode_);
+  }
+
+  class LookupModeBits: public BitField<LookupMode, 0, 1> {};
+
+  LookupMode mode_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_CODE_STUBS_PPC_H_
diff --git a/src/ppc/codegen-ppc.cc b/src/ppc/codegen-ppc.cc
new file mode 100644
index 0000000..47092df
--- /dev/null
+++ b/src/ppc/codegen-ppc.cc
@@ -0,0 +1,492 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "codegen.h"
+#include "macro-assembler.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm)
+
+UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) {
+  switch (type) {
+    case TranscendentalCache::SIN: return &sin;
+    case TranscendentalCache::COS: return &cos;
+    case TranscendentalCache::TAN: return &tan;
+    case TranscendentalCache::LOG: return &log;
+    default: UNIMPLEMENTED();
+  }
+  return NULL;
+}
+
+
+UnaryMathFunction CreateSqrtFunction() {
+  return &sqrt;
+}
+
+// -------------------------------------------------------------------------
+// Platform-specific RuntimeCallHelper functions.
+
+void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
+  masm->EnterFrame(StackFrame::INTERNAL);
+  ASSERT(!masm->has_frame());
+  masm->set_has_frame(true);
+}
+
+
+void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
+  masm->LeaveFrame(StackFrame::INTERNAL);
+  ASSERT(masm->has_frame());
+  masm->set_has_frame(false);
+}
+
+
+// -------------------------------------------------------------------------
+// Code generators
+
+void ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
+    MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : key
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  //  -- r6    : target map, scratch for subsequent call
+  //  -- r7    : scratch (elements)
+  // -----------------------------------
+  // Set transitioned map.
+  __ StoreP(r6, FieldMemOperand(r5, HeapObject::kMapOffset), r0);
+  __ RecordWriteField(r5,
+                      HeapObject::kMapOffset,
+                      r6,
+                      r22,
+                      kLRHasNotBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+}
+
+
+void ElementsTransitionGenerator::GenerateSmiToDouble(
+    MacroAssembler* masm, Label* fail) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : key
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  //  -- r6    : target map, scratch for subsequent call
+  //  -- r7    : scratch (elements)
+  // -----------------------------------
+  Label loop, entry, convert_hole, gc_required, only_change_map, done;
+
+  // Check for empty arrays, which only require a map transition and no changes
+  // to the backing store.
+  __ LoadP(r7, FieldMemOperand(r5, JSObject::kElementsOffset));
+  __ CompareRoot(r7, Heap::kEmptyFixedArrayRootIndex);
+  __ beq(&only_change_map);
+
+  // Preserve lr and use r30 as a temporary register.
+  __ mflr(r0);
+  __ Push(r0, r30);
+
+  __ LoadP(r8, FieldMemOperand(r7, FixedArray::kLengthOffset));
+  // r7: source FixedArray
+  // r8: number of elements (smi-tagged)
+
+  // Allocate new FixedDoubleArray.
+  __ SmiToDoubleArrayOffset(r30, r8);
+  __ addi(r30, r30, Operand(FixedDoubleArray::kHeaderSize + kPointerSize));
+  __ AllocateInNewSpace(r30, r9, r10, r22, &gc_required, NO_ALLOCATION_FLAGS);
+  // r9: destination FixedDoubleArray, not tagged as heap object.
+
+  // Align the array conveniently for doubles.
+  // Store a filler value in the unused memory.
+  Label aligned, aligned_done;
+  __ andi(r0, r9, Operand(kDoubleAlignmentMask));
+  __ mov(ip, Operand(masm->isolate()->factory()->one_pointer_filler_map()));
+  __ beq(&aligned, cr0);
+  // Store at the beginning of the allocated memory and update the base pointer.
+  __ StoreP(ip, MemOperand(r9));
+  __ addi(r9, r9, Operand(kPointerSize));
+  __ b(&aligned_done);
+
+  __ bind(&aligned);
+  // Store the filler at the end of the allocated memory.
+  __ subi(r30, r30, Operand(kPointerSize));
+  __ StorePX(ip, MemOperand(r9, r30));
+
+  __ bind(&aligned_done);
+
+  // Set destination FixedDoubleArray's length and map.
+  __ LoadRoot(r22, Heap::kFixedDoubleArrayMapRootIndex);
+  __ StoreP(r8, MemOperand(r9, FixedDoubleArray::kLengthOffset));
+  // Update receiver's map.
+  __ StoreP(r22, MemOperand(r9, HeapObject::kMapOffset));
+
+  __ StoreP(r6, FieldMemOperand(r5, HeapObject::kMapOffset), r0);
+  __ RecordWriteField(r5,
+                      HeapObject::kMapOffset,
+                      r6,
+                      r22,
+                      kLRHasBeenSaved,
+                      kDontSaveFPRegs,
+                      OMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  // Replace receiver's backing store with newly created FixedDoubleArray.
+  __ addi(r6, r9, Operand(kHeapObjectTag));
+  __ StoreP(r6, FieldMemOperand(r5, JSObject::kElementsOffset), r0);
+  __ RecordWriteField(r5,
+                      JSObject::kElementsOffset,
+                      r6,
+                      r22,
+                      kLRHasBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+
+  // Prepare for conversion loop.
+  __ addi(r6, r7, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ addi(r10, r9, Operand(FixedDoubleArray::kHeaderSize));
+  __ SmiToDoubleArrayOffset(r9, r8);
+  __ add(r9, r10, r9);
+#if V8_TARGET_ARCH_PPC64
+  __ mov(r7, Operand(kHoleNanInt64));
+#else
+  __ mov(r7, Operand(kHoleNanLower32));
+  __ mov(r8, Operand(kHoleNanUpper32));
+#endif
+  // r6: begin of source FixedArray element fields, not tagged
+  // r7: kHoleNanLower32
+  // r8: kHoleNanUpper32
+  // r9: end of destination FixedDoubleArray, not tagged
+  // r10: begin of FixedDoubleArray element fields, not tagged
+
+  __ b(&entry);
+
+  __ bind(&only_change_map);
+  __ StoreP(r6, FieldMemOperand(r5, HeapObject::kMapOffset), r0);
+  __ RecordWriteField(r5,
+                      HeapObject::kMapOffset,
+                      r6,
+                      r22,
+                      kLRHasBeenSaved,
+                      kDontSaveFPRegs,
+                      OMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ b(&done);
+
+  // Call into runtime if GC is required.
+  __ bind(&gc_required);
+  __ Pop(r0, r30);
+  __ mtlr(r0);
+  __ b(fail);
+
+  // Convert and copy elements.
+  __ bind(&loop);
+  __ LoadP(r22, MemOperand(r6));
+  __ addi(r6, r6, Operand(kPointerSize));
+  // r22: current element
+  __ UntagAndJumpIfNotSmi(r22, r22, &convert_hole);
+
+  // Normal smi, convert to double and store.
+  FloatingPointHelper::ConvertIntToDouble(
+    masm, r22, d0);
+  __ stfd(d0, MemOperand(r10, 0));
+  __ addi(r10, r10, Operand(8));
+
+  __ b(&entry);
+
+  // Hole found, store the-hole NaN.
+  __ bind(&convert_hole);
+  if (FLAG_debug_code) {
+    // Restore a "smi-untagged" heap object.
+    __ LoadP(r22, MemOperand(r6, -kPointerSize));
+    __ CompareRoot(r22, Heap::kTheHoleValueRootIndex);
+    __ Assert(eq, "object found in smi-only array");
+  }
+#if V8_TARGET_ARCH_PPC64
+  __ std(r7, MemOperand(r10, 0));
+#else
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ stw(r7, MemOperand(r10, 0));
+  __ stw(r8, MemOperand(r10, 4));
+#else
+  __ stw(r8, MemOperand(r10, 0));
+  __ stw(r7, MemOperand(r10, 4));
+#endif
+#endif
+  __ addi(r10, r10, Operand(8));
+
+  __ bind(&entry);
+  __ cmp(r10, r9);
+  __ blt(&loop);
+
+  __ Pop(r0, r30);
+  __ mtlr(r0);
+  __ bind(&done);
+}
+
+
+void ElementsTransitionGenerator::GenerateDoubleToObject(
+    MacroAssembler* masm, Label* fail) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : key
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  //  -- r6    : target map, scratch for subsequent call
+  //  -- r7    : scratch (elements)
+  // -----------------------------------
+  Label entry, loop, convert_hole, gc_required, only_change_map;
+
+  // Check for empty arrays, which only require a map transition and no changes
+  // to the backing store.
+  __ LoadP(r7, FieldMemOperand(r5, JSObject::kElementsOffset));
+  __ CompareRoot(r7, Heap::kEmptyFixedArrayRootIndex);
+  __ beq(&only_change_map);
+
+  __ Push(r6, r5, r4, r3);
+  __ LoadP(r8, FieldMemOperand(r7, FixedArray::kLengthOffset));
+  // r7: source FixedDoubleArray
+  // r8: number of elements (smi-tagged)
+
+  // Allocate new FixedArray.
+  __ li(r3, Operand(FixedDoubleArray::kHeaderSize));
+  __ SmiToPtrArrayOffset(r0, r8);
+  __ add(r3, r3, r0);
+  __ AllocateInNewSpace(r3, r9, r10, r22, &gc_required, NO_ALLOCATION_FLAGS);
+  // r9: destination FixedArray, not tagged as heap object
+  // Set destination FixedDoubleArray's length and map.
+  __ LoadRoot(r22, Heap::kFixedArrayMapRootIndex);
+  __ StoreP(r8, MemOperand(r9, FixedDoubleArray::kLengthOffset));
+  __ StoreP(r22, MemOperand(r9, HeapObject::kMapOffset));
+
+  // Prepare for conversion loop.
+  __ addi(r7, r7, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+  __ addi(r6, r9, Operand(FixedArray::kHeaderSize));
+  __ addi(r9, r9, Operand(kHeapObjectTag));
+  __ SmiToPtrArrayOffset(r8, r8);
+  __ add(r8, r6, r8);
+  __ LoadRoot(r10, Heap::kTheHoleValueRootIndex);
+  __ LoadRoot(r22, Heap::kHeapNumberMapRootIndex);
+  // Using offsetted addresses in r7 to fully take advantage of post-indexing.
+  // r6: begin of destination FixedArray element fields, not tagged
+  // r7: begin of source FixedDoubleArray element fields, not tagged
+  // r8: end of destination FixedArray, not tagged
+  // r9: destination FixedArray
+  // r10: the-hole pointer
+  // r22: heap number map
+  __ b(&entry);
+
+  // Call into runtime if GC is required.
+  __ bind(&gc_required);
+  __ Pop(r6, r5, r4, r3);
+  __ b(fail);
+
+  __ bind(&loop);
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ lwz(r4, MemOperand(r7, 4));
+#else
+  __ lwz(r4, MemOperand(r7));
+#endif
+  __ addi(r7, r7, Operand(8));
+  // r4: current element's upper 32 bit
+  // r7: address of next element's upper 32 bit
+  __ Cmpi(r4, Operand(kHoleNanUpper32), r0);
+  __ beq(&convert_hole);
+
+  // Non-hole double, copy value into a heap number.
+  __ AllocateHeapNumber(r5, r3, r4, r22, &gc_required);
+  // r5: new heap number
+#if V8_TARGET_ARCH_PPC64
+  __ ld(r3, MemOperand(r7, -8));
+  __ addi(r4, r5, Operand(-1));  // subtract tag for std
+  __ std(r3, MemOperand(r4, HeapNumber::kValueOffset));
+#else
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ lwz(r3, MemOperand(r7, -8));
+  __ lwz(r4, MemOperand(r7, -4));
+  __ stw(r3, FieldMemOperand(r5, HeapNumber::kValueOffset));
+  __ stw(r4, FieldMemOperand(r5, HeapNumber::kValueOffset+4));
+#else
+  __ lwz(r3, MemOperand(r7, -4));
+  __ lwz(r4, MemOperand(r7, -8));
+  __ stw(r3, FieldMemOperand(r5, HeapNumber::kValueOffset+4));
+  __ stw(r4, FieldMemOperand(r5, HeapNumber::kValueOffset));
+#endif
+#endif
+  __ mr(r3, r6);
+  __ StoreP(r5, MemOperand(r6));
+  __ addi(r6, r6, Operand(kPointerSize));
+  __ RecordWrite(r9,
+                 r3,
+                 r5,
+                 kLRHasNotBeenSaved,
+                 kDontSaveFPRegs,
+                 EMIT_REMEMBERED_SET,
+                 OMIT_SMI_CHECK);
+  __ b(&entry);
+
+  // Replace the-hole NaN with the-hole pointer.
+  __ bind(&convert_hole);
+  __ StoreP(r10, MemOperand(r6));
+  __ addi(r6, r6, Operand(kPointerSize));
+
+  __ bind(&entry);
+  __ cmpl(r6, r8);
+  __ blt(&loop);
+
+  __ Pop(r6, r5, r4, r3);
+  // Replace receiver's backing store with newly created and filled FixedArray.
+  __ StoreP(r9, FieldMemOperand(r5, JSObject::kElementsOffset), r0);
+  __ RecordWriteField(r5,
+                      JSObject::kElementsOffset,
+                      r9,
+                      r22,
+                      kLRHasNotBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+
+  __ bind(&only_change_map);
+  // Update receiver's map.
+  __ StoreP(r6, FieldMemOperand(r5, HeapObject::kMapOffset), r0);
+  __ RecordWriteField(r5,
+                      HeapObject::kMapOffset,
+                      r6,
+                      r22,
+                      kLRHasNotBeenSaved,
+                      kDontSaveFPRegs,
+                      OMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+}
+
+
+// roohack - assume ip can be used as a scratch register below
+void StringCharLoadGenerator::Generate(MacroAssembler* masm,
+                                       Register string,
+                                       Register index,
+                                       Register result,
+                                       Label* call_runtime) {
+  // Fetch the instance type of the receiver into result register.
+  __ LoadP(result, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ lbz(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
+
+  // We need special handling for indirect strings.
+  Label check_sequential;
+  __ andi(r0, result, Operand(kIsIndirectStringMask));
+  __ beq(&check_sequential, cr0);
+
+  // Dispatch on the indirect string shape: slice or cons.
+  Label cons_string;
+  __ mov(ip, Operand(kSlicedNotConsMask));
+  __ and_(r0, result, ip, SetRC);
+  __ beq(&cons_string, cr0);
+
+  // Handle slices.
+  Label indirect_string_loaded;
+  __ LoadP(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
+  __ LoadP(string, FieldMemOperand(string, SlicedString::kParentOffset));
+  __ SmiUntag(ip, result);
+  __ add(index, index, ip);
+  __ b(&indirect_string_loaded);
+
+  // Handle cons strings.
+  // Check whether the right hand side is the empty string (i.e. if
+  // this is really a flat string in a cons string). If that is not
+  // the case we would rather go to the runtime system now to flatten
+  // the string.
+  __ bind(&cons_string);
+  __ LoadP(result, FieldMemOperand(string, ConsString::kSecondOffset));
+  __ CompareRoot(result, Heap::kEmptyStringRootIndex);
+  __ bne(call_runtime);
+  // Get the first of the two strings and load its instance type.
+  __ LoadP(string, FieldMemOperand(string, ConsString::kFirstOffset));
+
+  __ bind(&indirect_string_loaded);
+  __ LoadP(result, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ lbz(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
+
+  // Distinguish sequential and external strings. Only these two string
+  // representations can reach here (slices and flat cons strings have been
+  // reduced to the underlying sequential or external string).
+  Label external_string, check_encoding;
+  __ bind(&check_sequential);
+  STATIC_ASSERT(kSeqStringTag == 0);
+  __ andi(r0, result, Operand(kStringRepresentationMask));
+  __ bne(&external_string, cr0);
+
+  // Prepare sequential strings
+  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
+  __ addi(string,
+          string,
+          Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+  __ b(&check_encoding);
+
+  // Handle external strings.
+  __ bind(&external_string);
+  if (FLAG_debug_code) {
+    // Assert that we do not have a cons or slice (indirect strings) here.
+    // Sequential strings have already been ruled out.
+    __ andi(r0, result, Operand(kIsIndirectStringMask));
+    __ Assert(eq, "external string expected, but not found", cr0);
+  }
+  // Rule out short external strings.
+  STATIC_CHECK(kShortExternalStringTag != 0);
+  __ andi(r0, result, Operand(kShortExternalStringMask));
+  __ bne(call_runtime, cr0);
+  __ LoadP(string,
+           FieldMemOperand(string, ExternalString::kResourceDataOffset));
+
+  Label ascii, done;
+  __ bind(&check_encoding);
+  STATIC_ASSERT(kTwoByteStringTag == 0);
+  __ andi(r0, result, Operand(kStringEncodingMask));
+  __ bne(&ascii, cr0);
+  // Two-byte string.
+  __ ShiftLeftImm(result, index, Operand(1));
+  __ lhzx(result, MemOperand(string, result));
+  __ b(&done);
+  __ bind(&ascii);
+  // Ascii string.
+  __ lbzx(result, MemOperand(string, index));
+  __ bind(&done);
+}
+
+#undef __
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/codegen-ppc.h b/src/ppc/codegen-ppc.h
new file mode 100644
index 0000000..379966c
--- /dev/null
+++ b/src/ppc/codegen-ppc.h
@@ -0,0 +1,96 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_CODEGEN_PPC_H_
+#define V8_PPC_CODEGEN_PPC_H_
+
+#include "ast.h"
+#include "ic-inl.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations
+class CompilationInfo;
+
+enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
+
+// -------------------------------------------------------------------------
+// CodeGenerator
+
+class CodeGenerator: public AstVisitor {
+ public:
+  static bool MakeCode(CompilationInfo* info);
+
+  // Printing of AST, etc. as requested by flags.
+  static void MakeCodePrologue(CompilationInfo* info);
+
+  // Allocate and install the code.
+  static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
+                                       Code::Flags flags,
+                                       CompilationInfo* info);
+
+  // Print the code after compiling it.
+  static void PrintCode(Handle<Code> code, CompilationInfo* info);
+
+  static bool ShouldGenerateLog(Expression* type);
+
+  static void SetFunctionInfo(Handle<JSFunction> fun,
+                              FunctionLiteral* lit,
+                              bool is_toplevel,
+                              Handle<Script> script);
+
+  static bool RecordPositions(MacroAssembler* masm,
+                              int pos,
+                              bool right_here = false);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
+};
+
+
+class StringCharLoadGenerator : public AllStatic {
+ public:
+  // Generates the code for handling different string types and loading the
+  // indexed character into |result|.  We expect |index| as untagged input and
+  // |result| as untagged output.
+  static void Generate(MacroAssembler* masm,
+                       Register string,
+                       Register index,
+                       Register result,
+                       Label* call_runtime);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_CODEGEN_PPC_H_
diff --git a/src/ppc/constants-ppc.cc b/src/ppc/constants-ppc.cc
new file mode 100644
index 0000000..2080dd8
--- /dev/null
+++ b/src/ppc/constants-ppc.cc
@@ -0,0 +1,122 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "constants-ppc.h"
+
+
+namespace v8 {
+namespace internal {
+
+// These register names are defined in a way to match the native disassembler
+// formatting. See for example the command "objdump -d <binary file>".
+const char* Registers::names_[kNumRegisters] = {
+  "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7",
+  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+  "r16", "r17", "r18", "r19", "r20", "r21", "r22",
+  "r23", "r24", "r25", "r26", "r27", "r28", "r29",
+  "r30", "fp"
+};
+
+
+// List of alias names which can be used when referring to PPC registers.
+const Registers::RegisterAlias Registers::aliases_[] = {
+  {10, "sl"},
+  {11, "r11"},
+  {12, "r12"},
+  {13, "r13"},
+  {14, "r14"},
+  {15, "r15"},
+  {kNoRegister, NULL}
+};
+
+
+const char* Registers::Name(int reg) {
+  const char* result;
+  if ((0 <= reg) && (reg < kNumRegisters)) {
+    result = names_[reg];
+  } else {
+    result = "noreg";
+  }
+  return result;
+}
+
+// Power
+const char* FPRegisters::names_[kNumFPRegisters] = {
+    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+    "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
+    "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+    "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
+};
+const char* FPRegisters::Name(int reg) {
+  ASSERT((0 <= reg) && (reg < kNumFPRegisters));
+  return names_[reg];
+}
+int FPRegisters::Number(const char* name) {
+  for (int i = 0; i < kNumFPRegisters; i++) {
+    if (strcmp(names_[i], name) == 0) {
+        return i;
+    }
+  }
+
+  // No register with the requested name found.
+  return kNoRegister;
+}
+
+// end of Power
+
+int Registers::Number(const char* name) {
+  // Look through the canonical names.
+  for (int i = 0; i < kNumRegisters; i++) {
+    if (strcmp(names_[i], name) == 0) {
+      return i;
+    }
+  }
+
+  // Look through the alias names.
+  int i = 0;
+  while (aliases_[i].reg != kNoRegister) {
+    if (strcmp(aliases_[i].name, name) == 0) {
+      return aliases_[i].reg;
+    }
+    i++;
+  }
+
+  // No register with the requested name found.
+  return kNoRegister;
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/constants-ppc.h b/src/ppc/constants-ppc.h
new file mode 100644
index 0000000..4be5563
--- /dev/null
+++ b/src/ppc/constants-ppc.h
@@ -0,0 +1,637 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_CONSTANTS_PPC_H_
+#define V8_PPC_CONSTANTS_PPC_H_
+
+namespace v8 {
+namespace internal {
+
+// Number of registers
+const int kNumRegisters = 32;
+
+// FP support.
+const int kNumFPDoubleRegisters = 32;
+const int kNumFPRegisters = kNumFPDoubleRegisters;
+
+const int kNoRegister = -1;
+
+// For FlushICache
+// This constant will be different for other versions of PowerPC
+// It must be a power of 2
+const unsigned int kCacheLineSizeLog2 = 7;
+const unsigned int kCacheLineSize = (1 << kCacheLineSizeLog2);
+
+// sign-extend the least significant 16-bit of value <imm>
+#define SIGN_EXT_IMM16(imm) ((static_cast<int>(imm) << 16) >> 16)
+
+// -----------------------------------------------------------------------------
+// Conditions.
+
+// Defines constants and accessor classes to assemble, disassemble and
+// simulate PPC instructions.
+//
+// Section references in the code refer to the "PowerPC Microprocessor
+// Family: The Programmer.s Reference Guide" from 10/95
+// https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600741775/$file/prg.pdf
+//
+
+// Constants for specific fields are defined in their respective named enums.
+// General constants are in an anonymous enum in class Instr.
+enum Condition {
+  kNoCondition = -1,
+  eq         =  0,         // Equal.
+  ne         =  1,         // Not equal.
+  ge         =  2,         // Greater or equal.
+  lt         =  3,         // Less than.
+  gt         =  4,         // Greater than.
+  le         =  5,         // Less then or equal
+  unordered  =  6,         // Floating-point unordered
+  ordered    =  7,
+  overflow   =  8,         // Summary overflow
+  nooverflow =  9,
+  al         = 10          // Always.
+};
+
+
+inline Condition NegateCondition(Condition cond) {
+  ASSERT(cond != al);
+  return static_cast<Condition>(cond ^ ne);
+}
+
+
+// Corresponds to transposing the operands of a comparison.
+inline Condition ReverseCondition(Condition cond) {
+  switch (cond) {
+    case lt:
+      return gt;
+    case gt:
+      return lt;
+    case ge:
+      return le;
+    case le:
+      return ge;
+    default:
+      return cond;
+  };
+}
+
+// -----------------------------------------------------------------------------
+// Instructions encoding.
+
+// Instr is merely used by the Assembler to distinguish 32bit integers
+// representing instructions from usual 32 bit values.
+// Instruction objects are pointers to 32bit values, and provide methods to
+// access the various ISA fields.
+typedef int32_t Instr;
+
+// Opcodes as defined in section 4.2 table 34 (32bit PowerPC)
+enum Opcode {
+  TWI     =  3 << 26,  // Trap Word Immediate
+  MULLI   =  7 << 26,  // Multiply Low Immediate
+  SUBFIC  =  8 << 26,  // Subtract from Immediate Carrying
+  CMPLI   = 10 << 26,  // Compare Logical Immediate
+  CMPI    = 11 << 26,  // Compare Immediate
+  ADDIC   = 12 << 26,  // Add Immediate Carrying
+  ADDICx  = 13 << 26,  // Add Immediate Carrying and Record
+  ADDI    = 14 << 26,  // Add Immediate
+  ADDIS   = 15 << 26,  // Add Immediate Shifted
+  BCX     = 16 << 26,  // Branch Conditional
+  SC      = 17 << 26,  // System Call
+  BX      = 18 << 26,  // Branch
+  EXT1    = 19 << 26,  // Extended code set 1
+  RLWIMIX = 20 << 26,  // Rotate Left Word Immediate then Mask Insert
+  RLWINMX = 21 << 26,  // Rotate Left Word Immediate then AND with Mask
+  RLWNMX  = 23 << 26,  // Rotate Left then AND with Mask
+  ORI     = 24 << 26,  // OR Immediate
+  ORIS    = 25 << 26,  // OR Immediate Shifted
+  XORI    = 26 << 26,  // XOR Immediate
+  XORIS   = 27 << 26,  // XOR Immediate Shifted
+  ANDIx   = 28 << 26,  // AND Immediate
+  ANDISx  = 29 << 26,  // AND Immediate Shifted
+  EXT5    = 30 << 26,  // Extended code set 5 - 64bit only
+  EXT2    = 31 << 26,  // Extended code set 2
+  LWZ     = 32 << 26,  // Load Word and Zero
+  LWZU    = 33 << 26,  // Load Word with Zero Update
+  LBZ     = 34 << 26,  // Load Byte and Zero
+  LBZU    = 35 << 26,  // Load Byte and Zero with Update
+  STW     = 36 << 26,  // Store
+  STWU    = 37 << 26,  // Store Word with Update
+  STB     = 38 << 26,  // Store Byte
+  STBU    = 39 << 26,  // Store Byte with Update
+  LHZ     = 40 << 26,  // Load Half and Zero
+  LHZU    = 41 << 26,  // Load Half and Zero with Update
+  LHA     = 42 << 26,  // Load Half Algebraic
+  LHAU    = 43 << 26,  // Load Half Algebraic with Update
+  STH     = 44 << 26,  // Store Half
+  STHU    = 45 << 26,  // Store Half with Update
+  LMW     = 46 << 26,  // Load Multiple Word
+  STMW    = 47 << 26,  // Store Multiple Word
+  LFS     = 48 << 26,  // Load Floating-Point Single
+  LFSU    = 49 << 26,  // Load Floating-Point Single with Update
+  LFD     = 50 << 26,  // Load Floating-Point Double
+  LFDU    = 51 << 26,  // Load Floating-Point Double with Update
+  STFS    = 52 << 26,  // Store Floating-Point Single
+  STFSU   = 53 << 26,  // Store Floating-Point Single with Update
+  STFD    = 54 << 26,  // Store Floating-Point Double
+  STFDU   = 55 << 26,  // Store Floating-Point Double with Update
+  LD      = 58 << 26,  // Load Double Word
+  EXT3    = 59 << 26,  // Extended code set 3
+  STD     = 62 << 26,  // Store Double Word (optionally with Update)
+  EXT4    = 63 << 26   // Extended code set 4
+};
+
+// Bits 10-1
+enum OpcodeExt1 {
+  MCRF   = 0 << 1,    // Move Condition Register Field
+  BCLRX  = 16 << 1,   // Branch Conditional Link Register
+  CRNOR  = 33 << 1,   // Condition Register NOR)
+  RFI    = 50 << 1,   // Return from Interrupt
+  CRANDC = 129 << 1,  // Condition Register AND with Complement
+  ISYNC  = 150 << 1,  // Instruction Synchronize
+  CRXOR  = 193 << 1,  // Condition Register XOR
+  CRNAND = 225 << 1,  // Condition Register NAND
+  CRAND  = 257 << 1,  // Condition Register AND
+  CREQV  = 289 << 1,  // Condition Register Equivalent
+  CRORC  = 417 << 1,  // Condition Register OR with Complement
+  CROR   = 449 << 1,  // Condition Register OR
+  BCCTRX = 528 << 1   // Branch Conditional to Count Register
+};
+
+// Bits 9-1 or 10-1
+enum OpcodeExt2 {
+  CMP = 0 << 1,
+  TW = 4 << 1,
+  SUBFCX = 8 << 1,
+  ADDCX = 10 << 1,
+  MULHWUX = 11 << 1,
+  MFCR = 19 << 1,
+  LWARX = 20 << 1,
+  LDX = 21 << 1,
+  LWZX = 23 << 1,    // load word zero w/ x-form
+  SLWX = 24 << 1,
+  CNTLZWX = 26 << 1,
+  SLDX = 27 << 1,
+  ANDX = 28 << 1,
+  CMPL = 32 << 1,
+  SUBFX = 40 << 1,
+  LDUX = 53 << 1,
+  DCBST = 54 << 1,
+  LWZUX = 55 << 1,   // load word zero w/ update x-form
+  CNTLZDX = 58 << 1,
+  ANDCX = 60 << 1,
+  MULHWX = 75 << 1,
+  DCBF = 86 << 1,
+  LBZX = 87 << 1,    // load byte zero w/ x-form
+  NEGX = 104 << 1,
+  LBZUX = 119 << 1,  // load byte zero w/ update x-form
+  NORX = 124 << 1,
+  SUBFEX = 136 << 1,
+  ADDEX = 138 << 1,
+  STDX = 149 << 1,
+  STWX = 151 << 1,    // store word w/ x-form
+  STDUX = 181 << 1,
+  STWUX = 183 << 1,   // store word w/ update x-form
+/*
+  MTCRF
+  MTMSR
+  STWCXx
+  SUBFZEX
+*/
+  ADDZEX = 202 << 1,  // Add to Zero Extended
+/*
+  MTSR
+*/
+  STBX = 215 << 1,    // store byte w/ x-form
+  MULLD  = 233 << 1,  // Multiply Low Double Word
+  MULLW  = 235 << 1,  // Multiply Low Word
+  STBUX = 247 << 1,   // store byte w/ update x-form
+  ADDX = 266 << 1,    // Add
+  LHZX = 279 << 1,    // load half-word zero w/ x-form
+  LHZUX = 311 << 1,   // load half-word zero w/ update x-form
+  LHAX =343 << 1,     // load half-word algebraic w/ x-form
+  LHAUX = 375 << 1,   // load half-word algebraic w/ update x-form
+  XORX = 316 << 1,    // Exclusive OR
+  MFSPR = 339 <<1,    // Move from Special-Purpose-Register
+  STHX = 407 << 1,    // store half-word w/ x-form
+  STHUX = 439 << 1,   // store half-word w/ update x-form
+  ORX = 444 << 1,     // Or
+  MTSPR = 467 <<1,    // Move to Special-Purpose-Register
+  DIVD  = 489 << 1,   // Divide Double Word
+  DIVW  = 491 << 1,   // Divide Word
+
+  // Below represent bits 10-1  (any value >= 512)
+  LFSX = 535 << 1,    // load float-single w/ x-form
+  SRWX = 536 << 1,    // Shift Right Word
+  SRDX = 539 << 1,    // Shift Right Double Word
+  LFSUX = 567 << 1,   // load float-single w/ update x-form
+  SYNC = 598 << 1,    // Synchronize
+  LFDX = 599 << 1,    // load float-double w/ x-form
+  LFDUX = 631 << 1,   // load float-double w/ update X-form
+  STFSX = 663 << 1,   // store float-single w/ x-form
+  STFSUX = 695 << 1,  // store float-single w/ update x-form
+  STFDX = 727 << 1,   // store float-double w/ x-form
+  STFDUX = 759 << 1,  // store float-double w/ update x-form
+  SRAW = 792 << 1,    // Shift Right Algebraic Word
+  SRAD = 794 << 1,    // Shift Right Algebraic Double Word
+  SRAWIX = 824 << 1,  // Shift Right Algebraic Word Immediate
+  SRADIX = 413 << 2,  // Shift Right Algebraic Double Word Immediate
+  EXTSH = 922 << 1,   // Extend Sign Halfword
+  EXTSB = 954 << 1,   // Extend Sign Byte
+  ICBI = 982 << 1,    // Instruction Cache Block Invalidate
+  EXTSW = 986 << 1    // Extend Sign Word
+};
+
+// Some use Bits 10-1 and other only 5-1 for the opcode
+enum OpcodeExt4 {
+  // Bits 5-1
+  FDIV   = 18 << 1,   // Floating Divide
+  FSUB   = 20 << 1,   // Floating Subtract
+  FADD   = 21 << 1,   // Floating Add
+  FSQRT  = 22 << 1,   // Floating Square Root
+  FSEL   = 23 << 1,   // Floating Select
+  FMUL   = 25 << 1,   // Floating Multiply
+
+  // Bits 10-1
+  FCMPU  =   0 << 1,  // Floating Compare Unordered
+  FRSP   =  12 << 1,  // Floating-Point Rounding
+  FCTIW  =  14 << 1,  // Floating Convert to Integer Word X-form
+  FCTIWZ =  15 << 1,  // Floating Convert to Integer Word with Round to Zero
+  FNEG   =  40 << 1,  // Floating Negate
+  MCRFS  =  64 << 1,  // Move to Condition Register from FPSCR
+  FMR    =  72 << 1,  // Floating Move Register
+  MTFSFI = 134 << 1,  // Move to FPSCR Field Immediate
+  FABS   = 264 << 1,  // Floating Absolute Value
+  FRIM   = 488 << 1,  // Floating Round to Integer Minus
+  MFFS   = 583 << 1,  // move from FPSCR x-form
+  MTFSF  = 711 << 1,  // move to FPSCR fields XFL-form
+  FCFID  = 846 << 1,  // Floating convert from integer doubleword
+  FCTID  = 814 << 1,  // Floating convert from integer doubleword
+  FCTIDZ = 815 << 1   // Floating convert from integer doubleword
+};
+
+// Bits 4-2
+enum OpcodeExt5 {
+  RLDICL = 0 << 2,    // Rotate Left Double Word Immediate then Clear Left
+  RLDICR = 1 << 2,    // Rotate Left Double Word Immediate then Clear Right
+  RLDIC  = 2 << 2,    // Rotate Left Double Word Immediate then Clear
+  RLDIMI = 3 << 2     // Rotate Left Double Word Immediate then Mask Insert
+};
+
+// Instruction encoding bits and masks.
+enum {
+  // Instruction encoding bit
+  B1  = 1 << 1,
+  B4  = 1 << 4,
+  B5  = 1 << 5,
+  B7  = 1 << 7,
+  B8  = 1 << 8,
+  B9  = 1 << 9,
+  B12 = 1 << 12,
+  B18 = 1 << 18,
+  B19 = 1 << 19,
+  B20 = 1 << 20,
+  B22 = 1 << 22,
+  B23 = 1 << 23,
+  B24 = 1 << 24,
+  B25 = 1 << 25,
+  B26 = 1 << 26,
+  B27 = 1 << 27,
+  B28 = 1 << 28,
+
+  B6  = 1 << 6,
+  B10 = 1 << 10,
+  B11 = 1 << 11,
+  B16 = 1 << 16,
+  B17 = 1 << 17,
+  B21 = 1 << 21,
+
+  // Instruction bit masks
+  kCondMask   = 0x1F << 21,
+  kOff12Mask  = (1 << 12) - 1,
+  kImm24Mask  = (1 << 24) - 1,
+  kOff16Mask  = (1 << 16) - 1,
+  kImm16Mask  = (1 << 16) - 1,
+  kImm26Mask  = (1 << 26) - 1,
+  kBOfieldMask = 0x1f << 21,
+  kOpcodeMask = 0x3f << 26,
+  kExt2OpcodeMask = 0x1f << 1,
+  kExt5OpcodeMask = 0x3 << 2,
+  kBOMask = 0x1f << 21,
+  kBIMask = 0x1F << 16,
+  kBDMask = 0x14 << 2,
+  kAAMask = 0x01 << 1,
+  kLKMask = 0x01,
+  kRCMask = 0x01,
+  kTOMask = 0x1f << 21
+};
+
+// the following is to differentiate different faked opcodes for
+// the BOGUS PPC instruction we invented (when bit 25 is 0) or to mark
+// different stub code (when bit 25 is 1)
+//   - use primary opcode 1 for undefined instruction
+//   - use bit 25 to indicate whether the opcode is for fake-arm
+//     instr or stub-marker
+//   - use the least significant 6-bit to indicate FAKE_OPCODE_T or
+//     MARKER_T
+#define FAKE_OPCODE 1 << 26
+#define MARKER_SUBOPCODE_BIT 25
+#define MARKER_SUBOPCODE 1 << MARKER_SUBOPCODE_BIT
+#define FAKER_SUBOPCODE 0 << MARKER_SUBOPCODE_BIT
+
+enum FAKE_OPCODE_T {
+  fBKPT = 14,
+  fLastFaker  // can't be more than 128 (2^^7)
+};
+#define FAKE_OPCODE_HIGH_BIT 7  // fake opcode has to fall into bit 0~7
+#define F_NEXT_AVAILABLE_STUB_MARKER 369  // must be less than 2^^9 (512)
+#define STUB_MARKER_HIGH_BIT 9  // stub marker has to fall into bit 0~9
+// -----------------------------------------------------------------------------
+// Addressing modes and instruction variants.
+
+// Overflow Exception
+enum OEBit {
+  SetOE   = 1 << 10,  // Set overflow exception
+  LeaveOE = 0 << 10   // No overflow exception
+};
+
+// Record bit
+enum RCBit {  // Bit 0
+  SetRC   = 1,  // LT,GT,EQ,SO
+  LeaveRC = 0   // None
+};
+
+// Link bit
+enum LKBit {  // Bit 0
+  SetLK   = 1,  // Load effective address of next instruction
+  LeaveLK = 0   // No action
+};
+
+enum BOfield {  // Bits 25-21
+  DCBNZF =  0 << 21,  // Decrement CTR; branch if CTR != 0 and condition false
+  DCBEZF =  2 << 21,  // Decrement CTR; branch if CTR == 0 and condition false
+  BF     =  4 << 21,  // Branch if condition false
+  DCBNZT =  8 << 21,  // Decrement CTR; branch if CTR != 0 and condition true
+  DCBEZT = 10 << 21,  // Decrement CTR; branch if CTR == 0 and condition true
+  BT     = 12 << 21,  // Branch if condition true
+  DCBNZ  = 16 << 21,  // Decrement CTR; branch if CTR != 0
+  DCBEZ  = 18 << 21,  // Decrement CTR; branch if CTR == 0
+  BA     = 20 << 21   // Branch always
+};
+
+#ifdef _AIX
+#undef CR_LT
+#undef CR_GT
+#undef CR_EQ
+#undef CR_SO
+#endif
+
+enum CRBit {
+  CR_LT = 0,
+  CR_GT = 1,
+  CR_EQ = 2,
+  CR_SO = 3,
+  CR_FU = 3
+};
+
+#define CRWIDTH 4
+
+// -----------------------------------------------------------------------------
+// Supervisor Call (svc) specific support.
+
+// Special Software Interrupt codes when used in the presence of the PPC
+// simulator.
+// svc (formerly swi) provides a 24bit immediate value. Use bits 22:0 for
+// standard SoftwareInterrupCode. Bit 23 is reserved for the stop feature.
+enum SoftwareInterruptCodes {
+  // transition to C code
+  kCallRtRedirected= 0x10,
+  // break point
+  kBreakpoint= 0x821008,  // bits23-0 of 0x7d821008 = twge r2, r2
+  // stop
+  kStopCode = 1 << 23,
+  // info
+  kInfo     = 0x9ff808    // bits23-0 of 0x7d9ff808 = twge r31, r31
+};
+const uint32_t kStopCodeMask = kStopCode - 1;
+const uint32_t kMaxStopCode = kStopCode - 1;
+const int32_t  kDefaultStopCode = -1;
+
+// FP rounding modes.
+enum VFPRoundingMode {
+  RN = 0,   // Round to Nearest.
+  RZ = 1,   // Round towards zero.
+  RP = 2,   // Round towards Plus Infinity.
+  RM = 3,   // Round towards Minus Infinity.
+
+  // Aliases.
+  kRoundToNearest = RN,
+  kRoundToZero = RZ,
+  kRoundToPlusInf = RP,
+  kRoundToMinusInf = RM
+};
+
+const uint32_t kVFPRoundingModeMask = 3;
+
+enum CheckForInexactConversion {
+  kCheckForInexactConversion,
+  kDontCheckForInexactConversion
+};
+
+// -----------------------------------------------------------------------------
+// Specific instructions, constants, and masks.
+// These constants are declared in assembler-arm.cc, as they use named registers
+// and other constants.
+
+
+// add(sp, sp, 4) instruction (aka Pop())
+extern const Instr kPopInstruction;
+
+// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
+// register r is not encoded.
+extern const Instr kPushRegPattern;
+
+// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
+// register r is not encoded.
+extern const Instr kPopRegPattern;
+
+// use TWI to indicate redirection call for simulation mode
+const Instr rtCallRedirInstr = TWI;
+
+// -----------------------------------------------------------------------------
+// Instruction abstraction.
+
+// The class Instruction enables access to individual fields defined in the PPC
+// architecture instruction set encoding.
+// Note that the Assembler uses typedef int32_t Instr.
+//
+// Example: Test whether the instruction at ptr does set the condition code
+// bits.
+//
+// bool InstructionSetsConditionCodes(byte* ptr) {
+//   Instruction* instr = Instruction::At(ptr);
+//   int type = instr->TypeValue();
+//   return ((type == 0) || (type == 1)) && instr->HasS();
+// }
+//
+class Instruction {
+ public:
+  enum {
+    kInstrSize = 4,
+    kInstrSizeLog2 = 2,
+    kPCReadOffset = 8
+  };
+
+  // Helper macro to define static accessors.
+  // We use the cast to char* trick to bypass the strict anti-aliasing rules.
+  #define DECLARE_STATIC_TYPED_ACCESSOR(return_type, Name)                     \
+    static inline return_type Name(Instr instr) {                              \
+      char* temp = reinterpret_cast<char*>(&instr);                            \
+      return reinterpret_cast<Instruction*>(temp)->Name();                     \
+    }
+
+  #define DECLARE_STATIC_ACCESSOR(Name) DECLARE_STATIC_TYPED_ACCESSOR(int, Name)
+
+  // Get the raw instruction bits.
+  inline Instr InstructionBits() const {
+    return *reinterpret_cast<const Instr*>(this);
+  }
+
+  // Set the raw instruction bits to value.
+  inline void SetInstructionBits(Instr value) {
+    *reinterpret_cast<Instr*>(this) = value;
+  }
+
+  // Read one particular bit out of the instruction bits.
+  inline int Bit(int nr) const {
+    return (InstructionBits() >> nr) & 1;
+  }
+
+  // Read a bit field's value out of the instruction bits.
+  inline int Bits(int hi, int lo) const {
+    return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1);
+  }
+
+  // Read a bit field out of the instruction bits.
+  inline int BitField(int hi, int lo) const {
+    return InstructionBits() & (((2 << (hi - lo)) - 1) << lo);
+  }
+
+  // Static support.
+
+  // Read one particular bit out of the instruction bits.
+  static inline int Bit(Instr instr, int nr) {
+    return (instr >> nr) & 1;
+  }
+
+  // Read the value of a bit field out of the instruction bits.
+  static inline int Bits(Instr instr, int hi, int lo) {
+    return (instr >> lo) & ((2 << (hi - lo)) - 1);
+  }
+
+
+  // Read a bit field out of the instruction bits.
+  static inline int BitField(Instr instr, int hi, int lo) {
+    return instr & (((2 << (hi - lo)) - 1) << lo);
+  }
+
+  // PowerPC
+  inline int RSValue() const { return Bits(25, 21); }
+  inline int RTValue() const { return Bits(25, 21); }
+  inline int RAValue() const { return Bits(20, 16); }
+  DECLARE_STATIC_ACCESSOR(RAValue);
+  inline int RBValue() const { return Bits(15, 11); }
+  DECLARE_STATIC_ACCESSOR(RBValue);
+  inline int RCValue() const { return Bits(10, 6); }
+  DECLARE_STATIC_ACCESSOR(RCValue);
+  // end PowerPC
+
+  inline int OpcodeValue() const {
+    return static_cast<Opcode>(Bits(31, 26));  // PowerPC
+  }
+  inline Opcode OpcodeField() const {
+    return static_cast<Opcode>(BitField(24, 21));
+  }
+
+  // Fields used in Software interrupt instructions
+  inline SoftwareInterruptCodes SvcValue() const {
+    return static_cast<SoftwareInterruptCodes>(Bits(23, 0));
+  }
+
+  // Instructions are read of out a code stream. The only way to get a
+  // reference to an instruction is to convert a pointer. There is no way
+  // to allocate or create instances of class Instruction.
+  // Use the At(pc) function to create references to Instruction.
+  static Instruction* At(byte* pc) {
+    return reinterpret_cast<Instruction*>(pc);
+  }
+
+
+ private:
+  // We need to prevent the creation of instances of class Instruction.
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
+};
+
+
+// Helper functions for converting between register numbers and names.
+class Registers {
+ public:
+  // Return the name of the register.
+  static const char* Name(int reg);
+
+  // Lookup the register number for the name provided.
+  static int Number(const char* name);
+
+  struct RegisterAlias {
+    int reg;
+    const char* name;
+  };
+
+ private:
+  static const char* names_[kNumRegisters];
+  static const RegisterAlias aliases_[];
+};
+
+// Helper functions for converting between FP register numbers and names.
+class FPRegisters {
+ public:
+  // Return the name of the register.
+  static const char* Name(int reg);
+
+  // Lookup the register number for the name provided.
+  static int Number(const char* name);
+
+ private:
+  static const char* names_[kNumFPRegisters];
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_CONSTANTS_PPC_H_
diff --git a/src/ppc/cpu-ppc.cc b/src/ppc/cpu-ppc.cc
new file mode 100644
index 0000000..037e3af
--- /dev/null
+++ b/src/ppc/cpu-ppc.cc
@@ -0,0 +1,90 @@
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// CPU specific code for ppc independent of OS goes here.
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "cpu.h"
+#include "macro-assembler.h"
+#include "simulator.h"  // for cache flushing.
+
+namespace v8 {
+namespace internal {
+
+void CPU::SetUp() {
+  CpuFeatures::Probe();
+}
+
+bool CPU::SupportsCrankshaft() {
+  return true;
+}
+
+void CPU::FlushICache(void* buffer, size_t size) {
+  // Nothing to do flushing no instructions.
+  if (size == 0) {
+    return;
+  }
+
+#if defined (USE_SIMULATOR)
+  // Not generating PPC instructions for C-code. This means that we are
+  // building an PPC emulator based target.  We should notify the simulator
+  // that the Icache was flushed.
+  // None of this code ends up in the snapshot so there are no issues
+  // around whether or not to generate the code when building snapshots.
+  Simulator::FlushICache(Isolate::Current()->simulator_i_cache(), buffer, size);
+#else
+
+  intptr_t mask = kCacheLineSize - 1;
+  byte *start = reinterpret_cast<byte *>(
+                 reinterpret_cast<intptr_t>(buffer) & ~mask);
+  byte *end = static_cast<byte *>(buffer) + size;
+  for (byte *pointer = start; pointer < end; pointer += kCacheLineSize) {
+    __asm__(
+      "dcbf 0, %0  \n"  \
+      "sync        \n"  \
+      "icbi 0, %0  \n"  \
+      "isync       \n"
+      : /* no output */
+      : "r" (pointer));
+  }
+
+#endif  // USE_SIMULATOR
+}
+
+
+void CPU::DebugBreak() {
+  UNIMPLEMENTED();  // Unimplemented on PowerPC
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/debug-ppc.cc b/src/ppc/debug-ppc.cc
new file mode 100644
index 0000000..0cc0765
--- /dev/null
+++ b/src/ppc/debug-ppc.cc
@@ -0,0 +1,362 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "codegen.h"
+#include "debug.h"
+
+namespace v8 {
+namespace internal {
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+bool BreakLocationIterator::IsDebugBreakAtReturn() {
+  return Debug::IsDebugBreakAtReturn(rinfo());
+}
+
+
+void BreakLocationIterator::SetDebugBreakAtReturn() {
+  // Patch the code changing the return from JS function sequence from
+  //
+  //   mr sp, fp
+  //   lwz fp, 0(sp)
+  //   lwz r0, 4(sp)
+  //   mtlr r0
+  //   addi sp, sp, <delta>
+  //   blr
+  //
+  // to a call to the debug break return code.
+  // this uses a FIXED_SEQUENCE to load a 32bit constant
+  //
+  //   lis r0, <address hi>
+  //   ori r0, r0, <address lo>
+  //   mtlr r0
+  //   blrl
+  //   bkpt
+  //
+  // The 64bit sequence is a bit longer
+  //   lis r0, <address bits 63-48>
+  //   ori r0, r0, <address bits 47-32>
+  //   sldi r0, r0, 32
+  //   oris r0, r0, <address bits 31-16>
+  //   ori  r0, r0, <address bits 15-0>
+  //   mtlr r0
+  //   blrl
+  //   bkpt
+  //
+  CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
+// printf("SetDebugBreakAtReturn: pc=%08x\n", (unsigned int)rinfo()->pc());
+  patcher.masm()->mov(v8::internal::r0,
+    Operand(reinterpret_cast<intptr_t>(
+      Isolate::Current()->debug()->debug_break_return()->entry())));
+  patcher.masm()->mtlr(v8::internal::r0);
+  patcher.masm()->bclr(BA, SetLK);
+  patcher.masm()->bkpt(0);
+}
+
+
+// Restore the JS frame exit code.
+void BreakLocationIterator::ClearDebugBreakAtReturn() {
+  rinfo()->PatchCode(original_rinfo()->pc(),
+                     Assembler::kJSReturnSequenceInstructions);
+}
+
+
+// A debug break in the frame exit code is identified by the JS frame exit code
+// having been patched with a call instruction.
+bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
+  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
+  return rinfo->IsPatchedReturnSequence();
+}
+
+
+bool BreakLocationIterator::IsDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  // Check whether the debug break slot instructions have been patched.
+  return rinfo()->IsPatchedDebugBreakSlotSequence();
+}
+
+
+void BreakLocationIterator::SetDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  // Patch the code changing the debug break slot code from
+  //
+  //   ori r3, r3, 0
+  //   ori r3, r3, 0
+  //   ori r3, r3, 0
+  //   ori r3, r3, 0
+  //   ori r3, r3, 0
+  //
+  // to a call to the debug break code, using a FIXED_SEQUENCE.
+  //
+  //   lis r0, <address hi>
+  //   ori r0, r0, <address lo>
+  //   mtlr r0
+  //   blrl
+  //
+  // The 64bit sequence is +3 instructions longer for the load
+  //
+  CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
+// printf("SetDebugBreakAtSlot: pc=%08x\n", (unsigned int)rinfo()->pc());
+  patcher.masm()->mov(v8::internal::r0,
+            Operand(reinterpret_cast<intptr_t>(
+                   Isolate::Current()->debug()->debug_break_slot()->entry())));
+  patcher.masm()->mtlr(v8::internal::r0);
+  patcher.masm()->bclr(BA, SetLK);
+}
+
+
+void BreakLocationIterator::ClearDebugBreakAtSlot() {
+  ASSERT(IsDebugBreakSlot());
+  rinfo()->PatchCode(original_rinfo()->pc(),
+                     Assembler::kDebugBreakSlotInstructions);
+}
+
+const bool Debug::FramePaddingLayout::kIsSupported = false;
+
+
+#define __ ACCESS_MASM(masm)
+
+
+static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
+                                          RegList object_regs,
+                                          RegList non_object_regs) {
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+// printf("Generate_DebugBreakCallHelper\n");
+    // Store the registers containing live values on the expression stack to
+    // make sure that these are correctly updated during GC. Non object values
+    // are stored as a smi causing it to be untouched by GC.
+    ASSERT((object_regs & ~kJSCallerSaved) == 0);
+    ASSERT((non_object_regs & ~kJSCallerSaved) == 0);
+    ASSERT((object_regs & non_object_regs) == 0);
+    if ((object_regs | non_object_regs) != 0) {
+      for (int i = 0; i < kNumJSCallerSaved; i++) {
+        int r = JSCallerSavedCode(i);
+        Register reg = { r };
+        if ((non_object_regs & (1 << r)) != 0) {
+          if (FLAG_debug_code) {
+            __ andis(r0, reg, Operand(0xc000));
+            __ Assert(eq, "Unable to encode value as smi", cr0);
+          }
+          __ SmiTag(reg);
+        }
+      }
+      __ MultiPush(object_regs | non_object_regs);
+    }
+
+#ifdef DEBUG
+    __ RecordComment("// Calling from debug break to runtime - come in - over");
+#endif
+    __ mov(r3, Operand(0, RelocInfo::NONE));  // no arguments
+    __ mov(r4, Operand(ExternalReference::debug_break(masm->isolate())));
+
+    CEntryStub ceb(1);
+    __ CallStub(&ceb);
+
+    // Restore the register values from the expression stack.
+    if ((object_regs | non_object_regs) != 0) {
+      __ MultiPop(object_regs | non_object_regs);
+      for (int i = 0; i < kNumJSCallerSaved; i++) {
+        int r = JSCallerSavedCode(i);
+        Register reg = { r };
+        if ((non_object_regs & (1 << r)) != 0) {
+          __ SmiUntag(reg);
+        }
+        if (FLAG_debug_code &&
+            (((object_regs |non_object_regs) & (1 << r)) == 0)) {
+          __ mov(reg, Operand(kDebugZapValue));
+        }
+      }
+    }
+
+    // Leave the internal frame.
+  }
+
+  // Now that the break point has been handled, resume normal execution by
+  // jumping to the target address intended by the caller and that was
+  // overwritten by the address of DebugBreakXXX.
+  ExternalReference after_break_target =
+      ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
+  __ mov(ip, Operand(after_break_target));
+  __ LoadP(ip, MemOperand(ip));
+  __ Jump(ip);
+}
+
+
+void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC load (from ic-ppc.cc).
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- r3    : receiver
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  // Registers r3 and r5 contain objects that need to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, r3.bit() | r5.bit(), 0);
+}
+
+
+void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC store (from ic-ppc.cc).
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  // Registers r3, r4, and r5 contain objects that need to be pushed on the
+  // expression stack of the fake JS frame.
+  Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit() | r5.bit(), 0);
+}
+
+
+void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit(), 0);
+}
+
+
+void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r3     : value
+  //  -- r4     : key
+  //  -- r5     : receiver
+  //  -- lr     : return address
+  Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit() | r5.bit(), 0);
+}
+
+
+void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
+  // Calling convention for IC call (from ic-ppc.cc)
+  // ----------- S t a t e -------------
+  //  -- r5     : name
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, r5.bit(), 0);
+}
+
+
+void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
+  // In places other than IC call sites it is expected that r3 is TOS which
+  // is an object - this is not generally the case so this should be used with
+  // care.
+  Generate_DebugBreakCallHelper(masm, r3.bit(), 0);
+}
+
+
+void Debug::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
+  // Register state for CallFunctionStub (from code-stubs-ppc.cc).
+  // ----------- S t a t e -------------
+  //  -- r4 : function
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, r4.bit(), 0);
+}
+
+
+void Debug::GenerateCallFunctionStubRecordDebugBreak(MacroAssembler* masm) {
+  // Register state for CallFunctionStub (from code-stubs-ppc.cc).
+  // ----------- S t a t e -------------
+  //  -- r4 : function
+  //  -- r5 : cache cell for call target
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit(), 0);
+}
+
+
+void Debug::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
+  // Calling convention for CallConstructStub (from code-stubs-ppc.cc)
+  // ----------- S t a t e -------------
+  //  -- r3     : number of arguments (not smi)
+  //  -- r4     : constructor function
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, r4.bit(), r3.bit());
+}
+
+
+void Debug::GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm) {
+  // Calling convention for CallConstructStub (from code-stubs-ppc.cc)
+  // ----------- S t a t e -------------
+  //  -- r3     : number of arguments (not smi)
+  //  -- r4     : constructor function
+  //  -- r5     : cache cell for call target
+  // -----------------------------------
+  Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit(), r3.bit());
+}
+
+
+void Debug::GenerateSlot(MacroAssembler* masm) {
+  // Generate enough nop's to make space for a call instruction. Avoid emitting
+  // the trampoline pool in the debug break slot code.
+  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
+  Label check_codesize;
+  __ bind(&check_codesize);
+  __ RecordDebugBreakSlot();
+  for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
+    __ nop(MacroAssembler::DEBUG_BREAK_NOP);
+  }
+  ASSERT_EQ(Assembler::kDebugBreakSlotInstructions,
+            masm->InstructionsGeneratedSince(&check_codesize));
+}
+
+
+void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
+  // In the places where a debug break slot is inserted no registers can contain
+  // object pointers.
+  Generate_DebugBreakCallHelper(masm, 0, 0);
+}
+
+
+void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
+  masm->Abort("LiveEdit frame dropping is not supported on ppc");
+}
+
+
+void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
+  masm->Abort("LiveEdit frame dropping is not supported on ppc");
+}
+
+const bool Debug::kFrameDropperSupported = false;
+
+#undef __
+
+
+
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/deoptimizer-ppc.cc b/src/ppc/deoptimizer-ppc.cc
new file mode 100644
index 0000000..79803b4
--- /dev/null
+++ b/src/ppc/deoptimizer-ppc.cc
@@ -0,0 +1,1259 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "codegen.h"
+#include "deoptimizer.h"
+#include "full-codegen.h"
+#include "safepoint-table.h"
+
+namespace v8 {
+namespace internal {
+
+const int Deoptimizer::table_entry_size_ = 20;
+
+
+int Deoptimizer::patch_size() {
+#if V8_TARGET_ARCH_PPC64
+  const int kCallInstructionSizeInWords = 7;
+#else
+  const int kCallInstructionSizeInWords = 4;
+#endif
+  return kCallInstructionSizeInWords * Assembler::kInstrSize;
+}
+
+
+void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
+  HandleScope scope;
+  AssertNoAllocation no_allocation;
+
+  if (!function->IsOptimized()) return;
+
+  // The optimized code is going to be patched, so we cannot use it
+  // any more.  Play safe and reset the whole cache.
+  function->shared()->ClearOptimizedCodeMap();
+
+  // Get the optimized code.
+  Code* code = function->code();
+  Address code_start_address = code->instruction_start();
+
+  // Invalidate the relocation information, as it will become invalid by the
+  // code patching below, and is not needed any more.
+  code->InvalidateRelocation();
+
+  // For each LLazyBailout instruction insert a call to the corresponding
+  // deoptimization entry.
+  DeoptimizationInputData* deopt_data =
+      DeoptimizationInputData::cast(code->deoptimization_data());
+#ifdef DEBUG
+  Address prev_call_address = NULL;
+#endif
+  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
+    if (deopt_data->Pc(i)->value() == -1) continue;
+    Address call_address = code_start_address + deopt_data->Pc(i)->value();
+    Address deopt_entry = GetDeoptimizationEntry(i, LAZY);
+    // We need calls to have a predictable size in the unoptimized code, but
+    // this is optimized code, so we don't have to have a predictable size.
+    int call_size_in_bytes =
+        MacroAssembler::CallSizeNotPredictableCodeSize(deopt_entry,
+                                                       RelocInfo::NONE);
+    int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize;
+    ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0);
+    ASSERT(call_size_in_bytes <= patch_size());
+    CodePatcher patcher(call_address, call_size_in_words);
+    patcher.masm()->Call(deopt_entry, RelocInfo::NONE);
+    ASSERT(prev_call_address == NULL ||
+           call_address >= prev_call_address + patch_size());
+    ASSERT(call_address + patch_size() <= code->instruction_end());
+#ifdef DEBUG
+    prev_call_address = call_address;
+#endif
+  }
+
+  Isolate* isolate = code->GetIsolate();
+
+  // Add the deoptimizing code to the list.
+  DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
+  DeoptimizerData* data = isolate->deoptimizer_data();
+  node->set_next(data->deoptimizing_code_list_);
+  data->deoptimizing_code_list_ = node;
+
+  // We might be in the middle of incremental marking with compaction.
+  // Tell collector to treat this code object in a special way and
+  // ignore all slots that might have been recorded on it.
+  isolate->heap()->mark_compact_collector()->InvalidateCode(code);
+
+  ReplaceCodeForRelatedFunctions(function, code);
+
+  if (FLAG_trace_deopt) {
+    PrintF("[forced deoptimization: ");
+    function->PrintName();
+    PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<uintptr_t>(function));
+  }
+}
+
+
+#if V8_TARGET_ARCH_PPC64
+static const int32_t kBranchBeforeStackCheck = 0x409c0020;
+static const int32_t kBranchBeforeInterrupt =  0x409c0044;
+#else
+static const int32_t kBranchBeforeStackCheck = 0x409c0014;
+static const int32_t kBranchBeforeInterrupt =  0x409c0024;
+#endif
+
+
+// This code has some dependency on the FIXED_SEQUENCE lis/ori
+void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
+                                        Address pc_after,
+                                        Code* check_code,
+                                        Code* replacement_code) {
+  const int kInstrSize = Assembler::kInstrSize;
+  // There are two 'Stack check' sequences from full-codegen-ppc.cc
+  // both have similar code - and FLAG_count_based_interrupts will
+  // control which we expect to find
+  //
+  // The call of the stack guard check has the following form:
+  // 409c0014       bge +40 -> 876  (0x25535c4c)  ;; (ok)
+  // 3d802553       lis     r12, 9555        ;; two part load
+  // 618c5000       ori     r12, r12, 20480  ;; of stack guard address
+  // 7d8803a6       mtlr    r12
+  // 4e800021       blrl
+  //    <-- pc_after
+  //
+  // 64bit will have an expanded mov() [lis/ori] sequence
+
+  // Check we have a branch & link through r12 (ip)
+  ASSERT(Memory::int32_at(pc_after - 2 * kInstrSize) == 0x7d8803a6);
+  ASSERT(Memory::int32_at(pc_after - kInstrSize) == 0x4e800021);
+
+#if V8_TARGET_ARCH_PPC64
+  ASSERT(Assembler::Is64BitLoadIntoR12(
+      Assembler::instr_at(pc_after - 7 * kInstrSize),
+      Assembler::instr_at(pc_after - 6 * kInstrSize),
+      Assembler::instr_at(pc_after - 5 * kInstrSize),
+      Assembler::instr_at(pc_after - 4 * kInstrSize),
+      Assembler::instr_at(pc_after - 3 * kInstrSize)));
+  if (FLAG_count_based_interrupts) {
+    ASSERT_EQ(kBranchBeforeInterrupt,
+              Memory::int32_at(pc_after - 8 * kInstrSize));
+  } else {
+    ASSERT_EQ(kBranchBeforeStackCheck,
+              Memory::int32_at(pc_after - 8 * kInstrSize));
+  }
+#else
+  ASSERT(Assembler::Is32BitLoadIntoR12(
+      Assembler::instr_at(pc_after - 4 * kInstrSize),
+      Assembler::instr_at(pc_after - 3 * kInstrSize)));
+  if (FLAG_count_based_interrupts) {
+    ASSERT_EQ(kBranchBeforeInterrupt,
+              Memory::int32_at(pc_after - 5 * kInstrSize));
+  } else {
+    ASSERT_EQ(kBranchBeforeStackCheck,
+              Memory::int32_at(pc_after - 5 * kInstrSize));
+  }
+#endif
+
+  // We patch the code to the following form:
+  // 60000000       ori     r0, r0, 0        ;; NOP
+  // 3d80NNNN       lis     r12, NNNN        ;; two part load
+  // 618cNNNN       ori     r12, r12, NNNN   ;; of on stack replace address
+  // 7d8803a6       mtlr    r12
+  // 4e800021       blrl
+
+#if V8_TARGET_ARCH_PPC64
+  CodePatcher patcher(pc_after - 8 * kInstrSize, 6);
+
+  // Assemble the 64 bit value from the five part load and verify
+  // that it is the stack guard code
+  uint64_t stack_check_address =
+    (Memory::uint32_at(pc_after - 7 * kInstrSize) & 0xFFFF) << 16;
+  stack_check_address |=
+    (Memory::uint32_at(pc_after - 6 * kInstrSize) & 0xFFFF);
+  stack_check_address <<= 32;
+  stack_check_address |=
+    (Memory::uint32_at(pc_after - 4 * kInstrSize) & 0xFFFF) << 16;
+  stack_check_address |=
+    (Memory::uint32_at(pc_after - 3 * kInstrSize) & 0xFFFF);
+#else
+  CodePatcher patcher(pc_after - 5 * kInstrSize, 3);
+
+  // Assemble the 32 bit value from the two part load and verify
+  // that it is the stack guard code
+  uint32_t stack_check_address =
+    (Memory::int32_at(pc_after - 4 * kInstrSize) & 0xFFFF) << 16;
+  stack_check_address |=
+    (Memory::int32_at(pc_after - 3 * kInstrSize) & 0xFFFF);
+#endif
+  ASSERT(stack_check_address ==
+    reinterpret_cast<uintptr_t>(check_code->entry()));
+
+  // Replace conditional jump with NOP.
+  patcher.masm()->nop();
+
+  // Now modify the two part load (or 5 part on 64bit)
+  patcher.masm()->mov(ip,
+    Operand(reinterpret_cast<uintptr_t>(replacement_code->entry())));
+
+#if V8_TARGET_ARCH_PPC64
+  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
+      unoptimized_code, pc_after - 7 * kInstrSize, replacement_code);
+#else
+  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
+      unoptimized_code, pc_after - 4 * kInstrSize, replacement_code);
+#endif
+}
+
+
+void Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code,
+                                         Address pc_after,
+                                         Code* check_code,
+                                         Code* replacement_code) {
+  const int kInstrSize = Assembler::kInstrSize;
+
+  // Check we have a branch & link through r12 (ip)
+  ASSERT(Memory::int32_at(pc_after - 2 * kInstrSize) == 0x7d8803a6);
+  ASSERT(Memory::int32_at(pc_after - kInstrSize) == 0x4e800021);
+
+#if V8_TARGET_ARCH_PPC64
+  ASSERT(Assembler::Is64BitLoadIntoR12(
+      Assembler::instr_at(pc_after - 7 * kInstrSize),
+      Assembler::instr_at(pc_after - 6 * kInstrSize),
+      Assembler::instr_at(pc_after - 5 * kInstrSize),
+      Assembler::instr_at(pc_after - 4 * kInstrSize),
+      Assembler::instr_at(pc_after - 3 * kInstrSize)));
+#else
+  ASSERT(Assembler::Is32BitLoadIntoR12(
+      Assembler::instr_at(pc_after - 4 * kInstrSize),
+      Assembler::instr_at(pc_after - 3 * kInstrSize)));
+#endif
+
+#if V8_TARGET_ARCH_PPC64
+  // Replace NOP with conditional jump.
+  CodePatcher patcher(pc_after - 8 * kInstrSize, 6);
+  if (FLAG_count_based_interrupts) {
+      patcher.masm()->bc(+68, BF,
+                v8::internal::Assembler::encode_crbit(cr7, CR_LT));  // bge
+    ASSERT_EQ(kBranchBeforeInterrupt,
+              Memory::int32_at(pc_after - 8 * kInstrSize));
+  } else {
+    patcher.masm()->bc(+32, BF,
+                v8::internal::Assembler::encode_crbit(cr7, CR_LT));  // bge
+    ASSERT_EQ(kBranchBeforeStackCheck,
+              Memory::int32_at(pc_after - 8 * kInstrSize));
+  }
+#else
+  // Replace NOP with conditional jump.
+  CodePatcher patcher(pc_after - 5 * kInstrSize, 3);
+  if (FLAG_count_based_interrupts) {
+      patcher.masm()->bc(+36, BF,
+                v8::internal::Assembler::encode_crbit(cr7, CR_LT));  // bge
+    ASSERT_EQ(kBranchBeforeInterrupt,
+              Memory::int32_at(pc_after - 5 * kInstrSize));
+  } else {
+    patcher.masm()->bc(+20, BF,
+                v8::internal::Assembler::encode_crbit(cr7, CR_LT));  // bge
+    ASSERT_EQ(kBranchBeforeStackCheck,
+              Memory::int32_at(pc_after - 5 * kInstrSize));
+  }
+#endif
+
+#if V8_TARGET_ARCH_PPC64
+  // Assemble the 64 bit value from the five part load and verify
+  // that it is the stack guard code
+  uint64_t stack_check_address =
+    (Memory::uint32_at(pc_after - 7 * kInstrSize) & 0xFFFF) << 16;
+  stack_check_address |=
+    (Memory::uint32_at(pc_after - 6 * kInstrSize) & 0xFFFF);
+  stack_check_address <<= 32;
+  stack_check_address |=
+    (Memory::uint32_at(pc_after - 4 * kInstrSize) & 0xFFFF) << 16;
+  stack_check_address |=
+    (Memory::uint32_at(pc_after - 3 * kInstrSize) & 0xFFFF);
+#else
+  // Assemble the 32 bit value from the two part load and verify
+  // that it is the replacement code address
+  // This assumes a FIXED_SEQUENCE for lis/ori
+  uint32_t stack_check_address =
+    (Memory::int32_at(pc_after - 4 * kInstrSize) & 0xFFFF) << 16;
+  stack_check_address |=
+    (Memory::int32_at(pc_after - 3 * kInstrSize) & 0xFFFF);
+#endif
+  ASSERT(stack_check_address ==
+    reinterpret_cast<uintptr_t>(replacement_code->entry()));
+
+  // Now modify the two part load (or 5 part on 64bit)
+  patcher.masm()->mov(ip,
+    Operand(reinterpret_cast<uintptr_t>(check_code->entry())));
+
+#if V8_TARGET_ARCH_PPC64
+  check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
+      unoptimized_code, pc_after - 7 * kInstrSize, check_code);
+#else
+  check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
+      unoptimized_code, pc_after - 4 * kInstrSize, check_code);
+#endif
+}
+
+
+static int LookupBailoutId(DeoptimizationInputData* data, BailoutId ast_id) {
+  ByteArray* translations = data->TranslationByteArray();
+  int length = data->DeoptCount();
+  for (int i = 0; i < length; i++) {
+    if (data->AstId(i) == ast_id) {
+      TranslationIterator it(translations,  data->TranslationIndex(i)->value());
+      int value = it.Next();
+      ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value));
+      // Read the number of frames.
+      value = it.Next();
+      if (value == 1) return i;
+    }
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+
+void Deoptimizer::DoComputeOsrOutputFrame() {
+  DeoptimizationInputData* data = DeoptimizationInputData::cast(
+      optimized_code_->deoptimization_data());
+  unsigned ast_id = data->OsrAstId()->value();
+
+  int bailout_id = LookupBailoutId(data, BailoutId(ast_id));
+  unsigned translation_index = data->TranslationIndex(bailout_id)->value();
+  ByteArray* translations = data->TranslationByteArray();
+
+  TranslationIterator iterator(translations, translation_index);
+  Translation::Opcode opcode =
+      static_cast<Translation::Opcode>(iterator.Next());
+  ASSERT(Translation::BEGIN == opcode);
+  USE(opcode);
+  int count = iterator.Next();
+  iterator.Skip(1);  // Drop JS frame count.
+  ASSERT(count == 1);
+  USE(count);
+
+  opcode = static_cast<Translation::Opcode>(iterator.Next());
+  USE(opcode);
+  ASSERT(Translation::JS_FRAME == opcode);
+  unsigned node_id = iterator.Next();
+  USE(node_id);
+  ASSERT(node_id == ast_id);
+  int closure_id = iterator.Next();
+  USE(closure_id);
+  ASSERT_EQ(Translation::kSelfLiteralId, closure_id);
+  unsigned height = iterator.Next();
+  unsigned height_in_bytes = height * kPointerSize;
+  USE(height_in_bytes);
+
+  unsigned fixed_size = ComputeFixedSize(function_);
+  unsigned input_frame_size = input_->GetFrameSize();
+  ASSERT(fixed_size + height_in_bytes == input_frame_size);
+
+  unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize;
+  unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value();
+  unsigned outgoing_size = outgoing_height * kPointerSize;
+  unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size;
+  ASSERT(outgoing_size == 0);  // OSR does not happen in the middle of a call.
+
+  if (FLAG_trace_osr) {
+    PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ",
+           reinterpret_cast<intptr_t>(function_));
+    function_->PrintName();
+    PrintF(" => node=%u, frame=%d->%d]\n",
+           ast_id,
+           input_frame_size,
+           output_frame_size);
+  }
+
+  // There's only one output frame in the OSR case.
+  output_count_ = 1;
+  output_ = new FrameDescription*[1];
+  output_[0] = new(output_frame_size) FrameDescription(
+      output_frame_size, function_);
+  output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
+
+  // Clear the incoming parameters in the optimized frame to avoid
+  // confusing the garbage collector.
+  unsigned output_offset = output_frame_size - kPointerSize;
+  int parameter_count = function_->shared()->formal_parameter_count() + 1;
+  for (int i = 0; i < parameter_count; ++i) {
+    output_[0]->SetFrameSlot(output_offset, 0);
+    output_offset -= kPointerSize;
+  }
+
+  // Translate the incoming parameters. This may overwrite some of the
+  // incoming argument slots we've just cleared.
+  int input_offset = input_frame_size - kPointerSize;
+  bool ok = true;
+  int limit = input_offset - (parameter_count * kPointerSize);
+  while (ok && input_offset > limit) {
+    ok = DoOsrTranslateCommand(&iterator, &input_offset);
+  }
+
+  // There are no translation commands for the caller's pc and fp, the
+  // context, and the function.  Set them up explicitly.
+  for (int i =  StandardFrameConstants::kCallerPCOffset;
+       ok && i >=  StandardFrameConstants::kMarkerOffset;
+       i -= kPointerSize) {
+    uintptr_t input_value = input_->GetFrameSlot(input_offset);
+    if (FLAG_trace_osr) {
+      const char* name = "UNKNOWN";
+      switch (i) {
+        case StandardFrameConstants::kCallerPCOffset:
+          name = "caller's pc";
+          break;
+        case StandardFrameConstants::kCallerFPOffset:
+          name = "fp";
+          break;
+        case StandardFrameConstants::kContextOffset:
+          name = "context";
+          break;
+        case StandardFrameConstants::kMarkerOffset:
+          name = "function";
+          break;
+      }
+      PrintF("    [sp + %d] <- 0x%08" V8PRIxPTR " ;"
+             " [sp + %d] (fixed part - %s)\n",
+             output_offset,
+             input_value,
+             input_offset,
+             name);
+    }
+
+    output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
+    input_offset -= kPointerSize;
+    output_offset -= kPointerSize;
+  }
+
+  // Translate the rest of the frame.
+  while (ok && input_offset >= 0) {
+    ok = DoOsrTranslateCommand(&iterator, &input_offset);
+  }
+
+  // If translation of any command failed, continue using the input frame.
+  if (!ok) {
+    delete output_[0];
+    output_[0] = input_;
+    output_[0]->SetPc(reinterpret_cast<uintptr_t>(from_));
+  } else {
+    // Set up the frame pointer and the context pointer.
+    output_[0]->SetRegister(fp.code(), input_->GetRegister(fp.code()));
+    output_[0]->SetRegister(cp.code(), input_->GetRegister(cp.code()));
+
+    unsigned pc_offset = data->OsrPcOffset()->value();
+    uintptr_t pc = reinterpret_cast<uintptr_t>(
+        optimized_code_->entry() + pc_offset);
+    output_[0]->SetPc(pc);
+  }
+  Code* continuation = isolate_->builtins()->builtin(Builtins::kNotifyOSR);
+  output_[0]->SetContinuation(
+      reinterpret_cast<uintptr_t>(continuation->entry()));
+
+  if (FLAG_trace_osr) {
+    PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ",
+           ok ? "finished" : "aborted",
+           reinterpret_cast<intptr_t>(function_));
+    function_->PrintName();
+    PrintF(" => pc=0x%0" V8PRIxPTR "]\n", output_[0]->GetPc());
+  }
+}
+
+
+void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
+                                                 int frame_index) {
+  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
+  unsigned height = iterator->Next();
+  unsigned height_in_bytes = height * kPointerSize;
+  if (FLAG_trace_deopt) {
+    PrintF("  translating arguments adaptor => height=%d\n", height_in_bytes);
+  }
+
+  unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
+  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
+
+  // Allocate and store the output frame description.
+  FrameDescription* output_frame =
+      new(output_frame_size) FrameDescription(output_frame_size, function);
+  output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
+
+  // Arguments adaptor can not be topmost or bottommost.
+  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
+  ASSERT(output_[frame_index] == NULL);
+  output_[frame_index] = output_frame;
+
+  // The top address of the frame is computed from the previous
+  // frame's top and this frame's size.
+  uintptr_t top_address;
+  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+  output_frame->SetTop(top_address);
+
+  // Compute the incoming parameter translation.
+  int parameter_count = height;
+  unsigned output_offset = output_frame_size;
+  for (int i = 0; i < parameter_count; ++i) {
+    output_offset -= kPointerSize;
+    DoTranslateCommand(iterator, frame_index, output_offset);
+  }
+
+  // Read caller's PC from the previous frame.
+  output_offset -= kPointerSize;
+  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
+  output_frame->SetFrameSlot(output_offset, callers_pc);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; caller's pc\n",
+           top_address + output_offset, output_offset, callers_pc);
+  }
+
+  // Read caller's FP from the previous frame, and set this frame's FP.
+  output_offset -= kPointerSize;
+  intptr_t value = output_[frame_index - 1]->GetFp();
+  output_frame->SetFrameSlot(output_offset, value);
+  intptr_t fp_value = top_address + output_offset;
+  output_frame->SetFp(fp_value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; caller's fp\n", fp_value, output_offset, value);
+  }
+
+  // A marker value is used in place of the context.
+  output_offset -= kPointerSize;
+  intptr_t context = reinterpret_cast<intptr_t>(
+      Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+  output_frame->SetFrameSlot(output_offset, context);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; context (adaptor sentinel)\n",
+           top_address + output_offset, output_offset, context);
+  }
+
+  // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(function);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; function\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // Number of incoming arguments.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<uintptr_t>(Smi::FromInt(height - 1));
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; argc (%d)\n",
+           top_address + output_offset, output_offset, value, height - 1);
+  }
+
+  ASSERT(0 == output_offset);
+
+  Builtins* builtins = isolate_->builtins();
+  Code* adaptor_trampoline =
+      builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
+  uintptr_t pc = reinterpret_cast<uintptr_t>(
+      adaptor_trampoline->instruction_start() +
+      isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
+  output_frame->SetPc(pc);
+}
+
+
+void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
+                                              int frame_index) {
+  Builtins* builtins = isolate_->builtins();
+  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
+  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
+  unsigned height = iterator->Next();
+  unsigned height_in_bytes = height * kPointerSize;
+  if (FLAG_trace_deopt) {
+    PrintF("  translating construct stub => height=%d\n", height_in_bytes);
+  }
+
+  unsigned fixed_frame_size = 8 * kPointerSize;
+  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
+
+  // Allocate and store the output frame description.
+  FrameDescription* output_frame =
+      new(output_frame_size) FrameDescription(output_frame_size, function);
+  output_frame->SetFrameType(StackFrame::CONSTRUCT);
+
+  // Construct stub can not be topmost or bottommost.
+  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
+  ASSERT(output_[frame_index] == NULL);
+  output_[frame_index] = output_frame;
+
+  // The top address of the frame is computed from the previous
+  // frame's top and this frame's size.
+  uintptr_t top_address;
+  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+  output_frame->SetTop(top_address);
+
+  // Compute the incoming parameter translation.
+  int parameter_count = height;
+  unsigned output_offset = output_frame_size;
+  for (int i = 0; i < parameter_count; ++i) {
+    output_offset -= kPointerSize;
+    DoTranslateCommand(iterator, frame_index, output_offset);
+  }
+
+  // Read caller's PC from the previous frame.
+  output_offset -= kPointerSize;
+  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
+  output_frame->SetFrameSlot(output_offset, callers_pc);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; caller's pc\n",
+           top_address + output_offset, output_offset, callers_pc);
+  }
+
+  // Read caller's FP from the previous frame, and set this frame's FP.
+  output_offset -= kPointerSize;
+  intptr_t value = output_[frame_index - 1]->GetFp();
+  output_frame->SetFrameSlot(output_offset, value);
+  intptr_t fp_value = top_address + output_offset;
+  output_frame->SetFp(fp_value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; caller's fp\n", fp_value, output_offset, value);
+  }
+
+  // The context can be gotten from the previous frame.
+  output_offset -= kPointerSize;
+  value = output_[frame_index - 1]->GetContext();
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; context\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // A marker value is used in place of the function.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; function (construct sentinel)\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // The output frame reflects a JSConstructStubGeneric frame.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(construct_stub);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; code object\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // Number of incoming arguments.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<uintptr_t>(Smi::FromInt(height - 1));
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; argc (%d)\n",
+           top_address + output_offset, output_offset, value, height - 1);
+  }
+
+  // Constructor function being invoked by the stub.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(function);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; constructor function\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // The newly allocated object was passed as receiver in the artificial
+  // constructor stub environment created by HEnvironment::CopyForInlining().
+  output_offset -= kPointerSize;
+  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; allocated receiver\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  ASSERT(0 == output_offset);
+
+  uintptr_t pc = reinterpret_cast<uintptr_t>(
+      construct_stub->instruction_start() +
+      isolate_->heap()->construct_stub_deopt_pc_offset()->value());
+  output_frame->SetPc(pc);
+}
+
+
+void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
+                                             int frame_index,
+                                             bool is_setter_stub_frame) {
+  JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
+  // The receiver (and the implicit return value, if any) are expected in
+  // registers by the LoadIC/StoreIC, so they don't belong to the output stack
+  // frame. This means that we have to use a height of 0.
+  unsigned height = 0;
+  unsigned height_in_bytes = height * kPointerSize;
+  const char* kind = is_setter_stub_frame ? "setter" : "getter";
+  if (FLAG_trace_deopt) {
+    PrintF("  translating %s stub => height=%u\n", kind, height_in_bytes);
+  }
+
+  // We need 5 stack entries from StackFrame::INTERNAL (lr, fp, cp, frame type,
+  // code object, see MacroAssembler::EnterFrame). For a setter stub frames we
+  // need one additional entry for the implicit return value, see
+  // StoreStubCompiler::CompileStoreViaSetter.
+  unsigned fixed_frame_entries = 5 + (is_setter_stub_frame ? 1 : 0);
+  unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
+  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
+
+  // Allocate and store the output frame description.
+  FrameDescription* output_frame =
+      new(output_frame_size) FrameDescription(output_frame_size, accessor);
+  output_frame->SetFrameType(StackFrame::INTERNAL);
+
+  // A frame for an accessor stub can not be the topmost or bottommost one.
+  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
+  ASSERT(output_[frame_index] == NULL);
+  output_[frame_index] = output_frame;
+
+  // The top address of the frame is computed from the previous frame's top and
+  // this frame's size.
+  uintptr_t top_address = (output_[frame_index - 1]->GetTop() -
+                           output_frame_size);
+  output_frame->SetTop(top_address);
+
+  unsigned output_offset = output_frame_size;
+
+  // Read caller's PC from the previous frame.
+  output_offset -= kPointerSize;
+  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
+  output_frame->SetFrameSlot(output_offset, callers_pc);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
+           " ; caller's pc\n",
+           top_address + output_offset, output_offset, callers_pc);
+  }
+
+  // Read caller's FP from the previous frame, and set this frame's FP.
+  output_offset -= kPointerSize;
+  intptr_t value = output_[frame_index - 1]->GetFp();
+  output_frame->SetFrameSlot(output_offset, value);
+  intptr_t fp_value = top_address + output_offset;
+  output_frame->SetFp(fp_value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
+           " ; caller's fp\n",
+           fp_value, output_offset, value);
+  }
+
+  // The context can be gotten from the previous frame.
+  output_offset -= kPointerSize;
+  value = output_[frame_index - 1]->GetContext();
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
+           " ; context\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // A marker value is used in place of the function.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
+           " ; function (%s sentinel)\n",
+           top_address + output_offset, output_offset, value, kind);
+  }
+
+  // Get Code object from accessor stub.
+  output_offset -= kPointerSize;
+  Builtins::Name name = is_setter_stub_frame ?
+      Builtins::kStoreIC_Setter_ForDeopt :
+      Builtins::kLoadIC_Getter_ForDeopt;
+  Code* accessor_stub = isolate_->builtins()->builtin(name);
+  value = reinterpret_cast<intptr_t>(accessor_stub);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
+           " ; code object\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // Skip receiver.
+  Translation::Opcode opcode =
+      static_cast<Translation::Opcode>(iterator->Next());
+  iterator->Skip(Translation::NumberOfOperandsFor(opcode));
+
+  if (is_setter_stub_frame) {
+    // The implicit return value was part of the artificial setter stub
+    // environment.
+    output_offset -= kPointerSize;
+    DoTranslateCommand(iterator, frame_index, output_offset);
+  }
+
+  ASSERT(0 == output_offset);
+
+  Smi* offset = is_setter_stub_frame ?
+      isolate_->heap()->setter_stub_deopt_pc_offset() :
+      isolate_->heap()->getter_stub_deopt_pc_offset();
+  intptr_t pc = reinterpret_cast<intptr_t>(
+      accessor_stub->instruction_start() + offset->value());
+  output_frame->SetPc(pc);
+}
+
+
+// This code is very similar to ia32 code, but relies on register names (fp, sp)
+// and how the frame is laid out.
+void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
+                                   int frame_index) {
+  // Read the ast node id, function, and frame height for this output frame.
+  BailoutId node_id = BailoutId(iterator->Next());
+  JSFunction* function;
+  if (frame_index != 0) {
+    function = JSFunction::cast(ComputeLiteral(iterator->Next()));
+  } else {
+    int closure_id = iterator->Next();
+    USE(closure_id);
+    ASSERT_EQ(Translation::kSelfLiteralId, closure_id);
+    function = function_;
+  }
+  unsigned height = iterator->Next();
+  unsigned height_in_bytes = height * kPointerSize;
+  if (FLAG_trace_deopt) {
+    PrintF("  translating ");
+    function->PrintName();
+    PrintF(" => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
+  }
+
+  // The 'fixed' part of the frame consists of the incoming parameters and
+  // the part described by JavaScriptFrameConstants.
+  unsigned fixed_frame_size = ComputeFixedSize(function);
+  unsigned input_frame_size = input_->GetFrameSize();
+  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
+
+  // Allocate and store the output frame description.
+  FrameDescription* output_frame =
+      new(output_frame_size) FrameDescription(output_frame_size, function);
+  output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
+
+  bool is_bottommost = (0 == frame_index);
+  bool is_topmost = (output_count_ - 1 == frame_index);
+  ASSERT(frame_index >= 0 && frame_index < output_count_);
+  ASSERT(output_[frame_index] == NULL);
+  output_[frame_index] = output_frame;
+
+  // The top address for the bottommost output frame can be computed from
+  // the input frame pointer and the output frame's height.  For all
+  // subsequent output frames, it can be computed from the previous one's
+  // top address and the current frame's size.
+  uintptr_t top_address;
+  if (is_bottommost) {
+    // 2 = context and function in the frame.
+    top_address =
+        input_->GetRegister(fp.code()) - (2 * kPointerSize) - height_in_bytes;
+  } else {
+    top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+  }
+  output_frame->SetTop(top_address);
+
+  // Compute the incoming parameter translation.
+  int parameter_count = function->shared()->formal_parameter_count() + 1;
+  unsigned output_offset = output_frame_size;
+  unsigned input_offset = input_frame_size;
+  for (int i = 0; i < parameter_count; ++i) {
+    output_offset -= kPointerSize;
+    DoTranslateCommand(iterator, frame_index, output_offset);
+  }
+  input_offset -= (parameter_count * kPointerSize);
+
+  // There are no translation commands for the caller's pc and fp, the
+  // context, and the function.  Synthesize their values and set them up
+  // explicitly.
+  //
+  // The caller's pc for the bottommost output frame is the same as in the
+  // input frame.  For all subsequent output frames, it can be read from the
+  // previous one.  This frame's pc can be computed from the non-optimized
+  // function code and AST id of the bailout.
+  output_offset -= kPointerSize;
+  input_offset -= kPointerSize;
+  intptr_t value;
+  if (is_bottommost) {
+    value = input_->GetFrameSlot(input_offset);
+  } else {
+    value = output_[frame_index - 1]->GetPc();
+  }
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; caller's pc\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // The caller's frame pointer for the bottommost output frame is the same
+  // as in the input frame.  For all subsequent output frames, it can be
+  // read from the previous one.  Also compute and set this frame's frame
+  // pointer.
+  output_offset -= kPointerSize;
+  input_offset -= kPointerSize;
+  if (is_bottommost) {
+    value = input_->GetFrameSlot(input_offset);
+  } else {
+    value = output_[frame_index - 1]->GetFp();
+  }
+  output_frame->SetFrameSlot(output_offset, value);
+  intptr_t fp_value = top_address + output_offset;
+  ASSERT(!is_bottommost || input_->GetRegister(fp.code()) == fp_value);
+  output_frame->SetFp(fp_value);
+  if (is_topmost) {
+    output_frame->SetRegister(fp.code(), fp_value);
+  }
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; caller's fp\n", fp_value, output_offset, value);
+  }
+
+  // For the bottommost output frame the context can be gotten from the input
+  // frame. For all subsequent output frames it can be gotten from the function
+  // so long as we don't inline functions that need local contexts.
+  output_offset -= kPointerSize;
+  input_offset -= kPointerSize;
+  if (is_bottommost) {
+    value = input_->GetFrameSlot(input_offset);
+  } else {
+    value = reinterpret_cast<intptr_t>(function->context());
+  }
+  output_frame->SetFrameSlot(output_offset, value);
+  output_frame->SetContext(value);
+  if (is_topmost) output_frame->SetRegister(cp.code(), value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; context\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // The function was mentioned explicitly in the BEGIN_FRAME.
+  output_offset -= kPointerSize;
+  input_offset -= kPointerSize;
+  value = reinterpret_cast<uintptr_t>(function);
+  // The function for the bottommost output frame should also agree with the
+  // input frame.
+  ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (FLAG_trace_deopt) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR
+           " ; function\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // Translate the rest of the frame.
+  for (unsigned i = 0; i < height; ++i) {
+    output_offset -= kPointerSize;
+    DoTranslateCommand(iterator, frame_index, output_offset);
+  }
+  ASSERT(0 == output_offset);
+
+  // Compute this frame's PC, state, and continuation.
+  Code* non_optimized_code = function->shared()->code();
+  FixedArray* raw_data = non_optimized_code->deoptimization_data();
+  DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
+  Address start = non_optimized_code->instruction_start();
+  unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
+  unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
+  uintptr_t pc_value = reinterpret_cast<uintptr_t>(start + pc_offset);
+  output_frame->SetPc(pc_value);
+#if 0  // applicable on PPC?
+  if (is_topmost) {
+    output_frame->SetRegister(pc.code(), pc_value);
+  }
+#endif
+
+  FullCodeGenerator::State state =
+      FullCodeGenerator::StateField::decode(pc_and_state);
+  output_frame->SetState(Smi::FromInt(state));
+
+
+  // Set the continuation for the topmost frame.
+  if (is_topmost && bailout_type_ != DEBUGGER) {
+    Builtins* builtins = isolate_->builtins();
+    Code* continuation = (bailout_type_ == EAGER)
+        ? builtins->builtin(Builtins::kNotifyDeoptimized)
+        : builtins->builtin(Builtins::kNotifyLazyDeoptimized);
+    output_frame->SetContinuation(
+        reinterpret_cast<uintptr_t>(continuation->entry()));
+  }
+}
+
+
+void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
+  // Set the register values. The values are not important as there are no
+  // callee saved registers in JavaScript frames, so all registers are
+  // spilled. Registers fp and sp are set to the correct values though.
+
+  for (int i = 0; i < Register::kNumRegisters; i++) {
+    input_->SetRegister(i, i * 4);
+  }
+  input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
+  input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
+  for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) {
+    input_->SetDoubleRegister(i, 0.0);
+  }
+
+  // Fill the frame content from the actual data on the frame.
+  for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) {
+    input_->SetFrameSlot(i, reinterpret_cast<intptr_t>(
+                           Memory::Address_at(tos + i)));
+  }
+}
+
+
+#define __ masm()->
+
+// This code tries to be close to ia32 code so that any changes can be
+// easily ported.
+void Deoptimizer::EntryGenerator::Generate() {
+  GeneratePrologue();
+
+  Isolate* isolate = masm()->isolate();
+
+  // Unlike on ARM we don't save all the registers, just the useful ones.
+  // For the rest, there are gaps on the stack, so the offsets remain the same.
+  const int kNumberOfRegisters = Register::kNumRegisters;
+
+  RegList restored_regs = kJSCallerSaved | kCalleeSaved;
+  RegList saved_regs = restored_regs | sp.bit();
+
+  const int kDoubleRegsSize =
+      kDoubleSize * DwVfpRegister::kNumAllocatableRegisters;
+
+  // Save all FPU registers before messing with them.
+  __ subi(sp, sp, Operand(kDoubleRegsSize));
+  for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; ++i) {
+    DwVfpRegister fpu_reg = DwVfpRegister::FromAllocationIndex(i);
+    int offset = i * kDoubleSize;
+    __ stfd(fpu_reg, MemOperand(sp, offset));
+  }
+
+  // Push saved_regs (needed to populate FrameDescription::registers_).
+  // Leave gaps for other registers.
+  __ subi(sp, sp, Operand(kNumberOfRegisters * kPointerSize));
+  for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) {
+    if ((saved_regs & (1 << i)) != 0) {
+      __ StoreP(ToRegister(i), MemOperand(sp, kPointerSize * i));
+    }
+  }
+
+  const int kSavedRegistersAreaSize =
+      (kNumberOfRegisters * kPointerSize) + kDoubleRegsSize;
+
+  // Get the bailout id from the stack.
+  __ LoadP(r5, MemOperand(sp, kSavedRegistersAreaSize));
+
+  // Get the address of the location in the code object if possible (r6) (return
+  // address for lazy deoptimization) and compute the fp-to-sp delta in
+  // register r7.
+  if (type() == EAGER) {
+    __ li(r6, Operand::Zero());
+    // Correct one word for bailout id.
+    __ addi(r7, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
+  } else if (type() == OSR) {
+    __ mflr(r6);
+    // Correct one word for bailout id.
+    __ addi(r7, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
+  } else {
+    __ mflr(r6);
+    // Correct two words for bailout id and return address.
+    __ addi(r7, sp, Operand(kSavedRegistersAreaSize + (2 * kPointerSize)));
+  }
+  __ sub(r7, fp, r7);
+
+  // Allocate a new deoptimizer object.
+  // Pass six arguments in r3 to r8.
+  __ PrepareCallCFunction(6, r8);
+  __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  __ li(r4, Operand(type()));  // bailout type,
+  // r5: bailout id already loaded.
+  // r6: code address or 0 already loaded.
+  // r7: Fp-to-sp delta.
+  __ mov(r8, Operand(ExternalReference::isolate_address()));
+  // Call Deoptimizer::New().
+  {
+    AllowExternalCallThatCantCauseGC scope(masm());
+    __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6);
+  }
+
+  // Preserve "deoptimizer" object in register r3 and get the input
+  // frame descriptor pointer to r4 (deoptimizer->input_);
+  __ LoadP(r4, MemOperand(r3, Deoptimizer::input_offset()));
+
+  // Copy core registers into FrameDescription::registers_[kNumRegisters].
+  ASSERT(Register::kNumRegisters == kNumberOfRegisters);
+  for (int i = 0; i < kNumberOfRegisters; i++) {
+    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
+    __ LoadP(r5, MemOperand(sp, i * kPointerSize));
+    __ StoreP(r5, MemOperand(r4, offset));
+  }
+
+  // Copy VFP registers to
+  // double_registers_[DoubleRegister::kNumAllocatableRegisters]
+  int double_regs_offset = FrameDescription::double_registers_offset();
+  for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; ++i) {
+    int dst_offset = i * kDoubleSize + double_regs_offset;
+    int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
+    __ lfd(d0, MemOperand(sp, src_offset));
+    __ stfd(d0, MemOperand(r4, dst_offset));
+  }
+
+  // Remove the bailout id, eventually return address, and the saved registers
+  // from the stack.
+  if (type() == EAGER || type() == OSR) {
+    __ addi(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
+  } else {
+    __ addi(sp, sp, Operand(kSavedRegistersAreaSize + (2 * kPointerSize)));
+  }
+
+  // Compute a pointer to the unwinding limit in register r5; that is
+  // the first stack slot not part of the input frame.
+  __ LoadP(r5, MemOperand(r4, FrameDescription::frame_size_offset()));
+  __ add(r5, r5, sp);
+
+  // Unwind the stack down to - but not including - the unwinding
+  // limit and copy the contents of the activation frame to the input
+  // frame description.
+  __ addi(r6,  r4, Operand(FrameDescription::frame_content_offset()));
+  Label pop_loop;
+  __ bind(&pop_loop);
+  __ pop(r7);
+  __ StoreP(r7, MemOperand(r6, 0));
+  __ addi(r6, r6, Operand(sizeof(intptr_t)));
+  __ cmp(r5, sp);
+  __ bne(&pop_loop);
+
+  // Compute the output frame in the deoptimizer.
+  __ push(r3);  // Preserve deoptimizer object across call.
+  // r3: deoptimizer object; r4: scratch.
+  __ PrepareCallCFunction(1, r4);
+  // Call Deoptimizer::ComputeOutputFrames().
+  {
+    AllowExternalCallThatCantCauseGC scope(masm());
+    __ CallCFunction(
+        ExternalReference::compute_output_frames_function(isolate), 1);
+  }
+  __ pop(r3);  // Restore deoptimizer object (class Deoptimizer).
+
+  // Replace the current (input) frame with the output frames.
+  Label outer_push_loop, inner_push_loop;
+  // Outer loop state: r3 = current "FrameDescription** output_",
+  // r4 = one past the last FrameDescription**.
+  __ lwz(r4, MemOperand(r3, Deoptimizer::output_count_offset()));
+  __ LoadP(r3, MemOperand(r3, Deoptimizer::output_offset()));  // r3 is output_.
+  __ ShiftLeftImm(r4, r4, Operand(kPointerSizeLog2));
+  __ add(r4, r3, r4);
+  __ bind(&outer_push_loop);
+  // Inner loop state: r5 = current FrameDescription*, r6 = loop index.
+  __ LoadP(r5, MemOperand(r3, 0));  // output_[ix]
+  __ LoadP(r6, MemOperand(r5, FrameDescription::frame_size_offset()));
+
+  __ bind(&inner_push_loop);
+  __ addi(r6, r6, Operand(-sizeof(intptr_t)));
+  __ add(r9, r5, r6);
+  __ LoadP(r10, MemOperand(r9, FrameDescription::frame_content_offset()));
+  __ push(r10);
+  __ cmpi(r6, Operand::Zero());
+  __ bne(&inner_push_loop);  // test for gt?
+
+  __ addi(r3, r3, Operand(kPointerSize));
+  __ cmp(r3, r4);
+  __ blt(&outer_push_loop);
+
+  // Push state, pc, and continuation from the last output frame.
+  if (type() != OSR) {
+    __ LoadP(r9, MemOperand(r5, FrameDescription::state_offset()));
+    __ push(r9);
+  }
+
+  __ LoadP(r9, MemOperand(r5, FrameDescription::pc_offset()));
+  __ push(r9);
+  __ LoadP(r9, MemOperand(r5, FrameDescription::continuation_offset()));
+  __ push(r9);
+
+  // Restore the registers from the last output frame.
+  ASSERT(!(ip.bit() & restored_regs));
+  __ mr(ip, r5);
+  for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
+    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
+    if ((restored_regs & (1 << i)) != 0) {
+      __ LoadP(ToRegister(i), MemOperand(ip, offset));
+    }
+  }
+
+  __ InitializeRootRegister();
+
+  __ pop(r10);  // get continuation, leave pc on stack
+  __ pop(r0);
+  __ mtlr(r0);
+  __ Jump(r10);
+  __ stop("Unreachable.");
+}
+
+
+void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
+  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
+
+  // Create a sequence of deoptimization entries. Note that any
+  // registers may be still live.
+  Label done;
+  for (int i = 0; i < count(); i++) {
+    int start = masm()->pc_offset();
+    USE(start);
+    if (type() == EAGER) {
+      __ nop();
+      __ nop();
+    } else {
+      // Emulate ia32 like call by pushing return address to stack.
+      __ mflr(r0);
+      __ push(r0);
+    }
+    __ li(ip, Operand(i));
+    __ push(ip);
+    __ b(&done);
+    ASSERT(masm()->pc_offset() - start == table_entry_size_);
+  }
+  __ bind(&done);
+}
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/src/ppc/disasm-ppc.cc b/src/ppc/disasm-ppc.cc
new file mode 100644
index 0000000..5a1e902
--- /dev/null
+++ b/src/ppc/disasm-ppc.cc
@@ -0,0 +1,1339 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A Disassembler object is used to disassemble a block of code instruction by
+// instruction. The default implementation of the NameConverter object can be
+// overriden to modify register names or to do symbol lookup on addresses.
+//
+// The example below will disassemble a block of code and print it to stdout.
+//
+//   NameConverter converter;
+//   Disassembler d(converter);
+//   for (byte* pc = begin; pc < end;) {
+//     v8::internal::EmbeddedVector<char, 256> buffer;
+//     byte* prev_pc = pc;
+//     pc += d.InstructionDecode(buffer, pc);
+//     printf("%p    %08x      %s\n",
+//            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
+//   }
+//
+// The Disassembler class also has a convenience method to disassemble a block
+// of code into a FILE*, meaning that the above functionality could also be
+// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#ifndef WIN32
+#include <stdint.h>
+#endif
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "constants-ppc.h"
+#include "disasm.h"
+#include "macro-assembler.h"
+#include "platform.h"
+
+
+namespace v8 {
+namespace internal {
+
+
+//------------------------------------------------------------------------------
+
+// Decoder decodes and disassembles instructions into an output buffer.
+// It uses the converter to convert register names and call destinations into
+// more informative description.
+class Decoder {
+ public:
+  Decoder(const disasm::NameConverter& converter,
+          Vector<char> out_buffer)
+    : converter_(converter),
+      out_buffer_(out_buffer),
+      out_buffer_pos_(0) {
+    out_buffer_[out_buffer_pos_] = '\0';
+  }
+
+  ~Decoder() {}
+
+  // Writes one disassembled instruction into 'buffer' (0-terminated).
+  // Returns the length of the disassembled machine instruction in bytes.
+  int InstructionDecode(byte* instruction);
+
+ private:
+  // Bottleneck functions to print into the out_buffer.
+  void PrintChar(const char ch);
+  void Print(const char* str);
+
+  // Printing of common values.
+  void PrintRegister(int reg);
+  void PrintDRegister(int reg);
+  int FormatFPRegister(Instruction* instr, const char* format);
+  void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
+
+  // Handle formatting of instructions and their options.
+  int FormatRegister(Instruction* instr, const char* option);
+  int FormatOption(Instruction* instr, const char* option);
+  void Format(Instruction* instr, const char* format);
+  void Unknown(Instruction* instr);
+  void UnknownFormat(Instruction* instr, const char* opcname);
+  void MarkerFormat(Instruction* instr, const char* opcname, int id);
+
+  // PowerPC decoding
+  void DecodeExt1(Instruction* instr);
+  void DecodeExt2(Instruction* instr);
+  void DecodeExt4(Instruction* instr);
+  void DecodeExt5(Instruction* instr);
+
+  const disasm::NameConverter& converter_;
+  Vector<char> out_buffer_;
+  int out_buffer_pos_;
+
+  DISALLOW_COPY_AND_ASSIGN(Decoder);
+};
+
+
+// Support for assertions in the Decoder formatting functions.
+#define STRING_STARTS_WITH(string, compare_string) \
+  (strncmp(string, compare_string, strlen(compare_string)) == 0)
+
+
+// Append the ch to the output buffer.
+void Decoder::PrintChar(const char ch) {
+  out_buffer_[out_buffer_pos_++] = ch;
+}
+
+
+// Append the str to the output buffer.
+void Decoder::Print(const char* str) {
+  char cur = *str++;
+  while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
+    PrintChar(cur);
+    cur = *str++;
+  }
+  out_buffer_[out_buffer_pos_] = 0;
+}
+
+// Print the register name according to the active name converter.
+void Decoder::PrintRegister(int reg) {
+  Print(converter_.NameOfCPURegister(reg));
+}
+
+// Print the double FP register name according to the active name converter.
+void Decoder::PrintDRegister(int reg) {
+  Print(FPRegisters::Name(reg));
+}
+
+// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
+// the FormatOption method.
+void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
+  switch (svc) {
+    case kCallRtRedirected:
+      Print("call rt redirected");
+      return;
+    case kBreakpoint:
+      Print("breakpoint");
+      return;
+    default:
+      if (svc >= kStopCode) {
+        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                        "%d - 0x%x",
+                                        svc & kStopCodeMask,
+                                        svc & kStopCodeMask);
+      } else {
+        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                        "%d",
+                                        svc);
+      }
+      return;
+  }
+}
+
+// Handle all register based formatting in this function to reduce the
+// complexity of FormatOption.
+int Decoder::FormatRegister(Instruction* instr, const char* format) {
+  ASSERT(format[0] == 'r');
+
+  if ((format[1] == 't') || (format[1] == 's')) {  // 'rt & 'rs register
+    int reg = instr->RTValue();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'a') {  // 'ra: RA register
+    int reg = instr->RAValue();
+    PrintRegister(reg);
+    return 2;
+  } else if (format[1] == 'b') {  // 'rb: RB register
+    int reg = instr->RBValue();
+    PrintRegister(reg);
+    return 2;
+  }
+
+  UNREACHABLE();
+  return -1;
+}
+
+
+// Handle all FP register based formatting in this function to reduce the
+// complexity of FormatOption.
+int Decoder::FormatFPRegister(Instruction* instr, const char* format) {
+  ASSERT(format[0] == 'D');
+
+  int retval = 2;
+  int reg = -1;
+  if (format[1] == 't') {
+    reg = instr->RTValue();
+  } else if (format[1] == 'a') {
+    reg = instr->RAValue();
+  } else if (format[1] == 'b') {
+    reg = instr->RBValue();
+  } else if (format[1] == 'c') {
+    reg = instr->RCValue();
+  } else {
+    UNREACHABLE();
+  }
+
+  PrintDRegister(reg);
+
+  return retval;
+}
+
+// FormatOption takes a formatting string and interprets it based on
+// the current instructions. The format string points to the first
+// character of the option string (the option escape has already been
+// consumed by the caller.)  FormatOption returns the number of
+// characters that were consumed from the formatting string.
+int Decoder::FormatOption(Instruction* instr, const char* format) {
+  switch (format[0]) {
+    case 'o': {
+      if (instr->Bit(10) == 1) {
+        Print("o");
+      }
+      return 1;
+    }
+    case '.': {
+      if (instr->Bit(0) == 1) {
+        Print(".");
+      } else {
+        Print(" ");  // ensure consistent spacing
+      }
+      return 1;
+    }
+    case 'r': {
+      return FormatRegister(instr, format);
+    }
+    case 'D': {
+      return FormatFPRegister(instr, format);
+    }
+    case 'i': {  // int16
+      int32_t value = (instr->Bits(15, 0) << 16) >> 16;
+      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                      "%d", value);
+      return 5;
+    }
+    case 'u': {  // uint16
+      int32_t value = instr->Bits(15, 0);
+      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                      "%d", value);
+      return 6;
+    }
+    case 'l': {
+      // Link (LK) Bit 0
+      if (instr->Bit(0) == 1) {
+        Print("l");
+      }
+      return 1;
+    }
+    case 'a': {
+      // Absolute Address Bit 1
+      if (instr->Bit(1) == 1) {
+        Print("a");
+      }
+      return 1;
+    }
+    case 't': {  // 'target: target of branch instructions
+      // target26 or target16
+      ASSERT(STRING_STARTS_WITH(format, "target"));
+      if ((format[6] == '2') && (format[7] == '6')) {
+        int off = ((instr->Bits(25, 2)) << 8) >> 6;
+        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                        "%+d -> %s",
+                                        off,
+                                        converter_.NameOfAddress(
+                                        reinterpret_cast<byte*>(instr) + off));
+        return 8;
+      } else if ((format[6] == '1') && (format[7] == '6')) {
+        int off = ((instr->Bits(15, 2)) << 18) >> 16;
+        out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                        "%+d -> %s",
+                                        off,
+                                        converter_.NameOfAddress(
+                                        reinterpret_cast<byte*>(instr) + off));
+        return 8;
+      }
+     case 's': {
+       ASSERT(format[1] == 'h');
+       int32_t value = 0;
+       int32_t opcode = instr->OpcodeValue() << 26;
+       int32_t sh = instr->Bits(15, 11);
+       if (opcode == EXT5 ||
+           (opcode == EXT2 &&
+            instr->Bits(10, 2) << 2 == SRADIX)) {
+         // SH Bits 1 and 15-11 (split field)
+         value = (sh | (instr->Bit(1) << 5));
+       } else {
+         // SH Bits 15-11
+         value = (sh << 26) >> 26;
+       }
+       out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                     "%d", value);
+       return 2;
+     }
+     case 'm': {
+       int32_t value = 0;
+       if (format[1] == 'e') {
+         if (instr->OpcodeValue() << 26 != EXT5) {
+           // ME Bits 10-6
+           value = (instr->Bits(10, 6) << 26) >> 26;
+         } else {
+           // ME Bits 5 and 10-6 (split field)
+           value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
+         }
+       } else if (format[1] == 'b') {
+         if (instr->OpcodeValue() << 26 != EXT5) {
+           // MB Bits 5-1
+           value = (instr->Bits(5, 1) << 26) >> 26;
+         } else {
+           // MB Bits 5 and 10-6 (split field)
+           value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
+         }
+       } else {
+         UNREACHABLE();  // bad format
+       }
+       out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                     "%d", value);
+       return 2;
+     }
+    }
+#if V8_TARGET_ARCH_PPC64
+    case 'd': {  // ds value for offset
+      int32_t value = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
+      out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                      "%d", value);
+      return 1;
+    }
+#endif
+    default: {
+      UNREACHABLE();
+      break;
+    }
+  }
+
+  UNREACHABLE();
+  return -1;
+}
+
+
+// Format takes a formatting string for a whole instruction and prints it into
+// the output buffer. All escaped options are handed to FormatOption to be
+// parsed further.
+void Decoder::Format(Instruction* instr, const char* format) {
+  char cur = *format++;
+  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
+    if (cur == '\'') {  // Single quote is used as the formatting escape.
+      format += FormatOption(instr, format);
+    } else {
+      out_buffer_[out_buffer_pos_++] = cur;
+    }
+    cur = *format++;
+  }
+  out_buffer_[out_buffer_pos_]  = '\0';
+}
+
+
+// The disassembler may end up decoding data inlined in the code. We do not want
+// it to crash if the data does not ressemble any known instruction.
+#define VERIFY(condition) \
+  if (!(condition)) {     \
+    Unknown(instr);       \
+    return;               \
+  }
+
+
+// For currently unimplemented decodings the disassembler calls Unknown(instr)
+// which will just print "unknown" of the instruction bits.
+void Decoder::Unknown(Instruction* instr) {
+  Format(instr, "unknown");
+}
+
+// For currently unimplemented decodings the disassembler calls
+// UnknownFormat(instr) which will just print opcode name of the
+// instruction bits.
+void Decoder::UnknownFormat(Instruction* instr, const char* name) {
+  char buffer[100];
+  snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name);
+  Format(instr, buffer);
+}
+
+void Decoder::MarkerFormat(Instruction* instr, const char* name, int id) {
+  char buffer[100];
+  snprintf(buffer, sizeof(buffer), "%s %d", name, id);
+  Format(instr, buffer);
+}
+
+// PowerPC
+void Decoder::DecodeExt1(Instruction* instr) {
+  switch (instr->Bits(10, 1) << 1) {
+    case MCRF: {
+      UnknownFormat(instr, "mcrf");  // not used by V8
+      break;
+    }
+    case BCLRX: {
+      switch (instr->Bits(25, 21) << 21) {
+        case DCBNZF: {
+          UnknownFormat(instr, "bclrx-dcbnzf");
+          break;
+        }
+        case DCBEZF: {
+          UnknownFormat(instr, "bclrx-dcbezf");
+          break;
+        }
+        case BF: {
+          UnknownFormat(instr, "bclrx-bf");
+          break;
+        }
+        case DCBNZT: {
+          UnknownFormat(instr, "bclrx-dcbbzt");
+          break;
+        }
+        case DCBEZT: {
+          UnknownFormat(instr, "bclrx-dcbnezt");
+          break;
+        }
+        case BT: {
+          UnknownFormat(instr, "bclrx-bt");
+          break;
+        }
+        case DCBNZ: {
+          UnknownFormat(instr, "bclrx-dcbnz");
+          break;
+        }
+        case DCBEZ: {
+          UnknownFormat(instr, "bclrx-dcbez");  // not used by V8
+          break;
+        }
+        case BA: {
+          if (instr->Bit(0) == 1) {
+            Format(instr, "blrl");
+          } else {
+            Format(instr, "blr");
+          }
+          break;
+        }
+      }
+      break;
+    }
+    case BCCTRX: {
+      switch (instr->Bits(25, 21) << 21) {
+        case DCBNZF: {
+          UnknownFormat(instr, "bcctrx-dcbnzf");
+          break;
+        }
+        case DCBEZF: {
+          UnknownFormat(instr, "bcctrx-dcbezf");
+          break;
+        }
+        case BF: {
+          UnknownFormat(instr, "bcctrx-bf");
+          break;
+        }
+        case DCBNZT: {
+          UnknownFormat(instr, "bcctrx-dcbnzt");
+          break;
+        }
+        case DCBEZT: {
+          UnknownFormat(instr, "bcctrx-dcbezf");
+          break;
+        }
+        case BT: {
+          UnknownFormat(instr, "bcctrx-bt");
+          break;
+        }
+        case DCBNZ: {
+          UnknownFormat(instr, "bcctrx-dcbnz");
+          break;
+        }
+        case DCBEZ: {
+          UnknownFormat(instr, "bcctrx-dcbez");
+          break;
+        }
+        case BA: {
+          if (instr->Bit(0) == 1) {
+            Format(instr, "bctrl");
+          } else {
+            Format(instr, "bctr");
+          }
+          break;
+        }
+        default: {
+          UNREACHABLE();
+        }
+      }
+      break;
+    }
+    case CRNOR: {
+      Format(instr, "crnor (stuff)");
+      break;
+    }
+    case RFI: {
+      Format(instr, "rfi (stuff)");
+      break;
+    }
+    case CRANDC: {
+      Format(instr, "crandc (stuff)");
+      break;
+    }
+    case ISYNC: {
+      Format(instr, "isync (stuff)");
+      break;
+    }
+    case CRXOR: {
+      Format(instr, "crxor (stuff)");
+      break;
+    }
+    case CRNAND: {
+      UnknownFormat(instr, "crnand");
+      break;
+    }
+    case CRAND: {
+      UnknownFormat(instr, "crand");
+      break;
+    }
+    case CREQV: {
+      UnknownFormat(instr, "creqv");
+      break;
+    }
+    case CRORC: {
+      UnknownFormat(instr, "crorc");
+      break;
+    }
+    case CROR: {
+      UnknownFormat(instr, "cror");
+      break;
+    }
+    default: {
+      Unknown(instr);  // not used by V8
+    }
+  }
+}
+
+void Decoder::DecodeExt2(Instruction* instr) {
+  // Some encodings are 10-1 bits, handle those first
+  switch (instr->Bits(10, 1) << 1) {
+    case SRWX: {
+      Format(instr, "srw'.    'ra, 'rs, 'rb");
+      return;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case SRDX: {
+      Format(instr, "srd'.    'ra, 'rs, 'rb");
+      return;
+    }
+#endif
+    case SRAW: {
+      Format(instr, "sraw'.   'ra, 'rs, 'rb");
+      return;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case SRAD: {
+      Format(instr, "srad'.   'ra, 'rs, 'rb");
+      return;
+    }
+#endif
+    case SRAWIX: {
+      Format(instr, "srawi'.  'ra,'rs,'sh");
+      return;
+    }
+    case EXTSH: {
+      Format(instr, "extsh'.  'ra, 'rs");
+      return;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case EXTSW: {
+      Format(instr, "extsw'.  'ra, 'rs");
+      return;
+    }
+#endif
+    case EXTSB: {
+      Format(instr, "extsb'.  'ra, 'rs");
+      return;
+    }
+    case LFSX: {
+      Format(instr, "lfsx    'rt, 'ra, 'rb");
+      return;
+    }
+    case LFSUX: {
+      Format(instr, "lfsux   'rt, 'ra, 'rb");
+      return;
+    }
+    case LFDX: {
+      Format(instr, "lfdx    'rt, 'ra, 'rb");
+      return;
+    }
+    case LFDUX: {
+      Format(instr, "lfdux   'rt, 'ra, 'rb");
+      return;
+    }
+    case STFSX: {
+      Format(instr, "stfsx    'rs, 'ra, 'rb");
+      return;
+    }
+    case STFSUX: {
+      Format(instr, "stfsux   'rs, 'ra, 'rb");
+      return;
+    }
+    case STFDX: {
+      Format(instr, "stfdx    'rs, 'ra, 'rb");
+      return;
+    }
+    case STFDUX: {
+      Format(instr, "stfdux   'rs, 'ra, 'rb");
+      return;
+    }
+  }
+
+  switch (instr->Bits(10, 2) << 2) {
+    case SRADIX: {
+      Format(instr, "sradi'.  'ra,'rs,'sh");
+      return;
+    }
+  }
+
+  // ?? are all of these xo_form?
+  switch (instr->Bits(9, 1) << 1) {
+    case CMP: {
+      Format(instr, "cmp     'ra, 'rb");
+      break;
+    }
+    case SLWX: {
+      Format(instr, "slw'.   'ra, 'rs, 'rb");
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case SLDX: {
+      Format(instr, "sld'.   'ra, 'rs, 'rb");
+      break;
+    }
+#endif
+    case SUBFCX: {
+      Format(instr, "subfc'. 'rt, 'ra, 'rb");
+      break;
+    }
+    case ADDCX: {
+      Format(instr, "addc'.   'rt, 'ra, 'rb");
+      break;
+    }
+    case CNTLZWX: {
+      Format(instr, "cntlzw'. 'ra, 'rs");
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case CNTLZDX: {
+      Format(instr, "cntlzd'. 'ra, 'rs");
+      break;
+    }
+#endif
+    case ANDX: {
+      Format(instr, "and'.    'ra, 'rs, 'rb");
+      break;
+    }
+    case ANDCX: {
+      Format(instr, "andc'.   'ra, 'rs, 'rb");
+      break;
+    }
+    case CMPL: {
+      Format(instr, "cmpl    'ra, 'rb");
+      break;
+    }
+    case NEGX: {
+      Format(instr, "neg'.    'rt, 'ra");
+      break;
+    }
+    case NORX: {
+      Format(instr, "nor'.    'rt, 'ra, 'rb");
+      break;
+    }
+    case SUBFX: {
+      Format(instr, "subf'.   'rt, 'ra, 'rb");
+      break;
+    }
+    case MULHWX: {
+      Format(instr, "mulhw'o'.  'rt, 'ra, 'rb");
+      break;
+    }
+    case ADDZEX: {
+      Format(instr, "addze'.   'rt, 'ra");
+      break;
+    }
+    case MULLW: {
+      Format(instr, "mullw'o'.  'rt, 'ra, 'rb");
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case MULLD: {
+      Format(instr, "mulld'o'.  'rt, 'ra, 'rb");
+      break;
+    }
+#endif
+    case DIVW: {
+      Format(instr, "divw'o'.   'rt, 'ra, 'rb");
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case DIVD: {
+      Format(instr, "divd'o'.   'rt, 'ra, 'rb");
+      break;
+    }
+#endif
+    case ADDX: {
+      Format(instr, "add'o     'rt, 'ra, 'rb");
+      break;
+    }
+    case XORX: {
+      Format(instr, "xor'.    'ra, 'rs, 'rb");
+      break;
+    }
+    case ORX: {
+      if ( instr->RTValue() == instr->RBValue() ) {
+        Format(instr, "mr      'ra, 'rb");
+      } else {
+        Format(instr, "or      'ra, 'rs, 'rb");
+      }
+      break;
+    }
+    case MFSPR: {
+      int spr = instr->Bits(20, 11);
+      if (256 == spr) {
+        Format(instr, "mflr    'rt");
+      } else {
+        Format(instr, "mfspr   'rt ??");
+      }
+      break;
+    }
+    case MTSPR: {
+      int spr = instr->Bits(20, 11);
+      if (256 == spr) {
+        Format(instr, "mtlr    'rt");
+      } else if (288 == spr) {
+        Format(instr, "mtctr   'rt");
+      } else {
+        Format(instr, "mtspr   'rt ??");
+      }
+      break;
+    }
+    case MFCR: {
+      Format(instr, "mfcr    'rt");
+      break;
+    }
+    case STWX: {
+      Format(instr, "stwx    'rs, 'ra, 'rb");
+      break;
+    }
+    case STWUX: {
+      Format(instr, "stwux   'rs, 'ra, 'rb");
+      break;
+    }
+    case STBX: {
+      Format(instr, "stbx    'rs, 'ra, 'rb");
+      break;
+    }
+    case STBUX: {
+      Format(instr, "stbux   'rs, 'ra, 'rb");
+      break;
+    }
+    case STHX: {
+      Format(instr, "sthx    'rs, 'ra, 'rb");
+      break;
+    }
+    case STHUX: {
+      Format(instr, "sthux   'rs, 'ra, 'rb");
+      break;
+    }
+    case LWZX: {
+      Format(instr, "lwzx    'rt, 'ra, 'rb");
+      break;
+    }
+    case LWZUX: {
+      Format(instr, "lwzux   'rt, 'ra, 'rb");
+      break;
+    }
+    case LBZX: {
+      Format(instr, "lbzx    'rt, 'ra, 'rb");
+      break;
+    }
+    case LBZUX: {
+      Format(instr, "lbzux   'rt, 'ra, 'rb");
+      break;
+    }
+    case LHZX: {
+      Format(instr, "lhzx    'rt, 'ra, 'rb");
+      break;
+    }
+    case LHZUX: {
+      Format(instr, "lhzux   'rt, 'ra, 'rb");
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case LDX: {
+      Format(instr, "ldx     'rt, 'ra, 'rb");
+      break;
+    }
+    case LDUX: {
+      Format(instr, "ldux    'rt, 'ra, 'rb");
+      break;
+    }
+    case STDX: {
+      Format(instr, "stdx    'rt, 'ra, 'rb");
+      break;
+    }
+    case STDUX: {
+      Format(instr, "stdux   'rt, 'ra, 'rb");
+      break;
+    }
+#endif
+    default: {
+      Unknown(instr);  // not used by V8
+    }
+  }
+}
+
+void Decoder::DecodeExt4(Instruction* instr) {
+  switch (instr->Bits(5, 1) << 1) {
+    case FDIV: {
+      Format(instr, "fdiv'.   'Dt, 'Da, 'Db");
+      return;
+    }
+    case FSUB: {
+      Format(instr, "fsub'.   'Dt, 'Da, 'Db");
+      return;
+    }
+    case FADD: {
+      Format(instr, "fadd'.   'Dt, 'Da, 'Db");
+      return;
+    }
+    case FSQRT: {
+      Format(instr, "fsqrt'.  'Dt, 'Db");
+      return;
+    }
+    case FSEL: {
+      Format(instr, "fsel'.   'Dt, 'Da, 'Dc, 'Db");
+      return;
+    }
+    case FMUL: {
+      Format(instr, "fmul'.   'Dt, 'Da, 'Dc");
+      return;
+    }
+  }
+
+  switch (instr->Bits(10, 1) << 1) {
+    case FCMPU: {
+      Format(instr, "fcmpu   'Da, 'Db");
+      break;
+    }
+    case FRSP: {
+      Format(instr, "frsp'.   'Dt, 'Db");
+      break;
+    }
+    case FCFID: {
+      Format(instr, "fcfid'.  'Dt, 'Db");
+      break;
+    }
+    case FCTID: {
+      Format(instr, "fctid   'Dt, 'Db");
+      break;
+    }
+    case FCTIDZ: {
+      Format(instr, "fctidz  'Dt, 'Db");
+      break;
+    }
+    case FCTIW: {
+      Format(instr, "fctiw'. 'Dt, 'Db");
+      break;
+    }
+    case FCTIWZ: {
+      Format(instr, "fctiwz'. 'Dt, 'Db");
+      break;
+    }
+    case FMR: {
+      Format(instr, "fmr'.    'Dt, 'Db");
+      break;
+    }
+    case MTFSFI: {
+      Format(instr, "mtfsfi'.  ?,?");
+      break;
+    }
+    case MFFS: {
+      Format(instr, "mffs'.   'Dt");
+      break;
+    }
+    case MTFSF: {
+      Format(instr, "mtfsf'.  'Db ?,?,?");
+      break;
+    }
+    case FABS: {
+      Format(instr, "fabs'.   'Dt, 'Db");
+      break;
+    }
+    case FRIM: {
+      Format(instr, "frim    'Dt, 'Db");
+      break;
+    }
+    case FNEG: {
+      Format(instr, "fneg'.   'Dt, 'Db");
+      break;
+    }
+    default: {
+      Unknown(instr);  // not used by V8
+    }
+  }
+}
+
+void Decoder::DecodeExt5(Instruction* instr) {
+  switch (instr->Bits(4, 2) << 2) {
+    case RLDICL: {
+      Format(instr, "rldicl'. 'ra, 'rs, 'sh, 'mb");
+      break;
+    }
+    case RLDICR: {
+      Format(instr, "rldicr'. 'ra, 'rs, 'sh, 'me");
+      break;
+    }
+    case RLDIC: {
+      Format(instr, "rldic'.  'ra, 'rs, 'sh, 'mb");
+      break;
+    }
+    case RLDIMI: {
+      Format(instr, "rldimi'. 'ra, 'rs, 'sh, 'mb");
+      break;
+    }
+    default: {
+      Unknown(instr);  // not used by V8
+    }
+  }
+}
+
+#undef VERIFIY
+
+// Disassemble the instruction at *instr_ptr into the output buffer.
+int Decoder::InstructionDecode(byte* instr_ptr) {
+  Instruction* instr = Instruction::At(instr_ptr);
+  // Print raw instruction bytes.
+  out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                  "%08x       ",
+                                  instr->InstructionBits());
+
+    switch (instr->OpcodeValue() << 26) {
+    case TWI: {
+      PrintSoftwareInterrupt(instr->SvcValue());
+      break;
+    }
+    case MULLI: {
+      UnknownFormat(instr, "mulli");
+      break;
+    }
+    case SUBFIC: {
+      Format(instr, "subfic  'rt, 'ra, 'int16");
+      break;
+    }
+    case CMPLI: {
+      Format(instr, "cmpli   'ra, 'uint16");
+      break;
+    }
+    case CMPI: {
+      Format(instr, "cmpi    'ra, 'int16");
+      break;
+    }
+    case ADDIC: {
+      Format(instr, "addic   'rt, 'ra, 'int16");
+      break;
+    }
+    case ADDICx: {
+      UnknownFormat(instr, "addicx");
+      break;
+    }
+    case ADDI: {
+      if ( instr->RAValue() == 0 ) {
+        // this is load immediate
+        Format(instr, "li      'rt, 'int16");
+      } else {
+        Format(instr, "addi    'rt, 'ra, 'int16");
+      }
+      break;
+    }
+    case ADDIS: {
+      if ( instr->RAValue() == 0 ) {
+        Format(instr, "lis     'rt, 'int16");
+      } else {
+        Format(instr, "addis   'rt, 'ra, 'int16");
+      }
+      break;
+    }
+    case BCX: {
+      int bo = instr->Bits(25, 21) << 21;
+      int bi = instr->Bits(20, 16);
+      switch (bi) {
+        case 2:
+        case 30:
+          if (BT == bo) {
+            Format(instr, "beq'l'a 'target16");
+            break;
+          }
+          if (BF == bo) {
+            Format(instr, "bne'l'a 'target16");
+            break;
+          }
+          Format(instr, "bc'l'a 'target16");
+          break;
+        case 29:
+          if (BT == bo) {
+            Format(instr, "bgt'l'a 'target16");
+            break;
+          }
+          if (BF == bo) {
+            Format(instr, "ble'l'a 'target16");
+            break;
+          }
+          Format(instr, "bc'l'a 'target16");
+          break;
+        case 28:
+          if (BT == bo) {
+            Format(instr, "blt'l'a 'target16");
+            break;
+          }
+          if (BF == bo) {
+            Format(instr, "bge'l'a 'target16");
+            break;
+          }
+          Format(instr, "bc'l'a 'target16");
+          break;
+        default:
+          Format(instr, "bc'l'a 'target16");
+          break;
+      }
+      break;
+    }
+    case SC: {
+      UnknownFormat(instr, "sc");
+      break;
+    }
+    case BX: {
+      Format(instr, "b'l'a 'target26");
+      break;
+    }
+    case EXT1: {
+      DecodeExt1(instr);
+      break;
+    }
+    case RLWIMIX: {
+      Format(instr, "rlwimi'. 'ra, 'rs, 'sh, 'me, 'mb");
+      break;
+    }
+    case RLWINMX: {
+      Format(instr, "rlwinm'. 'ra, 'rs, 'sh, 'me, 'mb");
+      break;
+    }
+    case RLWNMX: {
+      UnknownFormat(instr, "rlwnmx");
+      break;
+    }
+    case ORI: {
+      Format(instr, "ori     'ra, 'rs, 'uint16");
+      break;
+    }
+    case ORIS: {
+      Format(instr, "oris    'ra, 'rs, 'uint16");
+      break;
+    }
+    case XORI: {
+      Format(instr, "xori    'ra, 'rs, 'uint16");
+      break;
+    }
+    case XORIS: {
+      Format(instr, "xoris   'ra, 'rs, 'uint16");
+      break;
+    }
+    case ANDIx: {
+      Format(instr, "andi.   'ra, 'rs, 'uint16");
+      break;
+    }
+    case ANDISx: {
+      Format(instr, "andis.  'ra, 'rs, 'uint16");
+      break;
+    }
+    case EXT2: {
+      DecodeExt2(instr);
+      break;
+    }
+    case LWZ: {
+      Format(instr, "lwz     'rt, 'int16('ra)");
+      break;
+    }
+    case LWZU: {
+      Format(instr, "lwzu    'rt, 'int16('ra)");
+      break;
+    }
+    case LBZ: {
+      Format(instr, "lbz     'rt, 'int16('ra)");
+      break;
+    }
+    case LBZU: {
+      Format(instr, "lbzu    'rt, 'int16('ra)");
+      break;
+    }
+    case STW: {
+      Format(instr, "stw     'rs, 'int16('ra)");
+      break;
+    }
+    case STWU: {
+      Format(instr, "stwu    'rs, 'int16('ra)");
+      break;
+    }
+    case STB: {
+      Format(instr, "stb     'rs, 'int16('ra)");
+      break;
+    }
+    case STBU: {
+      Format(instr, "stbu    'rs, 'int16('ra)");
+      break;
+    }
+    case LHZ: {
+      Format(instr, "lhz     'rt, 'int16('ra)");
+      break;
+    }
+    case LHZU: {
+      Format(instr, "lhzu    'rt, 'int16('ra)");
+      break;
+    }
+    case LHA: {
+      Format(instr, "lha     'rt, 'int16('ra)");
+      break;
+    }
+    case LHAU: {
+      Format(instr, "lhau    'rt, 'int16('ra)");
+      break;
+    }
+    case STH: {
+      Format(instr, "sth 'rs, 'int16('ra)");
+      break;
+    }
+    case STHU: {
+      Format(instr, "sthu 'rs, 'int16('ra)");
+      break;
+    }
+    case LMW: {
+      UnknownFormat(instr, "lmw");
+      break;
+    }
+    case STMW: {
+      UnknownFormat(instr, "stmw");
+      break;
+    }
+    case LFS: {
+      Format(instr, "lfs     'Dt, 'int16('ra)");
+      break;
+    }
+    case LFSU: {
+      Format(instr, "lfsu    'Dt, 'int16('ra)");
+      break;
+    }
+    case LFD: {
+      Format(instr, "lfd     'Dt, 'int16('ra)");
+      break;
+    }
+    case LFDU: {
+      Format(instr, "lfdu    'Dt, 'int16('ra)");
+      break;
+    }
+    case STFS: {
+      Format(instr, "stfs    'Dt, 'int16('ra)");
+      break;
+    }
+    case STFSU: {
+      Format(instr, "stfsu   'Dt, 'int16('ra)");
+      break;
+    }
+    case STFD: {
+      Format(instr, "stfd    'Dt, 'int16('ra)");
+      break;
+    }
+    case STFDU: {
+      Format(instr, "stfdu   'Dt, 'int16('ra)");
+      break;
+    }
+    case EXT3:
+    case EXT4: {
+      DecodeExt4(instr);
+      break;
+    }
+    case EXT5: {
+      DecodeExt5(instr);
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case LD: {
+      switch (instr->Bits(1, 0)) {
+        case 0:
+          Format(instr, "ld      'rt, 'd('ra)");
+          break;
+        case 1:
+          Format(instr, "ldu     'rt, 'd('ra)");
+          break;
+        case 2:
+          Format(instr, "lwa     'rt, 'd('ra)");
+          break;
+      }
+      break;
+    }
+    case STD: {  // could be STD or STDU
+      if (instr->Bit(0) == 0) {
+        Format(instr, "std     'rs, 'd('ra)");
+      } else {
+        Format(instr, "stdu    'rs, 'd('ra)");
+      }
+      break;
+    }
+#endif
+
+    case FAKE_OPCODE: {
+      if (instr->Bits(MARKER_SUBOPCODE_BIT, MARKER_SUBOPCODE_BIT) == 1) {
+        int marker_code = instr->Bits(STUB_MARKER_HIGH_BIT, 0);
+        ASSERT(marker_code < F_NEXT_AVAILABLE_STUB_MARKER);
+        MarkerFormat(instr, "stub-marker ", marker_code);
+      } else {
+        int fake_opcode = instr->Bits(FAKE_OPCODE_HIGH_BIT, 0);
+        MarkerFormat(instr, "faker-opcode ", fake_opcode);
+      }
+      break;
+    }
+    default: {
+      Unknown(instr);
+      break;
+    }
+  }
+
+  return Instruction::kInstrSize;
+}
+
+
+} }  // namespace v8::internal
+
+
+
+//------------------------------------------------------------------------------
+
+namespace disasm {
+
+
+const char* NameConverter::NameOfAddress(byte* addr) const {
+  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
+  return tmp_buffer_.start();
+}
+
+
+const char* NameConverter::NameOfConstant(byte* addr) const {
+  return NameOfAddress(addr);
+}
+
+
+const char* NameConverter::NameOfCPURegister(int reg) const {
+  return v8::internal::Registers::Name(reg);
+}
+
+const char* NameConverter::NameOfByteCPURegister(int reg) const {
+  UNREACHABLE();  // PPC does not have the concept of a byte register
+  return "nobytereg";
+}
+
+
+const char* NameConverter::NameOfXMMRegister(int reg) const {
+  UNREACHABLE();  // PPC does not have any XMM registers
+  return "noxmmreg";
+}
+
+const char* NameConverter::NameInCode(byte* addr) const {
+  // The default name converter is called for unknown code. So we will not try
+  // to access any memory.
+  return "";
+}
+
+
+//------------------------------------------------------------------------------
+
+Disassembler::Disassembler(const NameConverter& converter)
+    : converter_(converter) {}
+
+
+Disassembler::~Disassembler() {}
+
+
+int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
+                                    byte* instruction) {
+  v8::internal::Decoder d(converter_, buffer);
+  return d.InstructionDecode(instruction);
+}
+
+
+// The PPC assembler does not currently use constant pools.
+int Disassembler::ConstantPoolSizeAt(byte* instruction) {
+  return -1;
+}
+
+
+void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
+  NameConverter converter;
+  Disassembler d(converter);
+  for (byte* pc = begin; pc < end;) {
+    v8::internal::EmbeddedVector<char, 128> buffer;
+    buffer[0] = '\0';
+    byte* prev_pc = pc;
+    pc += d.InstructionDecode(buffer, pc);
+    fprintf(f, "%p    %08x      %s\n",
+            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+  }
+}
+
+
+}  // namespace disasm
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/frames-ppc.cc b/src/ppc/frames-ppc.cc
new file mode 100644
index 0000000..0341e2b
--- /dev/null
+++ b/src/ppc/frames-ppc.cc
@@ -0,0 +1,48 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "frames-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+Address ExitFrame::ComputeStackPointer(Address fp) {
+  return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/frames-ppc.h b/src/ppc/frames-ppc.h
new file mode 100644
index 0000000..7cc3e02
--- /dev/null
+++ b/src/ppc/frames-ppc.h
@@ -0,0 +1,228 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_FRAMES_PPC_H_
+#define V8_PPC_FRAMES_PPC_H_
+
+namespace v8 {
+namespace internal {
+
+
+// Register list in load/store instructions
+// Note that the bit values must match those used in actual instruction encoding
+const int kNumRegs = 32;
+
+
+// Caller-saved/arguments registers
+const RegList kJSCallerSaved =
+  1 << 3  |  // r3  a1
+  1 << 4  |  // r4  a2
+  1 << 5  |  // r5  a3
+  1 << 6  |  // r6  a4
+  1 << 7  |  // r7  a5
+  1 << 8  |  // r8  a6
+  1 << 9  |  // r9  a7
+  1 << 10 |  // r10 a8
+  1 << 11;
+
+const int kNumJSCallerSaved = 9;
+
+typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
+
+// Return the code of the n-th caller-saved register available to JavaScript
+// e.g. JSCallerSavedReg(0) returns r0.code() == 0
+int JSCallerSavedCode(int n);
+
+
+// Callee-saved registers preserved when switching from C to JavaScript
+// N.B.  Do not bother saving all non-volatiles -- only those that v8
+//       modifies without saving/restoring inline.
+const RegList kCalleeSaved =
+  1 <<  14 |  // r14 (argument passing in CEntryStub)
+  1 <<  15 |  // r15 (argument passing in CEntryStub)
+  1 <<  16 |  // r16 (argument passing in CEntryStub)
+              // r17-r19 unused
+  1 <<  20 |  // r20 (cp in Javascript code)
+  1 <<  21 |  // r21 (roots array in Javascript code)
+  1 <<  22 |  // r22 (r9 hack in Javascript code)
+              // r23-r25 unused
+  1 <<  26 |  // r26 (HandleScope logic in MacroAssembler)
+  1 <<  27 |  // r27 (HandleScope logic in MacroAssembler)
+  1 <<  28 |  // r28 (HandleScope logic in MacroAssembler)
+  1 <<  29 |  // r29 (HandleScope logic in MacroAssembler)
+              // r30 used but saved/restored inline
+  1 <<  31;   // r31 (fp in Javascript code)
+
+
+const int kNumCalleeSaved = 11;
+
+// Number of registers for which space is reserved in safepoints. Must be a
+// multiple of 8.
+// TODO(regis): Only 8 registers may actually be sufficient. Revisit.
+const int kNumSafepointRegisters = 32;
+
+// Define the list of registers actually saved at safepoints.
+// Note that the number of saved registers may be smaller than the reserved
+// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
+const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
+const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
+
+// The following constants describe the stack frame linkage area as
+// defined by the ABI.
+#if defined(V8_TARGET_ARCH_PPC64) && __BYTE_ORDER == __LITTLE_ENDIAN
+// [0] back chain
+// [1] condition register save area
+// [2] link register save area
+// [3] TOC save area
+// [4] Parameter1 save area
+// ...
+// [11] Parameter8 save area
+// [12] Parameter9 slot (if necessary)
+// ...
+const int kNumRequiredStackFrameSlots = 12;
+const int kStackFrameLRSlot = 2;
+const int kStackFrameExtraParamSlot = 12;
+#elif defined(_AIX) || defined(V8_TARGET_ARCH_PPC64)
+// [0] back chain
+// [1] condition register save area
+// [2] link register save area
+// [3] reserved for compiler
+// [4] reserved by binder
+// [5] TOC save area
+// [6] Parameter1 save area
+// ...
+// [13] Parameter8 save area
+// [14] Parameter9 slot (if necessary)
+// ...
+const int kNumRequiredStackFrameSlots = 14;
+const int kStackFrameLRSlot = 2;
+const int kStackFrameExtraParamSlot = 14;
+#else
+// [0] back chain
+// [1] link register save area
+// [2] Parameter9 slot (if necessary)
+// ...
+const int kNumRequiredStackFrameSlots = 2;
+const int kStackFrameLRSlot = 1;
+const int kStackFrameExtraParamSlot = 2;
+#endif
+
+// ----------------------------------------------------
+
+
+class StackHandlerConstants : public AllStatic {
+ public:
+  static const int kNextOffset     = 0 * kPointerSize;
+  static const int kCodeOffset     = 1 * kPointerSize;
+#if defined(V8_TARGET_ARCH_PPC64) && (__BYTE_ORDER == __BIG_ENDIAN)
+  static const int kStateOffset    = 2 * kPointerSize + kIntSize;
+#else
+  static const int kStateOffset    = 2 * kPointerSize;
+#endif
+  static const int kStateSlot      = 2 * kPointerSize;
+  static const int kContextOffset  = 3 * kPointerSize;
+  static const int kFPOffset       = 4 * kPointerSize;
+
+  static const int kSize = kFPOffset + kPointerSize;
+};
+
+
+class EntryFrameConstants : public AllStatic {
+ public:
+  static const int kCallerFPOffset      = -3 * kPointerSize;
+};
+
+
+class ExitFrameConstants : public AllStatic {
+ public:
+  static const int kCodeOffset = -2 * kPointerSize;
+  static const int kSPOffset = -1 * kPointerSize;
+
+  // The caller fields are below the frame pointer on the stack.
+  static const int kCallerFPOffset = 0 * kPointerSize;
+  // The calling JS function is below FP.
+  static const int kCallerPCOffset = 1 * kPointerSize;
+
+  // FP-relative displacement of the caller's SP.  It points just
+  // below the saved PC.
+  static const int kCallerSPDisplacement = 2 * kPointerSize;
+};
+
+
+class StandardFrameConstants : public AllStatic {
+ public:
+  // Fixed part of the frame consists of return address, caller fp,
+  // context and function.
+  static const int kFixedFrameSize    =  4 * kPointerSize;
+  static const int kExpressionsOffset = -3 * kPointerSize;
+  static const int kMarkerOffset      = -2 * kPointerSize;
+  static const int kContextOffset     = -1 * kPointerSize;
+  static const int kCallerFPOffset    =  0 * kPointerSize;
+  static const int kCallerPCOffset    =  1 * kPointerSize;
+  static const int kCallerSPOffset    =  2 * kPointerSize;
+};
+
+
+class JavaScriptFrameConstants : public AllStatic {
+ public:
+  // FP-relative.
+  static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
+  static const int kLastParameterOffset = +2 * kPointerSize;
+  static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
+
+  // Caller SP-relative.
+  static const int kParam0Offset   = -2 * kPointerSize;
+  static const int kReceiverOffset = -1 * kPointerSize;
+};
+
+
+class ArgumentsAdaptorFrameConstants : public AllStatic {
+ public:
+  static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+  static const int kFrameSize =
+      StandardFrameConstants::kFixedFrameSize + kPointerSize;
+};
+
+
+class InternalFrameConstants : public AllStatic {
+ public:
+  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+};
+
+
+inline Object* JavaScriptFrame::function_slot_object() const {
+  const int offset = JavaScriptFrameConstants::kFunctionOffset;
+  return Memory::Object_at(fp() + offset);
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_FRAMES_PPC_H_
diff --git a/src/ppc/full-codegen-ppc.cc b/src/ppc/full-codegen-ppc.cc
new file mode 100644
index 0000000..235bf24
--- /dev/null
+++ b/src/ppc/full-codegen-ppc.cc
@@ -0,0 +1,4609 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "code-stubs.h"
+#include "codegen.h"
+#include "compiler.h"
+#include "debug.h"
+#include "full-codegen.h"
+#include "isolate-inl.h"
+#include "parser.h"
+#include "scopes.h"
+#include "stub-cache.h"
+
+#include "ppc/code-stubs-ppc.h"
+#include "ppc/macro-assembler-ppc.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm_)
+
+// A patch site is a location in the code which it is possible to patch. This
+// class has a number of methods to emit the code which is patchable and the
+// method EmitPatchInfo to record a marker back to the patchable code. This
+// marker is a cmpi rx, #yyy instruction, and x * 0x0000ffff + yyy (raw 16 bit
+// immediate value is used) is the delta from the pc to the first instruction of
+// the patchable code.
+// See PatchInlinedSmiCode in ic-ppc.cc for the code that patches it
+class JumpPatchSite BASE_EMBEDDED {
+ public:
+  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
+#ifdef DEBUG
+    info_emitted_ = false;
+#endif
+  }
+
+  ~JumpPatchSite() {
+    ASSERT(patch_site_.is_bound() == info_emitted_);
+  }
+
+  // When initially emitting this ensure that a jump is always generated to skip
+  // the inlined smi code.
+  void EmitJumpIfNotSmi(Register reg, Label* target) {
+    ASSERT(!patch_site_.is_bound() && !info_emitted_);
+    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
+    __ bind(&patch_site_);
+    __ cmp(reg, reg, cr0);
+    __ beq(target, cr0);  // Always taken before patched.
+  }
+
+  // When initially emitting this ensure that a jump is never generated to skip
+  // the inlined smi code.
+  void EmitJumpIfSmi(Register reg, Label* target) {
+    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
+    ASSERT(!patch_site_.is_bound() && !info_emitted_);
+    __ bind(&patch_site_);
+    __ cmp(reg, reg, cr0);
+    __ bne(target, cr0);  // Never taken before patched.
+  }
+
+  void EmitPatchInfo() {
+    if (patch_site_.is_bound()) {
+      int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
+      Register reg;
+      // I believe this is using reg as the high bits of of the offset
+      reg.set_code(delta_to_patch_site / kOff16Mask);
+      __ cmpi(reg, Operand(delta_to_patch_site % kOff16Mask));
+#ifdef DEBUG
+      info_emitted_ = true;
+#endif
+    } else {
+      __ nop();  // Signals no inlined code.
+    }
+  }
+
+ private:
+  MacroAssembler* masm_;
+  Label patch_site_;
+#ifdef DEBUG
+  bool info_emitted_;
+#endif
+};
+
+
+// Generate code for a JS function.  On entry to the function the receiver
+// and arguments have been pushed on the stack left to right.  The actual
+// argument count matches the formal parameter count expected by the
+// function.
+//
+// The live registers are:
+//   o r4: the JS function object being called (i.e., ourselves)
+//   o cp: our context
+//   o fp: our caller's frame pointer (aka r31)
+//   o sp: stack pointer
+//   o lr: return address  (bogus.. PPC has no lr reg)
+//
+// The function builds a JS frame.  Please see JavaScriptFrameConstants in
+// frames-ppc.h for its layout.
+void FullCodeGenerator::Generate() {
+  CompilationInfo* info = info_;
+  handler_table_ =
+      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
+  profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
+      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget)));
+  SetFunctionPosition(function());
+  Comment cmnt(masm_, "[ function compiled by full code generator");
+
+  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
+
+#ifdef DEBUG
+  if (strlen(FLAG_stop_at) > 0 &&
+      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+    __ stop("stop-at");
+  }
+#endif
+
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). r8 is zero for method calls and non-zero for
+  // function calls.
+  if (!info->is_classic_mode() || info->is_native()) {
+    Label ok;
+    __ cmpi(r8, Operand::Zero());
+    __ beq(&ok);
+    int receiver_offset = info->scope()->num_parameters() * kPointerSize;
+    __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+    __ StoreP(r5, MemOperand(sp, receiver_offset), r0);
+    __ bind(&ok);
+  }
+
+  // Open a frame scope to indicate that there is a frame on the stack.  The
+  // MANUAL indicates that the scope shouldn't actually generate code to set up
+  // the frame (that is done below).
+  FrameScope frame_scope(masm_, StackFrame::MANUAL);
+
+  int locals_count = info->scope()->num_stack_slots();
+
+  __ mflr(r0);
+  __ Push(r0, fp, cp, r4);
+
+  if (locals_count > 0) {
+    // Load undefined value here, so the value is ready for the loop
+    // below.
+    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  }
+  // Adjust fp to point to caller's fp.
+  __ addi(fp, sp, Operand(2 * kPointerSize));
+
+  { Comment cmnt(masm_, "[ Allocate locals");
+    for (int i = 0; i < locals_count; i++) {
+      __ push(ip);
+    }
+  }
+
+  bool function_in_register = true;
+
+  // Possibly allocate a local context.
+  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  if (heap_slots > 0) {
+    // Argument to NewContext is the function, which is still in r4.
+    Comment cmnt(masm_, "[ Allocate context");
+    __ push(r4);
+    if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
+      __ Push(info->scope()->GetScopeInfo());
+      __ CallRuntime(Runtime::kNewGlobalContext, 2);
+    } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+      FastNewContextStub stub(heap_slots);
+      __ CallStub(&stub);
+    } else {
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
+    }
+    function_in_register = false;
+    // Context is returned in both r3 and cp.  It replaces the context
+    // passed to us.  It's saved in the stack and kept live in cp.
+    __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+    // Copy any necessary parameters into the context.
+    int num_parameters = info->scope()->num_parameters();
+    for (int i = 0; i < num_parameters; i++) {
+      Variable* var = scope()->parameter(i);
+      if (var->IsContextSlot()) {
+        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
+            (num_parameters - 1 - i) * kPointerSize;
+        // Load parameter from stack.
+        __ LoadP(r3, MemOperand(fp, parameter_offset), r0);
+        // Store it in the context.
+        MemOperand target = ContextOperand(cp, var->index());
+        __ StoreP(r3, target, r0);
+
+        // Update the write barrier.
+        __ RecordWriteContextSlot(
+            cp, target.offset(), r3, r6, kLRHasBeenSaved, kDontSaveFPRegs);
+      }
+    }
+  }
+
+  Variable* arguments = scope()->arguments();
+  if (arguments != NULL) {
+    // Function uses arguments object.
+    Comment cmnt(masm_, "[ Allocate arguments object");
+    if (!function_in_register) {
+      // Load this again, if it's used by the local context below.
+      __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+    } else {
+      __ mr(r6, r4);
+    }
+    // Receiver is just before the parameters on the caller's stack.
+    int num_parameters = info->scope()->num_parameters();
+    int offset = num_parameters * kPointerSize;
+    __ addi(r5, fp,
+            Operand(StandardFrameConstants::kCallerSPOffset + offset));
+    __ LoadSmiLiteral(r4, Smi::FromInt(num_parameters));
+    __ Push(r6, r5, r4);
+
+    // Arguments to ArgumentsAccessStub:
+    //   function, receiver address, parameter count.
+    // The stub will rewrite receiever and parameter count if the previous
+    // stack frame was an arguments adapter frame.
+    ArgumentsAccessStub::Type type;
+    if (!is_classic_mode()) {
+      type = ArgumentsAccessStub::NEW_STRICT;
+    } else if (function()->has_duplicate_parameters()) {
+      type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
+    } else {
+      type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
+    }
+    ArgumentsAccessStub stub(type);
+    __ CallStub(&stub);
+
+    SetVar(arguments, r3, r4, r5);
+  }
+
+  if (FLAG_trace) {
+    __ CallRuntime(Runtime::kTraceEnter, 0);
+  }
+
+  // Visit the declarations and body unless there is an illegal
+  // redeclaration.
+  if (scope()->HasIllegalRedeclaration()) {
+    Comment cmnt(masm_, "[ Declarations");
+    scope()->VisitIllegalRedeclaration(this);
+
+  } else {
+    PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+    { Comment cmnt(masm_, "[ Declarations");
+      // For named function expressions, declare the function name as a
+      // constant.
+      if (scope()->is_function_scope() && scope()->function() != NULL) {
+        VariableDeclaration* function = scope()->function();
+        ASSERT(function->proxy()->var()->mode() == CONST ||
+               function->proxy()->var()->mode() == CONST_HARMONY);
+        ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
+        VisitVariableDeclaration(function);
+      }
+      VisitDeclarations(scope()->declarations());
+    }
+
+    { Comment cmnt(masm_, "[ Stack check");
+      PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+      Label ok;
+      __ LoadRoot(ip, Heap::kStackLimitRootIndex);
+      __ cmpl(sp, ip);
+      // This is a FIXED_SEQUENCE and must match the other StackCheck code
+      __ bc_short(ge, &ok);
+      StackCheckStub stub;
+      __ CallStub(&stub);
+      __ bind(&ok);
+    }
+
+    { Comment cmnt(masm_, "[ Body");
+      ASSERT(loop_depth() == 0);
+      VisitStatements(function()->body());
+      ASSERT(loop_depth() == 0);
+    }
+  }
+
+  // Always emit a 'return undefined' in case control fell off the end of
+  // the body.
+  { Comment cmnt(masm_, "[ return <undefined>;");
+    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+  }
+  EmitReturnSequence();
+}
+
+
+void FullCodeGenerator::ClearAccumulator() {
+  __ LoadSmiLiteral(r3, Smi::FromInt(0));
+}
+
+
+void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
+  __ mov(r5, Operand(profiling_counter_));
+  __ LoadP(r6, FieldMemOperand(r5, JSGlobalPropertyCell::kValueOffset));
+  __ SubSmiLiteral(r6, r6, Smi::FromInt(delta), r0);
+  __ StoreP(r6, FieldMemOperand(r5, JSGlobalPropertyCell::kValueOffset), r0);
+  __ cmpi(r6, Operand::Zero());
+}
+
+
+void FullCodeGenerator::EmitProfilingCounterReset() {
+  int reset_value = FLAG_interrupt_budget;
+  if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
+    // Self-optimization is a one-off thing: if it fails, don't try again.
+    reset_value = Smi::kMaxValue;
+  }
+  if (isolate()->IsDebuggerActive()) {
+    // Detect debug break requests as soon as possible.
+    reset_value = FLAG_interrupt_budget >> 4;
+  }
+  __ mov(r5, Operand(profiling_counter_));
+  __ LoadSmiLiteral(r6, Smi::FromInt(reset_value));
+  __ StoreP(r6, FieldMemOperand(r5, JSGlobalPropertyCell::kValueOffset), r0);
+}
+
+
+// N.B. Deoptimizer::PatchStackCheckCodeAt manipulates the branch
+// instruction to the ok label below.  Thus a change to this sequence
+// (i.e. change in instruction count between the branch and
+// destination) may require a corresponding change to that logic as
+// well.
+void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
+                                       Label* back_edge_target) {
+  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
+  Comment cmnt(masm_, "[ Stack check");
+  Label ok;
+
+  if (FLAG_count_based_interrupts) {
+    int weight = 1;
+    if (FLAG_weighted_back_edges) {
+      ASSERT(back_edge_target->is_bound());
+      int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
+      weight = Min(kMaxBackEdgeWeight,
+                   Max(1, distance / kBackEdgeDistanceUnit));
+    }
+    EmitProfilingCounterDecrement(weight);
+    __ bc_short(ge, &ok);
+    InterruptStub stub;
+    __ CallStub(&stub);
+  } else {
+    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
+    __ cmpl(sp, ip);
+    // This is a FIXED_SEQUENCE and must match the other StackCheck code
+    __ bc_short(ge, &ok);
+    StackCheckStub stub;
+    __ CallStub(&stub);
+  }
+
+  // Record a mapping of this PC offset to the OSR id.  This is used to find
+  // the AST id from the unoptimized code in order to use it as a key into
+  // the deoptimization input data found in the optimized code.
+  RecordStackCheck(stmt->OsrEntryId());
+
+  if (FLAG_count_based_interrupts) {
+    EmitProfilingCounterReset();
+  }
+
+  __ bind(&ok);
+  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  // Record a mapping of the OSR id to this PC.  This is used if the OSR
+  // entry becomes the target of a bailout.  We don't expect it to be, but
+  // we want it to work if it is.
+  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+}
+
+
+void FullCodeGenerator::EmitReturnSequence() {
+  Comment cmnt(masm_, "[ Return sequence");
+  if (return_label_.is_bound()) {
+    __ b(&return_label_);
+  } else {
+    __ bind(&return_label_);
+    if (FLAG_trace) {
+      // Push the return value on the stack as the parameter.
+      // Runtime::TraceExit returns its parameter in r3
+      __ push(r3);
+      __ CallRuntime(Runtime::kTraceExit, 1);
+    }
+    if (FLAG_interrupt_at_exit || FLAG_self_optimization) {
+      // Pretend that the exit is a backwards jump to the entry.
+      int weight = 1;
+      if (info_->ShouldSelfOptimize()) {
+        weight = FLAG_interrupt_budget / FLAG_self_opt_count;
+      } else if (FLAG_weighted_back_edges) {
+        int distance = masm_->pc_offset();
+        weight = Min(kMaxBackEdgeWeight,
+                     Max(1, distance / kBackEdgeDistanceUnit));
+      }
+      EmitProfilingCounterDecrement(weight);
+      Label ok;
+      __ bge(&ok);
+      __ push(r3);
+      if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
+        __ LoadP(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+        __ push(r5);
+        __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
+      } else {
+        InterruptStub stub;
+        __ CallStub(&stub);
+      }
+      __ pop(r3);
+      EmitProfilingCounterReset();
+      __ bind(&ok);
+    }
+
+#ifdef DEBUG
+    // Add a label for checking the size of the code used for returning.
+    Label check_exit_codesize;
+    masm_->bind(&check_exit_codesize);
+#endif
+    // Make sure that the constant pool is not emitted inside of the return
+    // sequence.
+    { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
+      // Here we use masm_-> instead of the __ macro to avoid the code coverage
+      // tool from instrumenting as we rely on the code size here.
+      int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
+      CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
+      __ RecordJSReturn();
+      masm_->mr(sp, fp);
+      masm_->LoadP(fp, MemOperand(sp));
+      masm_->LoadP(r0, MemOperand(sp, kPointerSize));
+      masm_->mtlr(r0);
+      masm_->Add(sp, sp, (uint32_t)(sp_delta + (2 * kPointerSize)), r0);
+      masm_->blr();
+#if V8_TARGET_ARCH_PPC64
+      // With 64bit we need a couple of nop() instructions to ensure we have
+      // enough space to SetDebugBreakAtReturn()
+      masm_->nop();
+      masm_->nop();
+#endif
+    }
+
+#ifdef DEBUG
+    // Check that the size of the code used for returning is large enough
+    // for the debugger's requirements.
+    ASSERT(Assembler::kJSReturnSequenceInstructions <=
+           masm_->InstructionsGeneratedSince(&check_exit_codesize));
+#endif
+  }
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
+  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
+  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+  codegen()->GetVar(result_register(), var);
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
+  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+  codegen()->GetVar(result_register(), var);
+  __ push(result_register());
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Variable* var) const {
+  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+  // For simplicity we always test the accumulator register.
+  codegen()->GetVar(result_register(), var);
+  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
+  codegen()->DoTest(this);
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+    Heap::RootListIndex index) const {
+  __ LoadRoot(result_register(), index);
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(
+    Heap::RootListIndex index) const {
+  __ LoadRoot(result_register(), index);
+  __ push(result_register());
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
+  codegen()->PrepareForBailoutBeforeSplit(condition(),
+                                          true,
+                                          true_label_,
+                                          false_label_);
+  if (index == Heap::kUndefinedValueRootIndex ||
+      index == Heap::kNullValueRootIndex ||
+      index == Heap::kFalseValueRootIndex) {
+    if (false_label_ != fall_through_) __ b(false_label_);
+  } else if (index == Heap::kTrueValueRootIndex) {
+    if (true_label_ != fall_through_) __ b(true_label_);
+  } else {
+    __ LoadRoot(result_register(), index);
+    codegen()->DoTest(this);
+  }
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+    Handle<Object> lit) const {
+  __ mov(result_register(), Operand(lit));
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
+  // Immediates cannot be pushed directly.
+  __ mov(result_register(), Operand(lit));
+  __ push(result_register());
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
+  codegen()->PrepareForBailoutBeforeSplit(condition(),
+                                          true,
+                                          true_label_,
+                                          false_label_);
+  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
+  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+    if (false_label_ != fall_through_) __ b(false_label_);
+  } else if (lit->IsTrue() || lit->IsJSObject()) {
+    if (true_label_ != fall_through_) __ b(true_label_);
+  } else if (lit->IsString()) {
+    if (String::cast(*lit)->length() == 0) {
+      if (false_label_ != fall_through_) __ b(false_label_);
+    } else {
+      if (true_label_ != fall_through_) __ b(true_label_);
+    }
+  } else if (lit->IsSmi()) {
+    if (Smi::cast(*lit)->value() == 0) {
+      if (false_label_ != fall_through_) __ b(false_label_);
+    } else {
+      if (true_label_ != fall_through_) __ b(true_label_);
+    }
+  } else {
+    // For simplicity we always test the accumulator register.
+    __ mov(result_register(), Operand(lit));
+    codegen()->DoTest(this);
+  }
+}
+
+
+void FullCodeGenerator::EffectContext::DropAndPlug(int count,
+                                                   Register reg) const {
+  ASSERT(count > 0);
+  __ Drop(count);
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
+    int count,
+    Register reg) const {
+  ASSERT(count > 0);
+  __ Drop(count);
+  __ Move(result_register(), reg);
+}
+
+
+void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
+                                                       Register reg) const {
+  ASSERT(count > 0);
+  if (count > 1) __ Drop(count - 1);
+  __ StoreP(reg, MemOperand(sp, 0));
+}
+
+
+void FullCodeGenerator::TestContext::DropAndPlug(int count,
+                                                 Register reg) const {
+  ASSERT(count > 0);
+  // For simplicity we always test the accumulator register.
+  __ Drop(count);
+  __ Move(result_register(), reg);
+  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
+  codegen()->DoTest(this);
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
+                                            Label* materialize_false) const {
+  ASSERT(materialize_true == materialize_false);
+  __ bind(materialize_true);
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+    Label* materialize_true,
+    Label* materialize_false) const {
+  Label done;
+  __ bind(materialize_true);
+  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
+  __ b(&done);
+  __ bind(materialize_false);
+  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
+  __ bind(&done);
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(
+    Label* materialize_true,
+    Label* materialize_false) const {
+  Label done;
+  __ bind(materialize_true);
+  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+  __ push(ip);
+  __ b(&done);
+  __ bind(materialize_false);
+  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+  __ push(ip);
+  __ bind(&done);
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
+                                          Label* materialize_false) const {
+  ASSERT(materialize_true == true_label_);
+  ASSERT(materialize_false == false_label_);
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(bool flag) const {
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
+  Heap::RootListIndex value_root_index =
+      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
+  __ LoadRoot(result_register(), value_root_index);
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
+  Heap::RootListIndex value_root_index =
+      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
+  __ LoadRoot(ip, value_root_index);
+  __ push(ip);
+}
+
+
+void FullCodeGenerator::TestContext::Plug(bool flag) const {
+  codegen()->PrepareForBailoutBeforeSplit(condition(),
+                                          true,
+                                          true_label_,
+                                          false_label_);
+  if (flag) {
+    if (true_label_ != fall_through_) __ b(true_label_);
+  } else {
+    if (false_label_ != fall_through_) __ b(false_label_);
+  }
+}
+
+
+void FullCodeGenerator::DoTest(Expression* condition,
+                               Label* if_true,
+                               Label* if_false,
+                               Label* fall_through) {
+  ToBooleanStub stub(result_register());
+  __ CallStub(&stub);
+  __ cmpi(result_register(), Operand::Zero());
+  Split(ne, if_true, if_false, fall_through);
+}
+
+
+void FullCodeGenerator::Split(Condition cond,
+                              Label* if_true,
+                              Label* if_false,
+                              Label* fall_through,
+                              CRegister cr) {
+  if (if_false == fall_through) {
+    __ b(cond, if_true, cr);
+  } else if (if_true == fall_through) {
+    __ b(NegateCondition(cond), if_false, cr);
+  } else {
+    __ b(cond, if_true, cr);
+    __ b(if_false);
+  }
+}
+
+
+MemOperand FullCodeGenerator::StackOperand(Variable* var) {
+  ASSERT(var->IsStackAllocated());
+  // Offset is negative because higher indexes are at lower addresses.
+  int offset = -var->index() * kPointerSize;
+  // Adjust by a (parameter or local) base offset.
+  if (var->IsParameter()) {
+    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
+  } else {
+    offset += JavaScriptFrameConstants::kLocal0Offset;
+  }
+  return MemOperand(fp, offset);
+}
+
+
+MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
+  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+  if (var->IsContextSlot()) {
+    int context_chain_length = scope()->ContextChainLength(var->scope());
+    __ LoadContext(scratch, context_chain_length);
+    return ContextOperand(scratch, var->index());
+  } else {
+    return StackOperand(var);
+  }
+}
+
+
+void FullCodeGenerator::GetVar(Register dest, Variable* var) {
+  // Use destination as scratch.
+  MemOperand location = VarOperand(var, dest);
+  __ LoadP(dest, location, r0);
+}
+
+
+void FullCodeGenerator::SetVar(Variable* var,
+                               Register src,
+                               Register scratch0,
+                               Register scratch1) {
+  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+  ASSERT(!scratch0.is(src));
+  ASSERT(!scratch0.is(scratch1));
+  ASSERT(!scratch1.is(src));
+  MemOperand location = VarOperand(var, scratch0);
+  __ StoreP(src, location, r0);
+
+  // Emit the write barrier code if the location is in the heap.
+  if (var->IsContextSlot()) {
+    __ RecordWriteContextSlot(scratch0,
+                              location.offset(),
+                              src,
+                              scratch1,
+                              kLRHasBeenSaved,
+                              kDontSaveFPRegs);
+  }
+}
+
+
+void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
+                                                     bool should_normalize,
+                                                     Label* if_true,
+                                                     Label* if_false) {
+  // Only prepare for bailouts before splits if we're in a test
+  // context. Otherwise, we let the Visit function deal with the
+  // preparation to avoid preparing with the same AST id twice.
+  if (!context()->IsTest() || !info_->IsOptimizable()) return;
+
+  Label skip;
+  if (should_normalize) __ b(&skip);
+  PrepareForBailout(expr, TOS_REG);
+  if (should_normalize) {
+    __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+    __ cmp(r3, ip);
+    Split(eq, if_true, if_false, NULL);
+    __ bind(&skip);
+  }
+}
+
+
+void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
+  // The variable in the declaration always resides in the current function
+  // context.
+  ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
+  if (generate_debug_code_) {
+    // Check that we're not inside a with or catch context.
+    __ LoadP(r4, FieldMemOperand(cp, HeapObject::kMapOffset));
+    __ CompareRoot(r4, Heap::kWithContextMapRootIndex);
+    __ Check(ne, "Declaration in with context.");
+    __ CompareRoot(r4, Heap::kCatchContextMapRootIndex);
+    __ Check(ne, "Declaration in catch context.");
+  }
+}
+
+
+void FullCodeGenerator::VisitVariableDeclaration(
+    VariableDeclaration* declaration) {
+  // If it was not possible to allocate the variable at compile time, we
+  // need to "declare" it at runtime to make sure it actually exists in the
+  // local context.
+  VariableProxy* proxy = declaration->proxy();
+  VariableMode mode = declaration->mode();
+  Variable* variable = proxy->var();
+  bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
+  switch (variable->location()) {
+    case Variable::UNALLOCATED:
+      globals_->Add(variable->name(), zone());
+      globals_->Add(variable->binding_needs_init()
+                        ? isolate()->factory()->the_hole_value()
+                        : isolate()->factory()->undefined_value(),
+                    zone());
+      break;
+
+    case Variable::PARAMETER:
+    case Variable::LOCAL:
+      if (hole_init) {
+        Comment cmnt(masm_, "[ VariableDeclaration");
+        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+        __ StoreP(ip, StackOperand(variable));
+      }
+      break;
+
+    case Variable::CONTEXT:
+      if (hole_init) {
+        Comment cmnt(masm_, "[ VariableDeclaration");
+        EmitDebugCheckDeclarationContext(variable);
+        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+        __ StoreP(ip, ContextOperand(cp, variable->index()), r0);
+        // No write barrier since the_hole_value is in old space.
+        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      }
+      break;
+
+    case Variable::LOOKUP: {
+      Comment cmnt(masm_, "[ VariableDeclaration");
+      __ mov(r5, Operand(variable->name()));
+      // Declaration nodes are always introduced in one of four modes.
+      ASSERT(IsDeclaredVariableMode(mode));
+      PropertyAttributes attr =
+          IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
+      __ LoadSmiLiteral(r4, Smi::FromInt(attr));
+      // Push initial value, if any.
+      // Note: For variables we must not push an initial value (such as
+      // 'undefined') because we may have a (legal) redeclaration and we
+      // must not destroy the current value.
+      if (hole_init) {
+        __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
+        __ Push(cp, r5, r4, r3);
+      } else {
+        __ LoadSmiLiteral(r3, Smi::FromInt(0));  // Indicates no initial value.
+        __ Push(cp, r5, r4, r3);
+      }
+      __ CallRuntime(Runtime::kDeclareContextSlot, 4);
+      break;
+    }
+  }
+}
+
+
+void FullCodeGenerator::VisitFunctionDeclaration(
+    FunctionDeclaration* declaration) {
+  VariableProxy* proxy = declaration->proxy();
+  Variable* variable = proxy->var();
+  switch (variable->location()) {
+    case Variable::UNALLOCATED: {
+      globals_->Add(variable->name(), zone());
+      Handle<SharedFunctionInfo> function =
+          Compiler::BuildFunctionInfo(declaration->fun(), script());
+      // Check for stack-overflow exception.
+      if (function.is_null()) return SetStackOverflow();
+      globals_->Add(function, zone());
+      break;
+    }
+
+    case Variable::PARAMETER:
+    case Variable::LOCAL: {
+      Comment cmnt(masm_, "[ FunctionDeclaration");
+      VisitForAccumulatorValue(declaration->fun());
+      __ StoreP(result_register(), StackOperand(variable));
+      break;
+    }
+
+    case Variable::CONTEXT: {
+      Comment cmnt(masm_, "[ FunctionDeclaration");
+      EmitDebugCheckDeclarationContext(variable);
+      VisitForAccumulatorValue(declaration->fun());
+      __ StoreP(result_register(),
+                ContextOperand(cp, variable->index()), r0);
+      int offset = Context::SlotOffset(variable->index());
+      // We know that we have written a function, which is not a smi.
+      __ RecordWriteContextSlot(cp,
+                                offset,
+                                result_register(),
+                                r5,
+                                kLRHasBeenSaved,
+                                kDontSaveFPRegs,
+                                EMIT_REMEMBERED_SET,
+                                OMIT_SMI_CHECK);
+      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      break;
+    }
+
+    case Variable::LOOKUP: {
+      Comment cmnt(masm_, "[ FunctionDeclaration");
+      __ mov(r5, Operand(variable->name()));
+      __ LoadSmiLiteral(r4, Smi::FromInt(NONE));
+      __ Push(cp, r5, r4);
+      // Push initial value for function declaration.
+      VisitForStackValue(declaration->fun());
+      __ CallRuntime(Runtime::kDeclareContextSlot, 4);
+      break;
+    }
+  }
+}
+
+
+void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
+  VariableProxy* proxy = declaration->proxy();
+  Variable* variable = proxy->var();
+  Handle<JSModule> instance = declaration->module()->interface()->Instance();
+  ASSERT(!instance.is_null());
+
+  switch (variable->location()) {
+    case Variable::UNALLOCATED: {
+      Comment cmnt(masm_, "[ ModuleDeclaration");
+      globals_->Add(variable->name(), zone());
+      globals_->Add(instance, zone());
+      Visit(declaration->module());
+      break;
+    }
+
+    case Variable::CONTEXT: {
+      Comment cmnt(masm_, "[ ModuleDeclaration");
+      EmitDebugCheckDeclarationContext(variable);
+      __ mov(r4, Operand(instance));
+      __ StoreP(r4, ContextOperand(cp, variable->index()), r0);
+      Visit(declaration->module());
+      break;
+    }
+
+    case Variable::PARAMETER:
+    case Variable::LOCAL:
+    case Variable::LOOKUP:
+      UNREACHABLE();
+  }
+}
+
+
+void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
+  VariableProxy* proxy = declaration->proxy();
+  Variable* variable = proxy->var();
+  switch (variable->location()) {
+    case Variable::UNALLOCATED:
+      // TODO(rossberg)
+      break;
+
+    case Variable::CONTEXT: {
+      Comment cmnt(masm_, "[ ImportDeclaration");
+      EmitDebugCheckDeclarationContext(variable);
+      // TODO(rossberg)
+      break;
+    }
+
+    case Variable::PARAMETER:
+    case Variable::LOCAL:
+    case Variable::LOOKUP:
+      UNREACHABLE();
+  }
+}
+
+
+void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
+  // TODO(rossberg)
+}
+
+
+void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
+  // Call the runtime to declare the globals.
+  // The context is the first argument.
+  __ mov(r4, Operand(pairs));
+  __ LoadSmiLiteral(r3, Smi::FromInt(DeclareGlobalsFlags()));
+  __ Push(cp, r4, r3);
+  __ CallRuntime(Runtime::kDeclareGlobals, 3);
+  // Return value is ignored.
+}
+
+
+void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
+  Comment cmnt(masm_, "[ SwitchStatement");
+  Breakable nested_statement(this, stmt);
+  SetStatementPosition(stmt);
+
+  // Keep the switch value on the stack until a case matches.
+  VisitForStackValue(stmt->tag());
+  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+
+  ZoneList<CaseClause*>* clauses = stmt->cases();
+  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
+
+  Label next_test;  // Recycled for each test.
+  // Compile all the tests with branches to their bodies.
+  for (int i = 0; i < clauses->length(); i++) {
+    CaseClause* clause = clauses->at(i);
+    clause->body_target()->Unuse();
+
+    // The default is not a test, but remember it as final fall through.
+    if (clause->is_default()) {
+      default_clause = clause;
+      continue;
+    }
+
+    Comment cmnt(masm_, "[ Case comparison");
+    __ bind(&next_test);
+    next_test.Unuse();
+
+    // Compile the label expression.
+    VisitForAccumulatorValue(clause->label());
+
+    // Perform the comparison as if via '==='.
+    __ LoadP(r4, MemOperand(sp, 0));  // Switch value.
+    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
+    JumpPatchSite patch_site(masm_);
+    if (inline_smi_code) {
+      Label slow_case;
+      __ orx(r5, r4, r3);
+      patch_site.EmitJumpIfNotSmi(r5, &slow_case);
+
+      __ cmp(r4, r3);
+      __ bne(&next_test);
+      __ Drop(1);  // Switch value is no longer needed.
+      __ b(clause->body_target());
+      __ bind(&slow_case);
+    }
+
+    // Record position before stub call for type feedback.
+    SetSourcePosition(clause->position());
+    Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
+    CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
+    patch_site.EmitPatchInfo();
+
+    __ cmpi(r3, Operand::Zero());
+    __ bne(&next_test);
+    __ Drop(1);  // Switch value is no longer needed.
+    __ b(clause->body_target());
+  }
+
+  // Discard the test value and jump to the default if present, otherwise to
+  // the end of the statement.
+  __ bind(&next_test);
+  __ Drop(1);  // Switch value is no longer needed.
+  if (default_clause == NULL) {
+    __ b(nested_statement.break_label());
+  } else {
+    __ b(default_clause->body_target());
+  }
+
+  // Compile all the case bodies.
+  for (int i = 0; i < clauses->length(); i++) {
+    Comment cmnt(masm_, "[ Case body");
+    CaseClause* clause = clauses->at(i);
+    __ bind(clause->body_target());
+    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    VisitStatements(clause->statements());
+  }
+
+  __ bind(nested_statement.break_label());
+  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+}
+
+
+void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
+  Comment cmnt(masm_, "[ ForInStatement");
+  SetStatementPosition(stmt);
+
+  Label loop, exit;
+  ForIn loop_statement(this, stmt);
+  increment_loop_depth();
+
+  // Get the object to enumerate over. Both SpiderMonkey and JSC
+  // ignore null and undefined in contrast to the specification; see
+  // ECMA-262 section 12.6.4.
+  VisitForAccumulatorValue(stmt->enumerable());
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ cmp(r3, ip);
+  __ beq(&exit);
+  Register null_value = r7;
+  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
+  __ cmp(r3, null_value);
+  __ beq(&exit);
+
+  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
+
+  // Convert the object to a JS object.
+  Label convert, done_convert;
+  __ JumpIfSmi(r3, &convert);
+  __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
+  __ bge(&done_convert);
+  __ bind(&convert);
+  __ push(r3);
+  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  __ bind(&done_convert);
+  __ push(r3);
+
+  // Check for proxies.
+  Label call_runtime;
+  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
+  __ CompareObjectType(r3, r4, r4, LAST_JS_PROXY_TYPE);
+  __ ble(&call_runtime);
+
+  // Check cache validity in generated code. This is a fast case for
+  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
+  // guarantee cache validity, call the runtime system to check cache
+  // validity or get the property names in a fixed array.
+  __ CheckEnumCache(null_value, &call_runtime);
+
+  // The enum cache is valid.  Load the map of the object being
+  // iterated over and use the cache for the iteration.
+  Label use_cache;
+  __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ b(&use_cache);
+
+  // Get the set of properties to enumerate.
+  __ bind(&call_runtime);
+  __ push(r3);  // Duplicate the enumerable object on the stack.
+  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
+
+  // If we got a map from the runtime call, we can do a fast
+  // modification check. Otherwise, we got a fixed array, and we have
+  // to do a slow check.
+  Label fixed_array;
+  __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
+  __ cmp(r5, ip);
+  __ bne(&fixed_array);
+
+  // We got a map in register r3. Get the enumeration cache from it.
+  Label no_descriptors;
+  __ bind(&use_cache);
+
+  __ EnumLength(r4, r3);
+  __ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
+  __ beq(&no_descriptors);
+
+  __ LoadInstanceDescriptors(r3, r5);
+  __ LoadP(r5, FieldMemOperand(r5, DescriptorArray::kEnumCacheOffset));
+  __ LoadP(r5,
+           FieldMemOperand(r5, DescriptorArray::kEnumCacheBridgeCacheOffset));
+
+  // Set up the four remaining stack slots.
+  __ push(r3);  // Map.
+  __ LoadSmiLiteral(r3, Smi::FromInt(0));
+  // Push enumeration cache, enumeration cache length (as smi) and zero.
+  __ Push(r5, r4, r3);
+  __ b(&loop);
+
+  __ bind(&no_descriptors);
+  __ Drop(1);
+  __ b(&exit);
+
+  // We got a fixed array in register r3. Iterate through that.
+  Label non_proxy;
+  __ bind(&fixed_array);
+
+  Handle<JSGlobalPropertyCell> cell =
+      isolate()->factory()->NewJSGlobalPropertyCell(
+          Handle<Object>(
+              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker)));
+  RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
+  __ LoadHeapObject(r4, cell);
+  __ LoadSmiLiteral(r5, Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
+  __ StoreP(r5, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset), r0);
+
+  __ LoadSmiLiteral(r4, Smi::FromInt(1));  // Smi indicates slow check
+  __ LoadP(r5, MemOperand(sp, 0 * kPointerSize));  // Get enumerated object
+  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
+  __ CompareObjectType(r5, r6, r6, LAST_JS_PROXY_TYPE);
+  __ bgt(&non_proxy);
+  __ LoadSmiLiteral(r4, Smi::FromInt(0));  // Zero indicates proxy
+  __ bind(&non_proxy);
+  __ Push(r4, r3);  // Smi and array
+  __ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset));
+  __ LoadSmiLiteral(r3, Smi::FromInt(0));
+  __ Push(r4, r3);  // Fixed array length (as smi) and initial index.
+
+  // Generate code for doing the condition check.
+  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  __ bind(&loop);
+  // Load the current count to r3, load the length to r4.
+  __ LoadP(r3, MemOperand(sp, 0 * kPointerSize));
+  __ LoadP(r4, MemOperand(sp, 1 * kPointerSize));
+  __ cmpl(r3, r4);  // Compare to the array length.
+  __ bge(loop_statement.break_label());
+
+  // Get the current entry of the array into register r6.
+  __ LoadP(r5, MemOperand(sp, 2 * kPointerSize));
+  __ addi(r5, r5, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ SmiToPtrArrayOffset(r6, r3);
+  __ LoadPX(r6, MemOperand(r6, r5));
+
+  // Get the expected map from the stack or a smi in the
+  // permanent slow case into register r2.
+  __ LoadP(r5, MemOperand(sp, 3 * kPointerSize));
+
+  // Check if the expected map still matches that of the enumerable.
+  // If not, we may have to filter the key.
+  Label update_each;
+  __ LoadP(r4, MemOperand(sp, 4 * kPointerSize));
+  __ LoadP(r7, FieldMemOperand(r4, HeapObject::kMapOffset));
+  __ cmp(r7, r5);
+  __ beq(&update_each);
+
+  // For proxies, no filtering is done.
+  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
+  __ CmpSmiLiteral(r5, Smi::FromInt(0), r0);
+  __ beq(&update_each);
+
+  // Convert the entry to a string or (smi) 0 if it isn't a property
+  // any more. If the property has been removed while iterating, we
+  // just skip it.
+  __ push(r4);  // Enumerable.
+  __ push(r6);  // Current entry.
+  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
+  __ mr(r6, r3);
+  __ cmpi(r6, Operand::Zero());
+  __ beq(loop_statement.continue_label());
+
+  // Update the 'each' property or variable from the possibly filtered
+  // entry in register r6.
+  __ bind(&update_each);
+  __ mr(result_register(), r6);
+  // Perform the assignment as if via '='.
+  { EffectContext context(this);
+    EmitAssignment(stmt->each());
+  }
+
+  // Generate code for the body of the loop.
+  Visit(stmt->body());
+
+  // Generate code for the going to the next element by incrementing
+  // the index (smi) stored on top of the stack.
+  __ bind(loop_statement.continue_label());
+  __ pop(r3);
+  __ AddSmiLiteral(r3, r3, Smi::FromInt(1), r0);
+  __ push(r3);
+
+  EmitStackCheck(stmt, &loop);
+  __ b(&loop);
+
+  // Remove the pointers stored on the stack.
+  __ bind(loop_statement.break_label());
+  __ Drop(5);
+
+  // Exit and decrement the loop depth.
+  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  __ bind(&exit);
+  decrement_loop_depth();
+}
+
+
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+                                       bool pretenure) {
+  // Use the fast case closure allocation code that allocates in new
+  // space for nested functions that don't need literals cloning. If
+  // we're running with the --always-opt or the --prepare-always-opt
+  // flag, we need to use the runtime function so that the new function
+  // we are creating here gets a chance to have its code optimized and
+  // doesn't just get a copy of the existing unoptimized code.
+  if (!FLAG_always_opt &&
+      !FLAG_prepare_always_opt &&
+      !pretenure &&
+      scope()->is_function_scope() &&
+      info->num_literals() == 0) {
+    FastNewClosureStub stub(info->language_mode());
+    __ mov(r3, Operand(info));
+    __ push(r3);
+    __ CallStub(&stub);
+  } else {
+    __ mov(r3, Operand(info));
+    __ LoadRoot(r4, pretenure ? Heap::kTrueValueRootIndex
+                              : Heap::kFalseValueRootIndex);
+    __ Push(cp, r3, r4);
+    __ CallRuntime(Runtime::kNewClosure, 3);
+  }
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
+  Comment cmnt(masm_, "[ VariableProxy");
+  EmitVariableLoad(expr);
+}
+
+
+void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+                                                      TypeofState typeof_state,
+                                                      Label* slow) {
+  Register current = cp;
+  Register next = r4;
+  Register temp = r5;
+
+  Scope* s = scope();
+  while (s != NULL) {
+    if (s->num_heap_slots() > 0) {
+      if (s->calls_non_strict_eval()) {
+        // Check that extension is NULL.
+        __ LoadP(temp, ContextOperand(current, Context::EXTENSION_INDEX));
+        __ cmpi(temp, Operand::Zero());
+        __ bne(slow);
+      }
+      // Load next context in chain.
+      __ LoadP(next, ContextOperand(current, Context::PREVIOUS_INDEX));
+      // Walk the rest of the chain without clobbering cp.
+      current = next;
+    }
+    // If no outer scope calls eval, we do not need to check more
+    // context extensions.
+    if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
+    s = s->outer_scope();
+  }
+
+  if (s->is_eval_scope()) {
+    Label loop, fast;
+    if (!current.is(next)) {
+      __ Move(next, current);
+    }
+    __ bind(&loop);
+    // Terminate at native context.
+    __ LoadP(temp, FieldMemOperand(next, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kNativeContextMapRootIndex);
+    __ cmp(temp, ip);
+    __ beq(&fast);
+    // Check that extension is NULL.
+    __ LoadP(temp, ContextOperand(next, Context::EXTENSION_INDEX));
+    __ cmpi(temp, Operand::Zero());
+    __ bne(slow);
+    // Load next context in chain.
+    __ LoadP(next, ContextOperand(next, Context::PREVIOUS_INDEX));
+    __ b(&loop);
+    __ bind(&fast);
+  }
+
+  __ LoadP(r3, GlobalObjectOperand());
+  __ mov(r5, Operand(var->name()));
+  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
+      ? RelocInfo::CODE_TARGET
+      : RelocInfo::CODE_TARGET_CONTEXT;
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+  CallIC(ic, mode);
+}
+
+
+MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
+                                                                Label* slow) {
+  ASSERT(var->IsContextSlot());
+  Register context = cp;
+  Register next = r6;
+  Register temp = r7;
+
+  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
+    if (s->num_heap_slots() > 0) {
+      if (s->calls_non_strict_eval()) {
+        // Check that extension is NULL.
+        __ LoadP(temp, ContextOperand(context, Context::EXTENSION_INDEX));
+        __ cmpi(temp, Operand::Zero());
+        __ bne(slow);
+      }
+      __ LoadP(next, ContextOperand(context, Context::PREVIOUS_INDEX));
+      // Walk the rest of the chain without clobbering cp.
+      context = next;
+    }
+  }
+  // Check that last extension is NULL.
+  __ LoadP(temp, ContextOperand(context, Context::EXTENSION_INDEX));
+  __ cmpi(temp, Operand::Zero());
+  __ bne(slow);
+
+  // This function is used only for loads, not stores, so it's safe to
+  // return an cp-based operand (the write barrier cannot be allowed to
+  // destroy the cp register).
+  return ContextOperand(context, var->index());
+}
+
+
+void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
+                                                  TypeofState typeof_state,
+                                                  Label* slow,
+                                                  Label* done) {
+  // Generate fast-case code for variables that might be shadowed by
+  // eval-introduced variables.  Eval is used a lot without
+  // introducing variables.  In those cases, we do not want to
+  // perform a runtime call for all variables in the scope
+  // containing the eval.
+  if (var->mode() == DYNAMIC_GLOBAL) {
+    EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
+    __ b(done);
+  } else if (var->mode() == DYNAMIC_LOCAL) {
+    Variable* local = var->local_if_not_shadowed();
+    __ LoadP(r3, ContextSlotOperandCheckExtensions(local, slow));
+    if (local->mode() == CONST ||
+        local->mode() == CONST_HARMONY ||
+        local->mode() == LET) {
+      __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
+      __ bne(done);
+      if (local->mode() == CONST) {
+        __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+      } else {  // LET || CONST_HARMONY
+        __ mov(r3, Operand(var->name()));
+        __ push(r3);
+        __ CallRuntime(Runtime::kThrowReferenceError, 1);
+      }
+    }
+    __ b(done);
+  }
+}
+
+
+void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
+  // Record position before possible IC call.
+  SetSourcePosition(proxy->position());
+  Variable* var = proxy->var();
+
+  // Three cases: global variables, lookup variables, and all other types of
+  // variables.
+  switch (var->location()) {
+    case Variable::UNALLOCATED: {
+      Comment cmnt(masm_, "Global variable");
+      // Use inline caching. Variable name is passed in r5 and the global
+      // object (receiver) in r3.
+      __ LoadP(r3, GlobalObjectOperand());
+      __ mov(r5, Operand(var->name()));
+      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+      CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
+      context()->Plug(r3);
+      break;
+    }
+
+    case Variable::PARAMETER:
+    case Variable::LOCAL:
+    case Variable::CONTEXT: {
+      Comment cmnt(masm_, var->IsContextSlot()
+                              ? "Context variable"
+                              : "Stack variable");
+      if (var->binding_needs_init()) {
+        // var->scope() may be NULL when the proxy is located in eval code and
+        // refers to a potential outside binding. Currently those bindings are
+        // always looked up dynamically, i.e. in that case
+        //     var->location() == LOOKUP.
+        // always holds.
+        ASSERT(var->scope() != NULL);
+
+        // Check if the binding really needs an initialization check. The check
+        // can be skipped in the following situation: we have a LET or CONST
+        // binding in harmony mode, both the Variable and the VariableProxy have
+        // the same declaration scope (i.e. they are both in global code, in the
+        // same function or in the same eval code) and the VariableProxy is in
+        // the source physically located after the initializer of the variable.
+        //
+        // We cannot skip any initialization checks for CONST in non-harmony
+        // mode because const variables may be declared but never initialized:
+        //   if (false) { const x; }; var y = x;
+        //
+        // The condition on the declaration scopes is a conservative check for
+        // nested functions that access a binding and are called before the
+        // binding is initialized:
+        //   function() { f(); let x = 1; function f() { x = 2; } }
+        //
+        bool skip_init_check;
+        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
+          skip_init_check = false;
+        } else {
+          // Check that we always have valid source position.
+          ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
+          ASSERT(proxy->position() != RelocInfo::kNoPosition);
+          skip_init_check = var->mode() != CONST &&
+              var->initializer_position() < proxy->position();
+        }
+
+        if (!skip_init_check) {
+          Label done;
+          // Let and const need a read barrier.
+          GetVar(r3, var);
+          __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
+          __ bne(&done);
+          if (var->mode() == LET || var->mode() == CONST_HARMONY) {
+            // Throw a reference error when using an uninitialized let/const
+            // binding in harmony mode.
+            __ mov(r3, Operand(var->name()));
+            __ push(r3);
+            __ CallRuntime(Runtime::kThrowReferenceError, 1);
+          } else {
+            // Uninitalized const bindings outside of harmony mode are unholed.
+            ASSERT(var->mode() == CONST);
+            __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+          }
+          __ bind(&done);
+          context()->Plug(r3);
+          break;
+        }
+      }
+      context()->Plug(var);
+      break;
+    }
+
+    case Variable::LOOKUP: {
+      Label done, slow;
+      // Generate code for loading from variables potentially shadowed
+      // by eval-introduced variables.
+      EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
+      __ bind(&slow);
+      Comment cmnt(masm_, "Lookup variable");
+      __ mov(r4, Operand(var->name()));
+      __ Push(cp, r4);  // Context and name.
+      __ CallRuntime(Runtime::kLoadContextSlot, 2);
+      __ bind(&done);
+      context()->Plug(r3);
+    }
+  }
+}
+
+
+void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+  Comment cmnt(masm_, "[ RegExpLiteral");
+  Label materialized;
+  // Registers will be used as follows:
+  // r8 = materialized value (RegExp literal)
+  // r7 = JS function, literals array
+  // r6 = literal index
+  // r5 = RegExp pattern
+  // r4 = RegExp flags
+  // r3 = RegExp literal clone
+  __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  __ LoadP(r7, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
+  int literal_offset =
+      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+  __ LoadP(r8, FieldMemOperand(r7, literal_offset), r0);
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ cmp(r8, ip);
+  __ bne(&materialized);
+
+  // Create regexp literal using runtime function.
+  // Result will be in r3.
+  __ LoadSmiLiteral(r6, Smi::FromInt(expr->literal_index()));
+  __ mov(r5, Operand(expr->pattern()));
+  __ mov(r4, Operand(expr->flags()));
+  __ Push(r7, r6, r5, r4);
+  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+  __ mr(r8, r3);
+
+  __ bind(&materialized);
+  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
+  Label allocated, runtime_allocate;
+  __ AllocateInNewSpace(size, r3, r5, r6, &runtime_allocate, TAG_OBJECT);
+  __ b(&allocated);
+
+  __ bind(&runtime_allocate);
+  __ push(r8);
+  __ LoadSmiLiteral(r3, Smi::FromInt(size));
+  __ push(r3);
+  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+  __ pop(r8);
+
+  __ bind(&allocated);
+  // After this, registers are used as follows:
+  // r3: Newly allocated regexp.
+  // r8: Materialized regexp.
+  // r5: temp.
+  __ CopyFields(r3, r8, r5.bit(), size / kPointerSize);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitAccessor(Expression* expression) {
+  if (expression == NULL) {
+    __ LoadRoot(r4, Heap::kNullValueRootIndex);
+    __ push(r4);
+  } else {
+    VisitForStackValue(expression);
+  }
+}
+
+
+void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
+  Comment cmnt(masm_, "[ ObjectLiteral");
+  Handle<FixedArray> constant_properties = expr->constant_properties();
+  __ LoadP(r6, MemOperand(fp,  JavaScriptFrameConstants::kFunctionOffset));
+  __ LoadP(r6, FieldMemOperand(r6, JSFunction::kLiteralsOffset));
+  __ LoadSmiLiteral(r5, Smi::FromInt(expr->literal_index()));
+  __ mov(r4, Operand(constant_properties));
+  int flags = expr->fast_elements()
+      ? ObjectLiteral::kFastElements
+      : ObjectLiteral::kNoFlags;
+  flags |= expr->has_function()
+      ? ObjectLiteral::kHasFunction
+      : ObjectLiteral::kNoFlags;
+  __ LoadSmiLiteral(r3, Smi::FromInt(flags));
+  __ Push(r6, r5, r4, r3);
+  int properties_count = constant_properties->length() / 2;
+  if (expr->depth() > 1) {
+    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
+  } else if (flags != ObjectLiteral::kFastElements ||
+      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
+    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
+  } else {
+    FastCloneShallowObjectStub stub(properties_count);
+    __ CallStub(&stub);
+  }
+
+  // If result_saved is true the result is on top of the stack.  If
+  // result_saved is false the result is in r3.
+  bool result_saved = false;
+
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  expr->CalculateEmitStore(zone());
+
+  AccessorTable accessor_table(zone());
+  for (int i = 0; i < expr->properties()->length(); i++) {
+    ObjectLiteral::Property* property = expr->properties()->at(i);
+    if (property->IsCompileTimeValue()) continue;
+
+    Literal* key = property->key();
+    Expression* value = property->value();
+    if (!result_saved) {
+      __ push(r3);  // Save result on stack
+      result_saved = true;
+    }
+    switch (property->kind()) {
+      case ObjectLiteral::Property::CONSTANT:
+        UNREACHABLE();
+      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
+        ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
+        // Fall through.
+      case ObjectLiteral::Property::COMPUTED:
+        if (key->handle()->IsSymbol()) {
+          if (property->emit_store()) {
+            VisitForAccumulatorValue(value);
+            __ mov(r5, Operand(key->handle()));
+            __ LoadP(r4, MemOperand(sp));
+            Handle<Code> ic = is_classic_mode()
+                ? isolate()->builtins()->StoreIC_Initialize()
+                : isolate()->builtins()->StoreIC_Initialize_Strict();
+            CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId());
+            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+          } else {
+            VisitForEffect(value);
+          }
+          break;
+        }
+        // Fall through.
+      case ObjectLiteral::Property::PROTOTYPE:
+        // Duplicate receiver on stack.
+        __ LoadP(r3, MemOperand(sp));
+        __ push(r3);
+        VisitForStackValue(key);
+        VisitForStackValue(value);
+        if (property->emit_store()) {
+          __ LoadSmiLiteral(r3, Smi::FromInt(NONE));  // PropertyAttributes
+          __ push(r3);
+          __ CallRuntime(Runtime::kSetProperty, 4);
+        } else {
+          __ Drop(3);
+        }
+        break;
+      case ObjectLiteral::Property::GETTER:
+        accessor_table.lookup(key)->second->getter = value;
+        break;
+      case ObjectLiteral::Property::SETTER:
+        accessor_table.lookup(key)->second->setter = value;
+        break;
+    }
+  }
+
+  // Emit code to define accessors, using only a single call to the runtime for
+  // each pair of corresponding getters and setters.
+  for (AccessorTable::Iterator it = accessor_table.begin();
+       it != accessor_table.end();
+       ++it) {
+    __ LoadP(r3, MemOperand(sp));  // Duplicate receiver.
+    __ push(r3);
+    VisitForStackValue(it->first);
+    EmitAccessor(it->second->getter);
+    EmitAccessor(it->second->setter);
+    __ LoadSmiLiteral(r3, Smi::FromInt(NONE));
+    __ push(r3);
+    __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
+  }
+
+  if (expr->has_function()) {
+    ASSERT(result_saved);
+    __ LoadP(r3, MemOperand(sp));
+    __ push(r3);
+    __ CallRuntime(Runtime::kToFastProperties, 1);
+  }
+
+  if (result_saved) {
+    context()->PlugTOS();
+  } else {
+    context()->Plug(r3);
+  }
+}
+
+
+void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
+  Comment cmnt(masm_, "[ ArrayLiteral");
+
+  ZoneList<Expression*>* subexprs = expr->values();
+  int length = subexprs->length();
+  Handle<FixedArray> constant_elements = expr->constant_elements();
+  ASSERT_EQ(2, constant_elements->length());
+  ElementsKind constant_elements_kind =
+      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
+  bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind);
+  Handle<FixedArrayBase> constant_elements_values(
+      FixedArrayBase::cast(constant_elements->get(1)));
+
+  __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  __ LoadP(r6, FieldMemOperand(r6, JSFunction::kLiteralsOffset));
+  __ LoadSmiLiteral(r5, Smi::FromInt(expr->literal_index()));
+  __ mov(r4, Operand(constant_elements));
+  __ Push(r6, r5, r4);
+  if (has_fast_elements && constant_elements_values->map() ==
+      isolate()->heap()->fixed_cow_array_map()) {
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
+    __ CallStub(&stub);
+    __ IncrementCounter(
+        isolate()->counters()->cow_arrays_created_stub(), 1, r4, r5);
+  } else if (expr->depth() > 1) {
+    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
+    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
+  } else {
+    ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
+           FLAG_smi_only_arrays);
+    FastCloneShallowArrayStub::Mode mode = has_fast_elements
+      ? FastCloneShallowArrayStub::CLONE_ELEMENTS
+      : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
+    FastCloneShallowArrayStub stub(mode, length);
+    __ CallStub(&stub);
+  }
+
+  bool result_saved = false;  // Is the result saved to the stack?
+
+  // Emit code to evaluate all the non-constant subexpressions and to store
+  // them into the newly cloned array.
+  for (int i = 0; i < length; i++) {
+    Expression* subexpr = subexprs->at(i);
+    // If the subexpression is a literal or a simple materialized literal it
+    // is already set in the cloned array.
+    if (subexpr->AsLiteral() != NULL ||
+        CompileTimeValue::IsCompileTimeValue(subexpr)) {
+      continue;
+    }
+
+    if (!result_saved) {
+      __ push(r3);
+      result_saved = true;
+    }
+    VisitForAccumulatorValue(subexpr);
+
+    if (IsFastObjectElementsKind(constant_elements_kind)) {
+      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
+      __ LoadP(r8, MemOperand(sp));  // Copy of array literal.
+      __ LoadP(r4, FieldMemOperand(r8, JSObject::kElementsOffset));
+      __ StoreP(result_register(), FieldMemOperand(r4, offset), r0);
+      // Update the write barrier for the array store.
+      __ RecordWriteField(r4, offset, result_register(), r5,
+                          kLRHasBeenSaved, kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
+    } else {
+      __ LoadP(r4, MemOperand(sp));  // Copy of array literal.
+      __ LoadP(r5, FieldMemOperand(r4, JSObject::kMapOffset));
+      __ LoadSmiLiteral(r6, Smi::FromInt(i));
+      __ LoadSmiLiteral(r7, Smi::FromInt(expr->literal_index()));
+      StoreArrayLiteralElementStub stub;
+      __ CallStub(&stub);
+    }
+
+    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
+  }
+
+  if (result_saved) {
+    context()->PlugTOS();
+  } else {
+    context()->Plug(r3);
+  }
+}
+
+
+void FullCodeGenerator::VisitAssignment(Assignment* expr) {
+  Comment cmnt(masm_, "[ Assignment");
+  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
+  // on the left-hand side.
+  if (!expr->target()->IsValidLeftHandSide()) {
+    VisitForEffect(expr->target());
+    return;
+  }
+
+  // Left-hand side can only be a property, a global or a (parameter or local)
+  // slot.
+  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
+  LhsKind assign_type = VARIABLE;
+  Property* property = expr->target()->AsProperty();
+  if (property != NULL) {
+    assign_type = (property->key()->IsPropertyName())
+        ? NAMED_PROPERTY
+        : KEYED_PROPERTY;
+  }
+
+  // Evaluate LHS expression.
+  switch (assign_type) {
+    case VARIABLE:
+      // Nothing to do here.
+      break;
+    case NAMED_PROPERTY:
+      if (expr->is_compound()) {
+        // We need the receiver both on the stack and in the accumulator.
+        VisitForAccumulatorValue(property->obj());
+        __ push(result_register());
+      } else {
+        VisitForStackValue(property->obj());
+      }
+      break;
+    case KEYED_PROPERTY:
+      if (expr->is_compound()) {
+        VisitForStackValue(property->obj());
+        VisitForAccumulatorValue(property->key());
+        __ LoadP(r4, MemOperand(sp, 0));
+        __ push(r3);
+      } else {
+        VisitForStackValue(property->obj());
+        VisitForStackValue(property->key());
+      }
+      break;
+  }
+
+  // For compound assignments we need another deoptimization point after the
+  // variable/property load.
+  if (expr->is_compound()) {
+    { AccumulatorValueContext context(this);
+      switch (assign_type) {
+        case VARIABLE:
+          EmitVariableLoad(expr->target()->AsVariableProxy());
+          PrepareForBailout(expr->target(), TOS_REG);
+          break;
+        case NAMED_PROPERTY:
+          EmitNamedPropertyLoad(property);
+          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          break;
+        case KEYED_PROPERTY:
+          EmitKeyedPropertyLoad(property);
+          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          break;
+      }
+    }
+
+    Token::Value op = expr->binary_op();
+    __ push(r3);  // Left operand goes on the stack.
+    VisitForAccumulatorValue(expr->value());
+
+    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
+        ? OVERWRITE_RIGHT
+        : NO_OVERWRITE;
+    SetSourcePosition(expr->position() + 1);
+    AccumulatorValueContext context(this);
+    if (ShouldInlineSmiCase(op)) {
+      EmitInlineSmiBinaryOp(expr->binary_operation(),
+                            op,
+                            mode,
+                            expr->target(),
+                            expr->value());
+    } else {
+      EmitBinaryOp(expr->binary_operation(), op, mode);
+    }
+
+    // Deoptimization point in case the binary operation may have side effects.
+    PrepareForBailout(expr->binary_operation(), TOS_REG);
+  } else {
+    VisitForAccumulatorValue(expr->value());
+  }
+
+  // Record source position before possible IC call.
+  SetSourcePosition(expr->position());
+
+  // Store the value.
+  switch (assign_type) {
+    case VARIABLE:
+      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
+                             expr->op());
+      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      context()->Plug(r3);
+      break;
+    case NAMED_PROPERTY:
+      EmitNamedPropertyAssignment(expr);
+      break;
+    case KEYED_PROPERTY:
+      EmitKeyedPropertyAssignment(expr);
+      break;
+  }
+}
+
+
+void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
+  SetSourcePosition(prop->position());
+  Literal* key = prop->key()->AsLiteral();
+  __ mov(r5, Operand(key->handle()));
+  // Call load IC. It has arguments receiver and property name r3 and r5.
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+  CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
+}
+
+
+void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
+  SetSourcePosition(prop->position());
+  // Call keyed load IC. It has arguments key and receiver in r3 and r4.
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
+  CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
+}
+
+
+void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
+                                              Token::Value op,
+                                              OverwriteMode mode,
+                                              Expression* left_expr,
+                                              Expression* right_expr) {
+  Label done, smi_case, stub_call;
+
+  Register scratch1 = r5;
+  Register scratch2 = r6;
+
+  // Get the arguments.
+  Register left = r4;
+  Register right = r3;
+  __ pop(left);
+
+  // Perform combined smi check on both operands.
+  __ orx(scratch1, left, right);
+  STATIC_ASSERT(kSmiTag == 0);
+  JumpPatchSite patch_site(masm_);
+  patch_site.EmitJumpIfSmi(scratch1, &smi_case);
+
+  __ bind(&stub_call);
+  BinaryOpStub stub(op, mode);
+  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET,
+         expr->BinaryOperationFeedbackId());
+  patch_site.EmitPatchInfo();
+  __ b(&done);
+
+  __ bind(&smi_case);
+  // Smi case. This code works the same way as the smi-smi case in the type
+  // recording binary operation stub, see
+  // BinaryOpStub::GenerateSmiSmiOperation for comments.
+  switch (op) {
+    case Token::SAR:
+      __ b(&stub_call);
+      __ GetLeastBitsFromSmi(scratch1, right, 5);
+      __ ShiftRightArith(right, left, scratch1);
+      __ ClearRightImm(right, right, Operand(kSmiTagSize + kSmiShiftSize));
+      break;
+    case Token::SHL: {
+      __ b(&stub_call);
+      __ GetLeastBitsFromSmi(scratch2, right, 5);
+#if V8_TARGET_ARCH_PPC64
+      __ ShiftLeft(right, left, scratch2);
+#else
+      __ SmiUntag(scratch1, left);
+      __ ShiftLeft(scratch1, scratch1, scratch2);
+      // Check that the *signed* result fits in a smi
+      __ JumpIfNotSmiCandidate(scratch1, scratch2, &stub_call);
+      __ SmiTag(right, scratch1);
+#endif
+      break;
+    }
+    case Token::SHR: {
+      __ b(&stub_call);
+      __ SmiUntag(scratch1, left);
+      __ GetLeastBitsFromSmi(scratch2, right, 5);
+      __ srw(scratch1, scratch1, scratch2);
+      // Unsigned shift is not allowed to produce a negative number.
+      __ JumpIfNotUnsignedSmiCandidate(scratch1, r0, &stub_call);
+      __ SmiTag(right, scratch1);
+      break;
+    }
+    case Token::ADD: {
+      Label add_no_overflow;
+      // C = A+B; C overflows if A/B have same sign and C has diff sign than A
+      __ xor_(r0, left, right);
+      __ add(scratch1, left, right);
+      __ TestSignBit(r0, r0);
+      __ bne(&add_no_overflow, cr0);
+      __ xor_(r0, right, scratch1);
+      __ TestSignBit(r0, r0);
+      __ bne(&stub_call, cr0);
+      __ bind(&add_no_overflow);
+      __ mr(right, scratch1);
+      break;
+    }
+    case Token::SUB: {
+      Label sub_no_overflow;
+      // C = A-B; C overflows if A/B have diff signs and C has diff sign than A
+      __ xor_(r0, left, right);
+      __ sub(scratch1, left, right);
+      __ TestSignBit(r0, r0);
+      __ beq(&sub_no_overflow, cr0);
+      __ xor_(r0, scratch1, left);
+      __ TestSignBit(r0, r0);
+      __ bne(&stub_call, cr0);
+      __ bind(&sub_no_overflow);
+      __ mr(right, scratch1);
+      break;
+    }
+    case Token::MUL: {
+      Label mul_zero;
+#if V8_TARGET_ARCH_PPC64
+      // Remove tag from both operands.
+      __ SmiUntag(ip, right);
+      __ SmiUntag(r0, left);
+      __ Mul(scratch1, r0, ip);
+      // Check for overflowing the smi range - no overflow if higher 33 bits of
+      // the result are identical.
+      __ TestIfInt32(scratch1, scratch2, ip);
+      __ bne(&stub_call);
+#else
+      __ SmiUntag(ip, right);
+      __ mullw(scratch1, left, ip);
+      __ mulhw(scratch2, left, ip);
+      // Check for overflowing the smi range - no overflow if higher 33 bits of
+      // the result are identical.
+      __ TestIfInt32(scratch2, scratch1, ip);
+      __ bne(&stub_call);
+#endif
+      // Go slow on zero result to handle -0.
+      __ cmpi(scratch1, Operand::Zero());
+      __ beq(&mul_zero);
+#if V8_TARGET_ARCH_PPC64
+      __ SmiTag(right, scratch1);
+#else
+      __ mr(right, scratch1);
+#endif
+      __ b(&done);
+      // We need -0 if we were multiplying a negative number with 0 to get 0.
+      // We know one of them was zero.
+      __ bind(&mul_zero);
+      __ add(scratch2, right, left);
+      __ cmpi(scratch2, Operand::Zero());
+      __ blt(&stub_call);
+      __ LoadSmiLiteral(right, Smi::FromInt(0));
+      break;
+    }
+    case Token::BIT_OR:
+      __ orx(right, left, right);
+      break;
+    case Token::BIT_AND:
+      __ and_(right, left, right);
+      break;
+    case Token::BIT_XOR:
+      __ xor_(right, left, right);
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  __ bind(&done);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
+                                     Token::Value op,
+                                     OverwriteMode mode) {
+  __ pop(r4);
+  BinaryOpStub stub(op, mode);
+  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
+  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET,
+         expr->BinaryOperationFeedbackId());
+  patch_site.EmitPatchInfo();
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitAssignment(Expression* expr) {
+  // Invalid left-hand sides are rewritten to have a 'throw
+  // ReferenceError' on the left-hand side.
+  if (!expr->IsValidLeftHandSide()) {
+    VisitForEffect(expr);
+    return;
+  }
+
+  // Left-hand side can only be a property, a global or a (parameter or local)
+  // slot.
+  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
+  LhsKind assign_type = VARIABLE;
+  Property* prop = expr->AsProperty();
+  if (prop != NULL) {
+    assign_type = (prop->key()->IsPropertyName())
+        ? NAMED_PROPERTY
+        : KEYED_PROPERTY;
+  }
+
+  switch (assign_type) {
+    case VARIABLE: {
+      Variable* var = expr->AsVariableProxy()->var();
+      EffectContext context(this);
+      EmitVariableAssignment(var, Token::ASSIGN);
+      break;
+    }
+    case NAMED_PROPERTY: {
+      __ push(r3);  // Preserve value.
+      VisitForAccumulatorValue(prop->obj());
+      __ mr(r4, r3);
+      __ pop(r3);  // Restore value.
+      __ mov(r5, Operand(prop->key()->AsLiteral()->handle()));
+      Handle<Code> ic = is_classic_mode()
+          ? isolate()->builtins()->StoreIC_Initialize()
+          : isolate()->builtins()->StoreIC_Initialize_Strict();
+      CallIC(ic);
+      break;
+    }
+    case KEYED_PROPERTY: {
+      __ push(r3);  // Preserve value.
+      VisitForStackValue(prop->obj());
+      VisitForAccumulatorValue(prop->key());
+      __ mr(r4, r3);
+      __ pop(r5);
+      __ pop(r3);  // Restore value.
+      Handle<Code> ic = is_classic_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize()
+          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
+      CallIC(ic);
+      break;
+    }
+  }
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+                                               Token::Value op) {
+  if (var->IsUnallocated()) {
+    // Global var, const, or let.
+    __ mov(r5, Operand(var->name()));
+    __ LoadP(r4, GlobalObjectOperand());
+    Handle<Code> ic = is_classic_mode()
+        ? isolate()->builtins()->StoreIC_Initialize()
+        : isolate()->builtins()->StoreIC_Initialize_Strict();
+    CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
+
+  } else if (op == Token::INIT_CONST) {
+    // Const initializers need a write barrier.
+    ASSERT(!var->IsParameter());  // No const parameters.
+    if (var->IsStackLocal()) {
+      Label skip;
+      __ LoadP(r4, StackOperand(var));
+      __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
+      __ bne(&skip);
+      __ StoreP(result_register(), StackOperand(var));
+      __ bind(&skip);
+    } else {
+      ASSERT(var->IsContextSlot() || var->IsLookupSlot());
+      // Like var declarations, const declarations are hoisted to function
+      // scope.  However, unlike var initializers, const initializers are
+      // able to drill a hole to that function context, even from inside a
+      // 'with' context.  We thus bypass the normal static scope lookup for
+      // var->IsContextSlot().
+      __ push(r3);
+      __ mov(r3, Operand(var->name()));
+      __ Push(cp, r3);  // Context and name.
+      __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
+    }
+
+  } else if (var->mode() == LET && op != Token::INIT_LET) {
+    // Non-initializing assignment to let variable needs a write barrier.
+    if (var->IsLookupSlot()) {
+      __ push(r3);  // Value.
+      __ mov(r4, Operand(var->name()));
+      __ LoadSmiLiteral(r3, Smi::FromInt(language_mode()));
+      __ Push(cp, r4, r3);  // Context, name, strict mode.
+      __ CallRuntime(Runtime::kStoreContextSlot, 4);
+    } else {
+      ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+      Label assign;
+      MemOperand location = VarOperand(var, r4);
+      __ LoadP(r6, location);
+      __ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
+      __ bne(&assign);
+      __ mov(r6, Operand(var->name()));
+      __ push(r6);
+      __ CallRuntime(Runtime::kThrowReferenceError, 1);
+      // Perform the assignment.
+      __ bind(&assign);
+      __ StoreP(result_register(), location, r0);
+      if (var->IsContextSlot()) {
+        // RecordWrite may destroy all its register arguments.
+        __ mr(r6, result_register());
+        int offset = Context::SlotOffset(var->index());
+        __ RecordWriteContextSlot(
+            r4, offset, r6, r5, kLRHasBeenSaved, kDontSaveFPRegs);
+      }
+    }
+
+  } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
+    // Assignment to var or initializing assignment to let/const
+    // in harmony mode.
+    if (var->IsStackAllocated() || var->IsContextSlot()) {
+      MemOperand location = VarOperand(var, r4);
+      if (generate_debug_code_ && op == Token::INIT_LET) {
+        // Check for an uninitialized let binding.
+        __ LoadP(r5, location);
+        __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
+        __ Check(eq, "Let binding re-initialization.");
+      }
+      // Perform the assignment.
+      __ StoreP(r3, location, r0);
+      if (var->IsContextSlot()) {
+        __ mr(r6, r3);
+        int offset = Context::SlotOffset(var->index());
+        __ RecordWriteContextSlot(
+            r4, offset, r6, r5, kLRHasBeenSaved, kDontSaveFPRegs);
+      }
+    } else {
+      ASSERT(var->IsLookupSlot());
+      __ push(r3);  // Value.
+      __ mov(r4, Operand(var->name()));
+      __ LoadSmiLiteral(r3, Smi::FromInt(language_mode()));
+      __ Push(cp, r4, r3);  // Context, name, strict mode.
+      __ CallRuntime(Runtime::kStoreContextSlot, 4);
+    }
+  }
+  // Non-initializing assignments to consts are ignored.
+}
+
+
+void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a named store IC.
+  Property* prop = expr->target()->AsProperty();
+  ASSERT(prop != NULL);
+  ASSERT(prop->key()->AsLiteral() != NULL);
+
+  // Record source code position before IC call.
+  SetSourcePosition(expr->position());
+  __ mov(r5, Operand(prop->key()->AsLiteral()->handle()));
+  __ pop(r4);
+
+  Handle<Code> ic = is_classic_mode()
+      ? isolate()->builtins()->StoreIC_Initialize()
+      : isolate()->builtins()->StoreIC_Initialize_Strict();
+  CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
+
+  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
+  // Assignment to a property, using a keyed store IC.
+
+  // Record source code position before IC call.
+  SetSourcePosition(expr->position());
+  __ pop(r4);  // Key.
+  __ pop(r5);
+
+  Handle<Code> ic = is_classic_mode()
+      ? isolate()->builtins()->KeyedStoreIC_Initialize()
+      : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
+  CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
+
+  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::VisitProperty(Property* expr) {
+  Comment cmnt(masm_, "[ Property");
+  Expression* key = expr->key();
+
+  if (key->IsPropertyName()) {
+    VisitForAccumulatorValue(expr->obj());
+    EmitNamedPropertyLoad(expr);
+    PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+    context()->Plug(r3);
+  } else {
+    VisitForStackValue(expr->obj());
+    VisitForAccumulatorValue(expr->key());
+    __ pop(r4);
+    EmitKeyedPropertyLoad(expr);
+    context()->Plug(r3);
+  }
+}
+
+
+void FullCodeGenerator::CallIC(Handle<Code> code,
+                               RelocInfo::Mode rmode,
+                               TypeFeedbackId ast_id) {
+  ic_total_count_++;
+  __ Call(code, rmode, ast_id);
+}
+
+void FullCodeGenerator::EmitCallWithIC(Call* expr,
+                                       Handle<Object> name,
+                                       RelocInfo::Mode mode) {
+  // Code common for calls using the IC.
+  ZoneList<Expression*>* args = expr->arguments();
+  int arg_count = args->length();
+  { PreservePositionScope scope(masm()->positions_recorder());
+    for (int i = 0; i < arg_count; i++) {
+      VisitForStackValue(args->at(i));
+    }
+    __ mov(r5, Operand(name));
+  }
+  // Record source position for debugger.
+  SetSourcePosition(expr->position());
+  // Call the IC initialization code.
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
+  CallIC(ic, mode, expr->CallFeedbackId());
+  RecordJSReturnSite(expr);
+  // Restore context register.
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
+                                            Expression* key) {
+  // Load the key.
+  VisitForAccumulatorValue(key);
+
+  // Swap the name of the function and the receiver on the stack to follow
+  // the calling convention for call ICs.
+  __ pop(r4);
+  __ push(r3);
+  __ push(r4);
+
+  // Code common for calls using the IC.
+  ZoneList<Expression*>* args = expr->arguments();
+  int arg_count = args->length();
+  { PreservePositionScope scope(masm()->positions_recorder());
+    for (int i = 0; i < arg_count; i++) {
+      VisitForStackValue(args->at(i));
+    }
+  }
+  // Record source position for debugger.
+  SetSourcePosition(expr->position());
+  // Call the IC initialization code.
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
+  __ LoadP(r5, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);  // Key.
+  CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId());
+  RecordJSReturnSite(expr);
+  // Restore context register.
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  context()->DropAndPlug(1, r3);  // Drop the key still on the stack.
+}
+
+
+void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
+  // Code common for calls using the call stub.
+  ZoneList<Expression*>* args = expr->arguments();
+  int arg_count = args->length();
+  { PreservePositionScope scope(masm()->positions_recorder());
+    for (int i = 0; i < arg_count; i++) {
+      VisitForStackValue(args->at(i));
+    }
+  }
+  // Record source position for debugger.
+  SetSourcePosition(expr->position());
+
+  // Record call targets in unoptimized code.
+  flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
+  Handle<Object> uninitialized =
+      TypeFeedbackCells::UninitializedSentinel(isolate());
+  Handle<JSGlobalPropertyCell> cell =
+      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
+  __ mov(r5, Operand(cell));
+
+  CallFunctionStub stub(arg_count, flags);
+  __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
+  __ CallStub(&stub);
+  RecordJSReturnSite(expr);
+  // Restore context register.
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  context()->DropAndPlug(1, r3);
+}
+
+
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+  // Push copy of the first argument or undefined if it doesn't exist.
+  if (arg_count > 0) {
+    __ LoadP(r4, MemOperand(sp, arg_count * kPointerSize), r0);
+  } else {
+    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
+  }
+  __ push(r4);
+
+  // Push the receiver of the enclosing function.
+  int receiver_offset = 2 + info_->scope()->num_parameters();
+  __ LoadP(r4, MemOperand(fp, receiver_offset * kPointerSize), r0);
+  __ push(r4);
+  // Push the language mode.
+  __ LoadSmiLiteral(r4, Smi::FromInt(language_mode()));
+  __ push(r4);
+
+  // Push the start position of the scope the calls resides in.
+  __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position()));
+  __ push(r4);
+
+  // Do the runtime call.
+  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+}
+
+
+void FullCodeGenerator::VisitCall(Call* expr) {
+#ifdef DEBUG
+  // We want to verify that RecordJSReturnSite gets called on all paths
+  // through this function.  Avoid early returns.
+  expr->return_is_recorded_ = false;
+#endif
+
+  Comment cmnt(masm_, "[ Call");
+  Expression* callee = expr->expression();
+  VariableProxy* proxy = callee->AsVariableProxy();
+  Property* property = callee->AsProperty();
+
+  if (proxy != NULL && proxy->var()->is_possibly_eval()) {
+    // In a call to eval, we first call %ResolvePossiblyDirectEval to
+    // resolve the function we need to call and the receiver of the
+    // call.  Then we call the resolved function using the given
+    // arguments.
+    ZoneList<Expression*>* args = expr->arguments();
+    int arg_count = args->length();
+
+    { PreservePositionScope pos_scope(masm()->positions_recorder());
+      VisitForStackValue(callee);
+      __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+      __ push(r5);  // Reserved receiver slot.
+
+      // Push the arguments.
+      for (int i = 0; i < arg_count; i++) {
+        VisitForStackValue(args->at(i));
+      }
+
+      // Push a copy of the function (found below the arguments) and
+      // resolve eval.
+      __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
+      __ push(r4);
+      EmitResolvePossiblyDirectEval(arg_count);
+
+      // The runtime call returns a pair of values in r3 (function) and
+      // r4 (receiver). Touch up the stack with the right values.
+      __ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
+      __ StoreP(r4, MemOperand(sp, arg_count * kPointerSize), r0);
+    }
+
+    // Record source position for debugger.
+    SetSourcePosition(expr->position());
+    CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
+    __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
+    __ CallStub(&stub);
+    RecordJSReturnSite(expr);
+    // Restore context register.
+    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+    context()->DropAndPlug(1, r3);
+  } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
+    // Push global object as receiver for the call IC.
+    __ LoadP(r3, GlobalObjectOperand());
+    __ push(r3);
+    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
+  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
+    // Call to a lookup slot (dynamically introduced variable).
+    Label slow, done;
+
+    { PreservePositionScope scope(masm()->positions_recorder());
+      // Generate code for loading from variables potentially shadowed
+      // by eval-introduced variables.
+      EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
+    }
+
+    __ bind(&slow);
+    // Call the runtime to find the function to call (returned in r3)
+    // and the object holding it (returned in edx).
+    __ push(context_register());
+    __ mov(r5, Operand(proxy->name()));
+    __ push(r5);
+    __ CallRuntime(Runtime::kLoadContextSlot, 2);
+    __ Push(r3, r4);  // Function, receiver.
+
+    // If fast case code has been generated, emit code to push the
+    // function and receiver and have the slow path jump around this
+    // code.
+    if (done.is_linked()) {
+      Label call;
+      __ b(&call);
+      __ bind(&done);
+      // Push function.
+      __ push(r3);
+      // The receiver is implicitly the global receiver. Indicate this
+      // by passing the hole to the call function stub.
+      __ LoadRoot(r4, Heap::kTheHoleValueRootIndex);
+      __ push(r4);
+      __ bind(&call);
+    }
+
+    // The receiver is either the global receiver or an object found
+    // by LoadContextSlot. That object could be the hole if the
+    // receiver is implicitly the global object.
+    EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
+  } else if (property != NULL) {
+    { PreservePositionScope scope(masm()->positions_recorder());
+      VisitForStackValue(property->obj());
+    }
+    if (property->key()->IsPropertyName()) {
+      EmitCallWithIC(expr,
+                     property->key()->AsLiteral()->handle(),
+                     RelocInfo::CODE_TARGET);
+    } else {
+      EmitKeyedCallWithIC(expr, property->key());
+    }
+  } else {
+    // Call to an arbitrary expression not handled specially above.
+    { PreservePositionScope scope(masm()->positions_recorder());
+      VisitForStackValue(callee);
+    }
+    // Load global receiver object.
+    __ LoadP(r4, GlobalObjectOperand());
+    __ LoadP(r4, FieldMemOperand(r4, GlobalObject::kGlobalReceiverOffset));
+    __ push(r4);
+    // Emit function call.
+    EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
+  }
+
+#ifdef DEBUG
+  // RecordJSReturnSite should have been called.
+  ASSERT(expr->return_is_recorded_);
+#endif
+}
+
+
+void FullCodeGenerator::VisitCallNew(CallNew* expr) {
+  Comment cmnt(masm_, "[ CallNew");
+  // According to ECMA-262, section 11.2.2, page 44, the function
+  // expression in new calls must be evaluated before the
+  // arguments.
+
+  // Push constructor on the stack.  If it's not a function it's used as
+  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
+  // ignored.
+  VisitForStackValue(expr->expression());
+
+  // Push the arguments ("left-to-right") on the stack.
+  ZoneList<Expression*>* args = expr->arguments();
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    VisitForStackValue(args->at(i));
+  }
+
+  // Call the construct call builtin that handles allocation and
+  // constructor invocation.
+  SetSourcePosition(expr->position());
+
+  // Load function and argument count into r4 and r3.
+  __ mov(r3, Operand(arg_count));
+  __ LoadP(r4, MemOperand(sp, arg_count * kPointerSize), r0);
+
+  // Record call targets in unoptimized code.
+  Handle<Object> uninitialized =
+      TypeFeedbackCells::UninitializedSentinel(isolate());
+  Handle<JSGlobalPropertyCell> cell =
+      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
+  __ mov(r5, Operand(cell));
+
+  CallConstructStub stub(RECORD_CALL_TARGET);
+  __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
+  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  __ andi(r0, r3, Operand(kSmiTagMask));
+  Split(eq, if_true, if_false, fall_through, cr0);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  __ TestIfPositiveSmi(r3, r0);
+  Split(eq, if_true, if_false, fall_through, cr0);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ JumpIfSmi(r3, if_false);
+  __ LoadRoot(ip, Heap::kNullValueRootIndex);
+  __ cmp(r3, ip);
+  __ beq(if_true);
+  __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
+  // Undetectable objects behave like undefined when tested with typeof.
+  __ lbz(r4, FieldMemOperand(r5, Map::kBitFieldOffset));
+  __ andi(r0, r4, Operand(1 << Map::kIsUndetectable));
+  __ bne(if_false, cr0);
+  __ lbz(r4, FieldMemOperand(r5, Map::kInstanceTypeOffset));
+  __ cmpi(r4, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+  __ blt(if_false);
+  __ cmpi(r4, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(le, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ JumpIfSmi(r3, if_false);
+  __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(ge, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ JumpIfSmi(r3, if_false);
+  __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ lbz(r4, FieldMemOperand(r4, Map::kBitFieldOffset));
+  __ andi(r0, r4, Operand(1 << Map::kIsUndetectable));
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(ne, if_true, if_false, fall_through, cr0);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
+    CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ AssertNotSmi(r3);
+
+  __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ lbz(ip, FieldMemOperand(r4, Map::kBitField2Offset));
+  __ andi(r0, ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
+  __ bne(if_true, cr0);
+
+  // Check for fast case object. Generate false result for slow case object.
+  __ LoadP(r5, FieldMemOperand(r3, JSObject::kPropertiesOffset));
+  __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(r5, ip);
+  __ beq(if_false);
+
+  // Look for valueOf symbol in the descriptor array, and indicate false if
+  // found. Since we omit an enumeration index check, if it is added via a
+  // transition that shares its descriptor array, this is a false positive.
+  Label entry, loop, done;
+
+  // Skip loop if no descriptors are valid.
+  __ NumberOfOwnDescriptors(r6, r4);
+  __ cmpi(r6, Operand::Zero());
+  __ beq(&done);
+
+  __ LoadInstanceDescriptors(r4, r7);
+  // r7: descriptor array.
+  // r6: valid entries in the descriptor array.
+  __ mov(ip, Operand(DescriptorArray::kDescriptorSize));
+  __ Mul(r6, r6, ip);
+  // Calculate location of the first key name.
+  __ addi(r7, r7, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
+  // Calculate the end of the descriptor array.
+  __ mr(r5, r7);
+  __ SmiToPtrArrayOffset(ip, r6);
+  __ add(r5, r5, ip);
+
+  // Loop through all the keys in the descriptor array. If one of these is the
+  // symbol valueOf the result is false.
+  // The use of ip to store the valueOf symbol asumes that it is not otherwise
+  // used in the loop below.
+  __ mov(ip, Operand(FACTORY->value_of_symbol()));
+  __ b(&entry);
+  __ bind(&loop);
+  __ LoadP(r6, MemOperand(r7, 0));
+  __ cmp(r6, ip);
+  __ beq(if_false);
+  __ addi(r7, r7, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
+  __ bind(&entry);
+  __ cmp(r7, r5);
+  __ bne(&loop);
+
+  __ bind(&done);
+  // If a valueOf property is not found on the object check that its
+  // prototype is the un-modified String prototype. If not result is false.
+  __ LoadP(r5, FieldMemOperand(r4, Map::kPrototypeOffset));
+  __ JumpIfSmi(r5, if_false);
+  __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset));
+  __ LoadP(r6, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ LoadP(r6, FieldMemOperand(r6, GlobalObject::kNativeContextOffset));
+  __ LoadP(r6, ContextOperand(r6,
+                              Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
+  __ cmp(r5, r6);
+  __ bne(if_false);
+
+  // Set the bit in the map to indicate that it has been checked safe for
+  // default valueOf and set true result.
+  __ lbz(r5, FieldMemOperand(r4, Map::kBitField2Offset));
+  __ ori(r5, r5, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
+  __ stb(r5, FieldMemOperand(r4, Map::kBitField2Offset));
+  __ b(if_true);
+
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ JumpIfSmi(r3, if_false);
+  __ CompareObjectType(r3, r4, r5, JS_FUNCTION_TYPE);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(eq, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ JumpIfSmi(r3, if_false);
+  __ CompareObjectType(r3, r4, r4, JS_ARRAY_TYPE);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(eq, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ JumpIfSmi(r3, if_false);
+  __ CompareObjectType(r3, r4, r4, JS_REGEXP_TYPE);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(eq, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+
+void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
+  ASSERT(expr->arguments()->length() == 0);
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  // Get the frame pointer for the calling frame.
+  __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+
+  // Skip the arguments adaptor frame if it exists.
+  Label check_frame_marker;
+  __ LoadP(r4, MemOperand(r5, StandardFrameConstants::kContextOffset));
+  __ CmpSmiLiteral(r4, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+  __ bne(&check_frame_marker);
+  __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
+
+  // Check the marker in the calling frame.
+  __ bind(&check_frame_marker);
+  __ LoadP(r4, MemOperand(r5, StandardFrameConstants::kMarkerOffset));
+  STATIC_ASSERT(StackFrame::CONSTRUCT < 0x4000);
+  __ CmpSmiLiteral(r4, Smi::FromInt(StackFrame::CONSTRUCT), r0);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(eq, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+
+  // Load the two objects into registers and perform the comparison.
+  VisitForStackValue(args->at(0));
+  VisitForAccumulatorValue(args->at(1));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ pop(r4);
+  __ cmp(r3, r4);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(eq, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+
+  // ArgumentsAccessStub expects the key in edx and the formal
+  // parameter count in r3.
+  VisitForAccumulatorValue(args->at(0));
+  __ mr(r4, r3);
+  __ LoadSmiLiteral(r3, Smi::FromInt(info_->scope()->num_parameters()));
+  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
+  ASSERT(expr->arguments()->length() == 0);
+  Label exit;
+  // Get the number of formal parameters.
+  __ LoadSmiLiteral(r3, Smi::FromInt(info_->scope()->num_parameters()));
+
+  // Check if the calling frame is an arguments adaptor frame.
+  __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kContextOffset));
+  __ CmpSmiLiteral(r6, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+  __ bne(&exit);
+
+  // Arguments adaptor case: Read the arguments length from the
+  // adaptor frame.
+  __ LoadP(r3, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
+
+  __ bind(&exit);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  Label done, null, function, non_function_constructor;
+
+  VisitForAccumulatorValue(args->at(0));
+
+  // If the object is a smi, we return null.
+  __ JumpIfSmi(r3, &null);
+
+  // Check that the object is a JS object but take special care of JS
+  // functions to make sure they have 'Function' as their class.
+  // Assume that there are only two callable types, and one of them is at
+  // either end of the type range for JS object types. Saves extra comparisons.
+  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
+  __ CompareObjectType(r3, r3, r4, FIRST_SPEC_OBJECT_TYPE);
+  // Map is now in r3.
+  __ blt(&null);
+  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
+                FIRST_SPEC_OBJECT_TYPE + 1);
+  __ beq(&function);
+
+  __ cmpi(r4, Operand(LAST_SPEC_OBJECT_TYPE));
+  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
+                LAST_SPEC_OBJECT_TYPE - 1);
+  __ beq(&function);
+  // Assume that there is no larger type.
+  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
+
+  // Check if the constructor in the map is a JS function.
+  __ LoadP(r3, FieldMemOperand(r3, Map::kConstructorOffset));
+  __ CompareObjectType(r3, r4, r4, JS_FUNCTION_TYPE);
+  __ bne(&non_function_constructor);
+
+  // r3 now contains the constructor function. Grab the
+  // instance class name from there.
+  __ LoadP(r3, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r3,
+           FieldMemOperand(r3, SharedFunctionInfo::kInstanceClassNameOffset));
+  __ b(&done);
+
+  // Functions have class 'Function'.
+  __ bind(&function);
+  __ LoadRoot(r3, Heap::kfunction_class_symbolRootIndex);
+  __ b(&done);
+
+  // Objects with a non-function constructor have class 'Object'.
+  __ bind(&non_function_constructor);
+  __ LoadRoot(r3, Heap::kObject_symbolRootIndex);
+  __ b(&done);
+
+  // Non-JS objects have class null.
+  __ bind(&null);
+  __ LoadRoot(r3, Heap::kNullValueRootIndex);
+
+  // All done.
+  __ bind(&done);
+
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitLog(CallRuntime* expr) {
+  // Conditionally generate a log call.
+  // Args:
+  //   0 (literal string): The type of logging (corresponds to the flags).
+  //     This is used to determine whether or not to generate the log call.
+  //   1 (string): Format string.  Access the string at argument index 2
+  //     with '%2s' (see Logger::LogRuntime for all the formats).
+  //   2 (array): Arguments to the format string.
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT_EQ(args->length(), 3);
+  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
+    VisitForStackValue(args->at(1));
+    VisitForStackValue(args->at(2));
+    __ CallRuntime(Runtime::kLog, 2);
+  }
+
+  // Finally, we're expected to leave a value on the top of the stack.
+  __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
+  ASSERT(expr->arguments()->length() == 0);
+  Label slow_allocate_heapnumber;
+  Label heapnumber_allocated;
+
+  __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(r7, r4, r5, r9, &slow_allocate_heapnumber);
+  __ b(&heapnumber_allocated);
+
+  __ bind(&slow_allocate_heapnumber);
+  // Allocate a heap number.
+  __ CallRuntime(Runtime::kNumberAlloc, 0);
+  __ mr(r7, r3);
+
+  __ bind(&heapnumber_allocated);
+
+  // Optimization opportunity here
+  // See other platforms for reference
+  __ PrepareCallCFunction(2, r3);
+  __ LoadP(r4,
+           ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX));
+  __ mr(r3, r7);
+  __ LoadP(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
+  __ CallCFunction(
+      ExternalReference::fill_heap_number_with_random_function(isolate()), 2);
+
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
+  // Load the arguments on the stack and call the stub.
+  SubStringStub stub;
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 3);
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+  VisitForStackValue(args->at(2));
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
+  // Load the arguments on the stack and call the stub.
+  RegExpExecStub stub;
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 4);
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+  VisitForStackValue(args->at(2));
+  VisitForStackValue(args->at(3));
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Label done;
+  // If the object is a smi return the object.
+  __ JumpIfSmi(r3, &done);
+  // If the object is not a value type, return the object.
+  __ CompareObjectType(r3, r4, r4, JS_VALUE_TYPE);
+  __ bne(&done);
+  __ LoadP(r3, FieldMemOperand(r3, JSValue::kValueOffset));
+
+  __ bind(&done);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+  ASSERT_NE(NULL, args->at(1)->AsLiteral());
+  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle()));
+
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Label runtime, done, not_date_object;
+  Register object = r3;
+  Register result = r3;
+  Register scratch0 = r22;
+  Register scratch1 = r4;
+
+  __ JumpIfSmi(object, &not_date_object);
+  __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE);
+  __ bne(&not_date_object);
+
+  if (index->value() == 0) {
+    __ LoadP(result, FieldMemOperand(object, JSDate::kValueOffset));
+    __ b(&done);
+  } else {
+    if (index->value() < JSDate::kFirstUncachedField) {
+      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
+      __ mov(scratch1, Operand(stamp));
+      __ LoadP(scratch1, MemOperand(scratch1));
+      __ LoadP(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset));
+      __ cmp(scratch1, scratch0);
+      __ bne(&runtime);
+      __ LoadP(result, FieldMemOperand(object, JSDate::kValueOffset +
+                                       kPointerSize * index->value()),
+               scratch0);
+      __ b(&done);
+    }
+    __ bind(&runtime);
+    __ PrepareCallCFunction(2, scratch1);
+    __ LoadSmiLiteral(r4, index);
+    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
+    __ b(&done);
+  }
+
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+  __ bind(&done);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
+  // Load the arguments on the stack and call the runtime function.
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+  MathPowStub stub(MathPowStub::ON_STACK);
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+  VisitForStackValue(args->at(0));  // Load the object.
+  VisitForAccumulatorValue(args->at(1));  // Load the value.
+  __ pop(r4);  // r3 = value. r4 = object.
+
+  Label done;
+  // If the object is a smi, return the value.
+  __ JumpIfSmi(r4, &done);
+
+  // If the object is not a value type, return the value.
+  __ CompareObjectType(r4, r5, r5, JS_VALUE_TYPE);
+  __ bne(&done);
+
+  // Store the value.
+  __ StoreP(r3, FieldMemOperand(r4, JSValue::kValueOffset), r0);
+  // Update the write barrier.  Save the value as it will be
+  // overwritten by the write barrier code and is needed afterward.
+  __ mr(r5, r3);
+  __ RecordWriteField(
+      r4, JSValue::kValueOffset, r5, r6, kLRHasBeenSaved, kDontSaveFPRegs);
+
+  __ bind(&done);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT_EQ(args->length(), 1);
+  // Load the argument on the stack and call the stub.
+  VisitForStackValue(args->at(0));
+
+  NumberToStringStub stub;
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForAccumulatorValue(args->at(0));
+
+  Label done;
+  StringCharFromCodeGenerator generator(r3, r4);
+  generator.GenerateFast(masm_);
+  __ b(&done);
+
+  NopRuntimeCallHelper call_helper;
+  generator.GenerateSlow(masm_, call_helper);
+
+  __ bind(&done);
+  context()->Plug(r4);
+}
+
+
+void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+  VisitForStackValue(args->at(0));
+  VisitForAccumulatorValue(args->at(1));
+
+  Register object = r4;
+  Register index = r3;
+  Register result = r6;
+
+  __ pop(object);
+
+  Label need_conversion;
+  Label index_out_of_range;
+  Label done;
+  StringCharCodeAtGenerator generator(object,
+                                      index,
+                                      result,
+                                      &need_conversion,
+                                      &need_conversion,
+                                      &index_out_of_range,
+                                      STRING_INDEX_IS_NUMBER);
+  generator.GenerateFast(masm_);
+  __ b(&done);
+
+  __ bind(&index_out_of_range);
+  // When the index is out of range, the spec requires us to return
+  // NaN.
+  __ LoadRoot(result, Heap::kNanValueRootIndex);
+  __ b(&done);
+
+  __ bind(&need_conversion);
+  // Load the undefined value into the result register, which will
+  // trigger conversion.
+  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
+  __ b(&done);
+
+  NopRuntimeCallHelper call_helper;
+  generator.GenerateSlow(masm_, call_helper);
+
+  __ bind(&done);
+  context()->Plug(result);
+}
+
+
+void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+  VisitForStackValue(args->at(0));
+  VisitForAccumulatorValue(args->at(1));
+
+  Register object = r4;
+  Register index = r3;
+  Register scratch = r6;
+  Register result = r3;
+
+  __ pop(object);
+
+  Label need_conversion;
+  Label index_out_of_range;
+  Label done;
+  StringCharAtGenerator generator(object,
+                                  index,
+                                  scratch,
+                                  result,
+                                  &need_conversion,
+                                  &need_conversion,
+                                  &index_out_of_range,
+                                  STRING_INDEX_IS_NUMBER);
+  generator.GenerateFast(masm_);
+  __ b(&done);
+
+  __ bind(&index_out_of_range);
+  // When the index is out of range, the spec requires us to return
+  // the empty string.
+  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
+  __ b(&done);
+
+  __ bind(&need_conversion);
+  // Move smi zero into the result register, which will trigger
+  // conversion.
+  __ LoadSmiLiteral(result, Smi::FromInt(0));
+  __ b(&done);
+
+  NopRuntimeCallHelper call_helper;
+  generator.GenerateSlow(masm_, call_helper);
+
+  __ bind(&done);
+  context()->Plug(result);
+}
+
+
+void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  StringAddStub stub(NO_STRING_ADD_FLAGS);
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT_EQ(2, args->length());
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+
+  StringCompareStub stub;
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
+  // Load the argument on the stack and call the stub.
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::TAGGED);
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
+  // Load the argument on the stack and call the stub.
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::TAGGED);
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitMathTan(CallRuntime* expr) {
+  // Load the argument on the stack and call the stub.
+  TranscendentalCacheStub stub(TranscendentalCache::TAN,
+                               TranscendentalCacheStub::TAGGED);
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
+  // Load the argument on the stack and call the stub.
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::TAGGED);
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
+  // Load the argument on the stack and call the runtime function.
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForStackValue(args->at(0));
+  __ CallRuntime(Runtime::kMath_sqrt, 1);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() >= 2);
+
+  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
+  for (int i = 0; i < arg_count + 1; i++) {
+    VisitForStackValue(args->at(i));
+  }
+  VisitForAccumulatorValue(args->last());  // Function.
+
+  Label runtime, done;
+  // Check for non-function argument (including proxy).
+  __ JumpIfSmi(r3, &runtime);
+  __ CompareObjectType(r3, r4, r4, JS_FUNCTION_TYPE);
+  __ bne(&runtime);
+
+  // InvokeFunction requires the function in r4. Move it in there.
+  __ mr(r4, result_register());
+  ParameterCount count(arg_count);
+  __ InvokeFunction(r4, count, CALL_FUNCTION,
+                    NullCallWrapper(), CALL_AS_METHOD);
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  __ b(&done);
+
+  __ bind(&runtime);
+  __ push(r3);
+  __ CallRuntime(Runtime::kCall, args->length());
+  __ bind(&done);
+
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
+  RegExpConstructResultStub stub;
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 3);
+  VisitForStackValue(args->at(0));
+  VisitForStackValue(args->at(1));
+  VisitForStackValue(args->at(2));
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT_EQ(2, args->length());
+  ASSERT_NE(NULL, args->at(0)->AsLiteral());
+  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
+
+  Handle<FixedArray> jsfunction_result_caches(
+      isolate()->native_context()->jsfunction_result_caches());
+  if (jsfunction_result_caches->length() <= cache_id) {
+    __ Abort("Attempt to use undefined cache.");
+    __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+    context()->Plug(r3);
+    return;
+  }
+
+  VisitForAccumulatorValue(args->at(1));
+
+  Register key = r3;
+  Register cache = r4;
+  __ LoadP(cache, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+  __ LoadP(cache, FieldMemOperand(cache, GlobalObject::kNativeContextOffset));
+  __ LoadP(cache,
+           ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
+  __ LoadP(cache,
+           FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)), r0);
+
+  Label done, not_found;
+  // tmp now holds finger offset as a smi.
+  __ LoadP(r5, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
+  // r5 now holds finger offset as a smi.
+  __ addi(r6, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  // r6 now points to the start of fixed array elements.
+  __ SmiToPtrArrayOffset(r5, r5);
+  __ LoadPUX(r5, MemOperand(r6, r5));
+  // r6 now points to the key of the pair.
+  __ cmp(key, r5);
+  __ bne(&not_found);
+
+  __ LoadP(r3, MemOperand(r6, kPointerSize));
+  __ b(&done);
+
+  __ bind(&not_found);
+  // Call runtime to perform the lookup.
+  __ Push(cache, key);
+  __ CallRuntime(Runtime::kGetFromCache, 2);
+
+  __ bind(&done);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT_EQ(2, args->length());
+
+  Register right = r3;
+  Register left = r4;
+  Register tmp = r5;
+  Register tmp2 = r6;
+
+  VisitForStackValue(args->at(0));
+  VisitForAccumulatorValue(args->at(1));
+  __ pop(left);
+
+  Label done, fail, ok;
+  __ cmp(left, right);
+  __ beq(&ok);
+  // Fail if either is a non-HeapObject.
+  __ and_(tmp, left, right);
+  __ JumpIfSmi(tmp, &fail);
+  __ LoadP(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
+  __ lbz(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
+  __ cmpi(tmp2, Operand(JS_REGEXP_TYPE));
+  __ bne(&fail);
+  __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
+  __ cmp(tmp, tmp2);
+  __ bne(&fail);
+  __ LoadP(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
+  __ LoadP(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
+  __ cmp(tmp, tmp2);
+  __ beq(&ok);
+  __ bind(&fail);
+  __ LoadRoot(r3, Heap::kFalseValueRootIndex);
+  __ b(&done);
+  __ bind(&ok);
+  __ LoadRoot(r3, Heap::kTrueValueRootIndex);
+  __ bind(&done);
+
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  __ lwz(r3, FieldMemOperand(r3, String::kHashFieldOffset));
+  // PPC - assume ip is free
+  __ mov(ip, Operand(String::kContainsCachedArrayIndexMask));
+  __ and_(r0, r3, ip);
+  __ cmpi(r0, Operand::Zero());
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(eq, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 1);
+  VisitForAccumulatorValue(args->at(0));
+
+  __ AssertString(r3);
+
+  __ lwz(r3, FieldMemOperand(r3, String::kHashFieldOffset));
+  __ IndexFromHash(r3, r3);
+
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
+  Label bailout, done, one_char_separator, long_separator,
+      non_trivial_array, not_size_one_array, loop,
+      empty_separator_loop, one_char_separator_loop,
+      one_char_separator_loop_entry, long_separator_loop;
+  ZoneList<Expression*>* args = expr->arguments();
+  ASSERT(args->length() == 2);
+  VisitForStackValue(args->at(1));
+  VisitForAccumulatorValue(args->at(0));
+
+  // All aliases of the same register have disjoint lifetimes.
+  Register array = r3;
+  Register elements = no_reg;  // Will be r3.
+  Register result = no_reg;  // Will be r3.
+  Register separator = r4;
+  Register array_length = r5;
+  Register result_pos = no_reg;  // Will be r5
+  Register string_length = r6;
+  Register string = r7;
+  Register element = r8;
+  Register elements_end = r9;
+  Register scratch1 = r10;
+  Register scratch2 = r22;
+
+  // Separator operand is on the stack.
+  __ pop(separator);
+
+  // Check that the array is a JSArray.
+  __ JumpIfSmi(array, &bailout);
+  __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE);
+  __ bne(&bailout);
+
+  // Check that the array has fast elements.
+  __ CheckFastElements(scratch1, scratch2, &bailout);
+
+  // If the array has length zero, return the empty string.
+  __ LoadP(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
+  __ SmiUntag(array_length);
+  __ cmpi(array_length, Operand::Zero());
+  __ bne(&non_trivial_array);
+  __ LoadRoot(r3, Heap::kEmptyStringRootIndex);
+  __ b(&done);
+
+  __ bind(&non_trivial_array);
+
+  // Get the FixedArray containing array's elements.
+  elements = array;
+  __ LoadP(elements, FieldMemOperand(array, JSArray::kElementsOffset));
+  array = no_reg;  // End of array's live range.
+
+  // Check that all array elements are sequential ASCII strings, and
+  // accumulate the sum of their lengths, as a smi-encoded value.
+  __ li(string_length, Operand::Zero());
+  __ addi(element,
+          elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ ShiftLeftImm(elements_end, array_length, Operand(kPointerSizeLog2));
+  __ add(elements_end, element, elements_end);
+  // Loop condition: while (element < elements_end).
+  // Live values in registers:
+  //   elements: Fixed array of strings.
+  //   array_length: Length of the fixed array of strings (not smi)
+  //   separator: Separator string
+  //   string_length: Accumulated sum of string lengths (smi).
+  //   element: Current array element.
+  //   elements_end: Array end.
+  if (generate_debug_code_) {
+    __ cmpi(array_length, Operand::Zero());
+    __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin");
+  }
+  __ bind(&loop);
+  __ LoadP(string, MemOperand(element));
+  __ addi(element, element, Operand(kPointerSize));
+  __ JumpIfSmi(string, &bailout);
+  __ LoadP(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ lbz(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
+  __ LoadP(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset));
+
+  __ AddAndCheckForOverflow(string_length, string_length, scratch1,
+                            scratch2, r0);
+  __ BranchOnOverflow(&bailout);
+
+  __ cmp(element, elements_end);
+  __ blt(&loop);
+
+  // If array_length is 1, return elements[0], a string.
+  __ cmpi(array_length, Operand(1));
+  __ bne(&not_size_one_array);
+  __ LoadP(r3, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  __ b(&done);
+
+  __ bind(&not_size_one_array);
+
+  // Live values in registers:
+  //   separator: Separator string
+  //   array_length: Length of the array.
+  //   string_length: Sum of string lengths (smi).
+  //   elements: FixedArray of strings.
+
+  // Check that the separator is a flat ASCII string.
+  __ JumpIfSmi(separator, &bailout);
+  __ LoadP(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
+  __ lbz(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
+
+  // Add (separator length times array_length) - separator length to the
+  // string_length to get the length of the result string.
+  __ LoadP(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
+  __ sub(string_length, string_length, scratch1);
+#if V8_TARGET_ARCH_PPC64
+  __ SmiUntag(scratch1, scratch1);
+  __ Mul(scratch2, array_length, scratch1);
+  // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
+  // zero.
+  __ ShiftRightImm(ip, scratch2, Operand(31), SetRC);
+  __ bne(&bailout, cr0);
+  __ SmiTag(scratch2, scratch2);
+#else
+  // array_length is not smi but the other values are, so the result is a smi
+  __ mullw(scratch2, array_length, scratch1);
+  __ mulhw(ip, array_length, scratch1);
+  // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
+  // zero.
+  __ cmpi(ip, Operand::Zero());
+  __ bne(&bailout);
+  __ TestSignBit32(scratch2, r0);
+  __ bne(&bailout, cr0);
+#endif
+
+  __ AddAndCheckForOverflow(string_length, string_length, scratch2,
+                            scratch1, r0);
+  __ BranchOnOverflow(&bailout);
+  __ SmiUntag(string_length);
+
+  // Get first element in the array to free up the elements register to be used
+  // for the result.
+  __ addi(element,
+          elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  result = elements;  // End of live range for elements.
+  elements = no_reg;
+  // Live values in registers:
+  //   element: First array element
+  //   separator: Separator string
+  //   string_length: Length of result string (not smi)
+  //   array_length: Length of the array.
+  __ AllocateAsciiString(result,
+                         string_length,
+                         scratch1,
+                         scratch2,
+                         elements_end,
+                         &bailout);
+  // Prepare for looping. Set up elements_end to end of the array. Set
+  // result_pos to the position of the result where to write the first
+  // character.
+  __ ShiftLeftImm(elements_end, array_length, Operand(kPointerSizeLog2));
+  __ add(elements_end, element, elements_end);
+  result_pos = array_length;  // End of live range for array_length.
+  array_length = no_reg;
+  __ addi(result_pos,
+          result,
+          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+
+  // Check the length of the separator.
+  __ LoadP(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
+  __ CmpSmiLiteral(scratch1, Smi::FromInt(1), r0);
+  __ beq(&one_char_separator);
+  __ bgt(&long_separator);
+
+  // Empty separator case
+  __ bind(&empty_separator_loop);
+  // Live values in registers:
+  //   result_pos: the position to which we are currently copying characters.
+  //   element: Current array element.
+  //   elements_end: Array end.
+
+  // Copy next array element to the result.
+  __ LoadP(string, MemOperand(element));
+  __ addi(element, element, Operand(kPointerSize));
+  __ LoadP(string_length, FieldMemOperand(string, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ addi(string, string,
+          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ cmp(element, elements_end);
+  __ blt(&empty_separator_loop);  // End while (element < elements_end).
+  ASSERT(result.is(r3));
+  __ b(&done);
+
+  // One-character separator case
+  __ bind(&one_char_separator);
+  // Replace separator with its ASCII character value.
+  __ lbz(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize));
+  // Jump into the loop after the code that copies the separator, so the first
+  // element is not preceded by a separator
+  __ b(&one_char_separator_loop_entry);
+
+  __ bind(&one_char_separator_loop);
+  // Live values in registers:
+  //   result_pos: the position to which we are currently copying characters.
+  //   element: Current array element.
+  //   elements_end: Array end.
+  //   separator: Single separator ASCII char (in lower byte).
+
+  // Copy the separator character to the result.
+  __ stb(separator, MemOperand(result_pos));
+  __ addi(result_pos, result_pos, Operand(1));
+
+  // Copy next array element to the result.
+  __ bind(&one_char_separator_loop_entry);
+  __ LoadP(string, MemOperand(element));
+  __ addi(element, element, Operand(kPointerSize));
+  __ LoadP(string_length, FieldMemOperand(string, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ addi(string, string,
+          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ cmpl(element, elements_end);
+  __ blt(&one_char_separator_loop);  // End while (element < elements_end).
+  ASSERT(result.is(r3));
+  __ b(&done);
+
+  // Long separator case (separator is more than one character). Entry is at the
+  // label long_separator below.
+  __ bind(&long_separator_loop);
+  // Live values in registers:
+  //   result_pos: the position to which we are currently copying characters.
+  //   element: Current array element.
+  //   elements_end: Array end.
+  //   separator: Separator string.
+
+  // Copy the separator to the result.
+  __ LoadP(string_length, FieldMemOperand(separator, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ addi(string,
+          separator,
+          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+
+  __ bind(&long_separator);
+  __ LoadP(string, MemOperand(element));
+  __ addi(element, element, Operand(kPointerSize));
+  __ LoadP(string_length, FieldMemOperand(string, String::kLengthOffset));
+  __ SmiUntag(string_length);
+  __ addi(string, string,
+          Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ cmpl(element, elements_end);
+  __ blt(&long_separator_loop);  // End while (element < elements_end).
+  ASSERT(result.is(r3));
+  __ b(&done);
+
+  __ bind(&bailout);
+  __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+  __ bind(&done);
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
+  Handle<String> name = expr->name();
+  if (name->length() > 0 && name->Get(0) == '_') {
+    Comment cmnt(masm_, "[ InlineRuntimeCall");
+    EmitInlineRuntimeCall(expr);
+    return;
+  }
+
+  Comment cmnt(masm_, "[ CallRuntime");
+  ZoneList<Expression*>* args = expr->arguments();
+
+  if (expr->is_jsruntime()) {
+    // Prepare for calling JS runtime function.
+    __ LoadP(r3, GlobalObjectOperand());
+    __ LoadP(r3, FieldMemOperand(r3, GlobalObject::kBuiltinsOffset));
+    __ push(r3);
+  }
+
+  // Push the arguments ("left-to-right").
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    VisitForStackValue(args->at(i));
+  }
+
+  if (expr->is_jsruntime()) {
+    // Call the JS runtime function.
+    __ mov(r5, Operand(expr->name()));
+    RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
+    Handle<Code> ic =
+        isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
+    CallIC(ic, mode, expr->CallRuntimeFeedbackId());
+    // Restore context register.
+    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  } else {
+    // Call the C runtime function.
+    __ CallRuntime(expr->function(), arg_count);
+  }
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
+  switch (expr->op()) {
+    case Token::DELETE: {
+      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
+      Property* property = expr->expression()->AsProperty();
+      VariableProxy* proxy = expr->expression()->AsVariableProxy();
+
+      if (property != NULL) {
+        VisitForStackValue(property->obj());
+        VisitForStackValue(property->key());
+        StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
+            ? kNonStrictMode : kStrictMode;
+        __ LoadSmiLiteral(r4, Smi::FromInt(strict_mode_flag));
+        __ push(r4);
+        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+        context()->Plug(r3);
+      } else if (proxy != NULL) {
+        Variable* var = proxy->var();
+        // Delete of an unqualified identifier is disallowed in strict mode
+        // but "delete this" is allowed.
+        ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
+        if (var->IsUnallocated()) {
+          __ LoadP(r5, GlobalObjectOperand());
+          __ mov(r4, Operand(var->name()));
+          __ LoadSmiLiteral(r3, Smi::FromInt(kNonStrictMode));
+          __ Push(r5, r4, r3);
+          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+          context()->Plug(r3);
+        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
+          // Result of deleting non-global, non-dynamic variables is false.
+          // The subexpression does not have side effects.
+          context()->Plug(var->is_this());
+        } else {
+          // Non-global variable.  Call the runtime to try to delete from the
+          // context where the variable was introduced.
+          __ push(context_register());
+          __ mov(r5, Operand(var->name()));
+          __ push(r5);
+          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
+          context()->Plug(r3);
+        }
+      } else {
+        // Result of deleting non-property, non-variable reference is true.
+        // The subexpression may have side effects.
+        VisitForEffect(expr->expression());
+        context()->Plug(true);
+      }
+      break;
+    }
+
+    case Token::VOID: {
+      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
+      VisitForEffect(expr->expression());
+      context()->Plug(Heap::kUndefinedValueRootIndex);
+      break;
+    }
+
+    case Token::NOT: {
+      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
+      if (context()->IsEffect()) {
+        // Unary NOT has no side effects so it's only necessary to visit the
+        // subexpression.  Match the optimizing compiler by not branching.
+        VisitForEffect(expr->expression());
+      } else if (context()->IsTest()) {
+        const TestContext* test = TestContext::cast(context());
+        // The labels are swapped for the recursive call.
+        VisitForControl(expr->expression(),
+                        test->false_label(),
+                        test->true_label(),
+                        test->fall_through());
+        context()->Plug(test->true_label(), test->false_label());
+      } else {
+        // We handle value contexts explicitly rather than simply visiting
+        // for control and plugging the control flow into the context,
+        // because we need to prepare a pair of extra administrative AST ids
+        // for the optimizing compiler.
+        ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
+        Label materialize_true, materialize_false, done;
+        VisitForControl(expr->expression(),
+                        &materialize_false,
+                        &materialize_true,
+                        &materialize_true);
+        __ bind(&materialize_true);
+        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        __ LoadRoot(r3, Heap::kTrueValueRootIndex);
+        if (context()->IsStackValue()) __ push(r3);
+        __ b(&done);
+        __ bind(&materialize_false);
+        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        __ LoadRoot(r3, Heap::kFalseValueRootIndex);
+        if (context()->IsStackValue()) __ push(r3);
+        __ bind(&done);
+      }
+      break;
+    }
+
+    case Token::TYPEOF: {
+      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
+      { StackValueContext context(this);
+        VisitForTypeofValue(expr->expression());
+      }
+      __ CallRuntime(Runtime::kTypeof, 1);
+      context()->Plug(r3);
+      break;
+    }
+
+    case Token::ADD: {
+      Comment cmt(masm_, "[ UnaryOperation (ADD)");
+      VisitForAccumulatorValue(expr->expression());
+      Label no_conversion;
+      __ JumpIfSmi(result_register(), &no_conversion);
+      ToNumberStub convert_stub;
+      __ CallStub(&convert_stub);
+      __ bind(&no_conversion);
+      context()->Plug(result_register());
+      break;
+    }
+
+    case Token::SUB:
+      EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
+      break;
+
+    case Token::BIT_NOT:
+      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
+      break;
+
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
+                                           const char* comment) {
+  // TODO(svenpanne): Allowing format strings in Comment would be nice here...
+  Comment cmt(masm_, comment);
+  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
+  UnaryOverwriteMode overwrite =
+      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
+  UnaryOpStub stub(expr->op(), overwrite);
+  // UnaryOpStub expects the argument to be in the
+  // accumulator register r3.
+  VisitForAccumulatorValue(expr->expression());
+  SetSourcePosition(expr->position());
+  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET,
+         expr->UnaryOperationFeedbackId());
+  context()->Plug(r3);
+}
+
+
+void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
+  Comment cmnt(masm_, "[ CountOperation");
+  SetSourcePosition(expr->position());
+
+  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
+  // as the left-hand side.
+  if (!expr->expression()->IsValidLeftHandSide()) {
+    VisitForEffect(expr->expression());
+    return;
+  }
+
+  // Expression can only be a property, a global or a (parameter or local)
+  // slot.
+  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
+  LhsKind assign_type = VARIABLE;
+  Property* prop = expr->expression()->AsProperty();
+  // In case of a property we use the uninitialized expression context
+  // of the key to detect a named property.
+  if (prop != NULL) {
+    assign_type =
+        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
+  }
+
+  // Evaluate expression and get value.
+  if (assign_type == VARIABLE) {
+    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
+    AccumulatorValueContext context(this);
+    EmitVariableLoad(expr->expression()->AsVariableProxy());
+  } else {
+    // Reserve space for result of postfix operation.
+    if (expr->is_postfix() && !context()->IsEffect()) {
+      __ LoadSmiLiteral(ip, Smi::FromInt(0));
+      __ push(ip);
+    }
+    if (assign_type == NAMED_PROPERTY) {
+      // Put the object both on the stack and in the accumulator.
+      VisitForAccumulatorValue(prop->obj());
+      __ push(r3);
+      EmitNamedPropertyLoad(prop);
+    } else {
+      VisitForStackValue(prop->obj());
+      VisitForAccumulatorValue(prop->key());
+      __ LoadP(r4, MemOperand(sp, 0));
+      __ push(r3);
+      EmitKeyedPropertyLoad(prop);
+    }
+  }
+
+  // We need a second deoptimization point after loading the value
+  // in case evaluating the property load my have a side effect.
+  if (assign_type == VARIABLE) {
+    PrepareForBailout(expr->expression(), TOS_REG);
+  } else {
+    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+  }
+
+  // Call ToNumber only if operand is not a smi.
+  Label no_conversion;
+  __ JumpIfSmi(r3, &no_conversion);
+  ToNumberStub convert_stub;
+  __ CallStub(&convert_stub);
+  __ bind(&no_conversion);
+
+  // Save result for postfix expressions.
+  if (expr->is_postfix()) {
+    if (!context()->IsEffect()) {
+      // Save the result on the stack. If we have a named or keyed property
+      // we store the result under the receiver that is currently on top
+      // of the stack.
+      switch (assign_type) {
+        case VARIABLE:
+          __ push(r3);
+          break;
+        case NAMED_PROPERTY:
+          __ StoreP(r3, MemOperand(sp, kPointerSize));
+          break;
+        case KEYED_PROPERTY:
+          __ StoreP(r3, MemOperand(sp, 2 * kPointerSize));
+          break;
+      }
+    }
+  }
+
+  // Inline smi case if we are in a loop.
+  Label stub_call, done;
+  JumpPatchSite patch_site(masm_);
+
+  int count_value = expr->op() == Token::INC ? 1 : -1;
+  __ LoadSmiLiteral(r4, Smi::FromInt(count_value));
+
+  if (ShouldInlineSmiCase(expr->op())) {
+    __ AddAndCheckForOverflow(r3, r3, r4, r5, r0);
+    __ BranchOnOverflow(&stub_call);
+
+    // We could eliminate this smi check if we split the code at
+    // the first smi check before calling ToNumber.
+    patch_site.EmitJumpIfSmi(r3, &done);
+
+    __ bind(&stub_call);
+    // Call stub. Undo operation first.
+    __ SubSmiLiteral(r3, r3, Smi::FromInt(count_value), r0);
+  }
+
+  // Record position before stub call.
+  SetSourcePosition(expr->position());
+
+  BinaryOpStub stub(Token::ADD, NO_OVERWRITE);
+  CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountBinOpFeedbackId());
+  patch_site.EmitPatchInfo();
+  __ bind(&done);
+
+  // Store the value returned in r3.
+  switch (assign_type) {
+    case VARIABLE:
+      if (expr->is_postfix()) {
+        { EffectContext context(this);
+          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
+                                 Token::ASSIGN);
+          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          context.Plug(r3);
+        }
+        // For all contexts except EffectConstant We have the result on
+        // top of the stack.
+        if (!context()->IsEffect()) {
+          context()->PlugTOS();
+        }
+      } else {
+        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
+                               Token::ASSIGN);
+        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        context()->Plug(r3);
+      }
+      break;
+    case NAMED_PROPERTY: {
+      __ mov(r5, Operand(prop->key()->AsLiteral()->handle()));
+      __ pop(r4);
+      Handle<Code> ic = is_classic_mode()
+          ? isolate()->builtins()->StoreIC_Initialize()
+          : isolate()->builtins()->StoreIC_Initialize_Strict();
+      CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
+      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      if (expr->is_postfix()) {
+        if (!context()->IsEffect()) {
+          context()->PlugTOS();
+        }
+      } else {
+        context()->Plug(r3);
+      }
+      break;
+    }
+    case KEYED_PROPERTY: {
+      __ pop(r4);  // Key.
+      __ pop(r5);  // Receiver.
+      Handle<Code> ic = is_classic_mode()
+          ? isolate()->builtins()->KeyedStoreIC_Initialize()
+          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
+      CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
+      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      if (expr->is_postfix()) {
+        if (!context()->IsEffect()) {
+          context()->PlugTOS();
+        }
+      } else {
+        context()->Plug(r3);
+      }
+      break;
+    }
+  }
+}
+
+
+void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
+  ASSERT(!context()->IsEffect());
+  ASSERT(!context()->IsTest());
+  VariableProxy* proxy = expr->AsVariableProxy();
+  if (proxy != NULL && proxy->var()->IsUnallocated()) {
+    Comment cmnt(masm_, "Global variable");
+    __ LoadP(r3, GlobalObjectOperand());
+    __ mov(r5, Operand(proxy->name()));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+    // Use a regular load, not a contextual load, to avoid a reference
+    // error.
+    CallIC(ic);
+    PrepareForBailout(expr, TOS_REG);
+    context()->Plug(r3);
+  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
+    Label done, slow;
+
+    // Generate code for loading from variables potentially shadowed
+    // by eval-introduced variables.
+    EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
+
+    __ bind(&slow);
+    __ mov(r3, Operand(proxy->name()));
+    __ Push(cp, r3);
+    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
+    PrepareForBailout(expr, TOS_REG);
+    __ bind(&done);
+
+    context()->Plug(r3);
+  } else {
+    // This expression cannot throw a reference error at the top level.
+    VisitInDuplicateContext(expr);
+  }
+}
+
+
+void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
+                                                 Expression* sub_expr,
+                                                 Handle<String> check) {
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  { AccumulatorValueContext context(this);
+    VisitForTypeofValue(sub_expr);
+  }
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+
+  if (check->Equals(isolate()->heap()->number_symbol())) {
+    __ JumpIfSmi(r3, if_true);
+    __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+    __ cmp(r3, ip);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (check->Equals(isolate()->heap()->string_symbol())) {
+    __ JumpIfSmi(r3, if_false);
+    // Check for undetectable objects => false.
+    __ CompareObjectType(r3, r3, r4, FIRST_NONSTRING_TYPE);
+    __ bge(if_false);
+    __ lbz(r4, FieldMemOperand(r3, Map::kBitFieldOffset));
+    STATIC_ASSERT((1 << Map::kIsUndetectable) < 0x8000);
+    __ andi(r0, r4, Operand(1 << Map::kIsUndetectable));
+    Split(eq, if_true, if_false, fall_through, cr0);
+  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
+    __ CompareRoot(r3, Heap::kTrueValueRootIndex);
+    __ beq(if_true);
+    __ CompareRoot(r3, Heap::kFalseValueRootIndex);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (FLAG_harmony_typeof &&
+             check->Equals(isolate()->heap()->null_symbol())) {
+    __ CompareRoot(r3, Heap::kNullValueRootIndex);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
+    __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
+    __ beq(if_true);
+    __ JumpIfSmi(r3, if_false);
+    // Check for undetectable objects => true.
+    __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ lbz(r4, FieldMemOperand(r3, Map::kBitFieldOffset));
+    __ andi(r0, r4, Operand(1 << Map::kIsUndetectable));
+    Split(ne, if_true, if_false, fall_through, cr0);
+
+  } else if (check->Equals(isolate()->heap()->function_symbol())) {
+    __ JumpIfSmi(r3, if_false);
+    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
+    __ CompareObjectType(r3, r3, r4, JS_FUNCTION_TYPE);
+    __ beq(if_true);
+    __ cmpi(r4, Operand(JS_FUNCTION_PROXY_TYPE));
+    Split(eq, if_true, if_false, fall_through);
+  } else if (check->Equals(isolate()->heap()->object_symbol())) {
+    __ JumpIfSmi(r3, if_false);
+    if (!FLAG_harmony_typeof) {
+      __ CompareRoot(r3, Heap::kNullValueRootIndex);
+      __ beq(if_true);
+    }
+    // Check for JS objects => true.
+    __ CompareObjectType(r3, r3, r4, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
+    __ blt(if_false);
+    __ CompareInstanceType(r3, r4, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
+    __ bgt(if_false);
+    // Check for undetectable objects => false.
+    __ lbz(r4, FieldMemOperand(r3, Map::kBitFieldOffset));
+    __ andi(r0, r4, Operand(1 << Map::kIsUndetectable));
+    Split(eq, if_true, if_false, fall_through, cr0);
+  } else {
+    if (if_false != fall_through) __ b(if_false);
+  }
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
+  Comment cmnt(masm_, "[ CompareOperation");
+  SetSourcePosition(expr->position());
+
+  // First we try a fast inlined version of the compare when one of
+  // the operands is a literal.
+  if (TryLiteralCompare(expr)) return;
+
+  // Always perform the comparison for its control flow.  Pack the result
+  // into the expression's context after the comparison is performed.
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  Token::Value op = expr->op();
+  VisitForStackValue(expr->left());
+  switch (op) {
+    case Token::IN:
+      VisitForStackValue(expr->right());
+      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
+      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
+      __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+      __ cmp(r3, ip);
+      Split(eq, if_true, if_false, fall_through);
+      break;
+
+    case Token::INSTANCEOF: {
+      VisitForStackValue(expr->right());
+      InstanceofStub stub(InstanceofStub::kNoFlags);
+      __ CallStub(&stub);
+      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+      // The stub returns 0 for true.
+      __ cmpi(r3, Operand::Zero());
+      Split(eq, if_true, if_false, fall_through);
+      break;
+    }
+
+    default: {
+      VisitForAccumulatorValue(expr->right());
+      Condition cond = eq;
+      switch (op) {
+        case Token::EQ_STRICT:
+        case Token::EQ:
+          cond = eq;
+          break;
+        case Token::LT:
+          cond = lt;
+          break;
+        case Token::GT:
+          cond = gt;
+         break;
+        case Token::LTE:
+          cond = le;
+          break;
+        case Token::GTE:
+          cond = ge;
+          break;
+        case Token::IN:
+        case Token::INSTANCEOF:
+        default:
+          UNREACHABLE();
+      }
+      __ pop(r4);
+
+      bool inline_smi_code = ShouldInlineSmiCase(op);
+      JumpPatchSite patch_site(masm_);
+      if (inline_smi_code) {
+        Label slow_case;
+        __ orx(r5, r3, r4);
+        patch_site.EmitJumpIfNotSmi(r5, &slow_case);
+        __ cmp(r4, r3);
+        Split(cond, if_true, if_false, NULL);
+        __ bind(&slow_case);
+      }
+
+      // Record position and call the compare IC.
+      SetSourcePosition(expr->position());
+      Handle<Code> ic = CompareIC::GetUninitialized(op);
+      CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
+      patch_site.EmitPatchInfo();
+      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+      __ cmpi(r3, Operand::Zero());
+      Split(cond, if_true, if_false, fall_through);
+    }
+  }
+
+  // Convert the result of the comparison into one expected for this
+  // expression's context.
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
+                                              Expression* sub_expr,
+                                              NilValue nil) {
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false,
+                         &if_true, &if_false, &fall_through);
+
+  VisitForAccumulatorValue(sub_expr);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Heap::RootListIndex nil_value = nil == kNullValue ?
+      Heap::kNullValueRootIndex :
+      Heap::kUndefinedValueRootIndex;
+  __ LoadRoot(r4, nil_value);
+  __ cmp(r3, r4);
+  if (expr->op() == Token::EQ_STRICT) {
+    Split(eq, if_true, if_false, fall_through);
+  } else {
+    Heap::RootListIndex other_nil_value = nil == kNullValue ?
+        Heap::kUndefinedValueRootIndex :
+        Heap::kNullValueRootIndex;
+    __ beq(if_true);
+    __ LoadRoot(r4, other_nil_value);
+    __ cmp(r3, r4);
+    __ beq(if_true);
+    __ JumpIfSmi(r3, if_false);
+    // It can be an undetectable object.
+    __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ lbz(r4, FieldMemOperand(r4, Map::kBitFieldOffset));
+    __ andi(r4, r4, Operand(1 << Map::kIsUndetectable));
+    __ cmpi(r4, Operand(1 << Map::kIsUndetectable));
+    Split(eq, if_true, if_false, fall_through);
+  }
+  context()->Plug(if_true, if_false);
+}
+
+
+void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
+  __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  context()->Plug(r3);
+}
+
+
+Register FullCodeGenerator::result_register() {
+  return r3;
+}
+
+
+Register FullCodeGenerator::context_register() {
+  return cp;
+}
+
+
+void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
+  ASSERT_EQ(static_cast<int>(POINTER_SIZE_ALIGN(frame_offset)), frame_offset);
+  __ StoreP(value, MemOperand(fp, frame_offset), r0);
+}
+
+
+void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
+  __ LoadP(dst, ContextOperand(cp, context_index), r0);
+}
+
+
+void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
+  Scope* declaration_scope = scope()->DeclarationScope();
+  if (declaration_scope->is_global_scope() ||
+      declaration_scope->is_module_scope()) {
+    // Contexts nested in the native context have a canonical empty function
+    // as their closure, not the anonymous closure containing the global
+    // code.  Pass a smi sentinel and let the runtime look up the empty
+    // function.
+    __ LoadSmiLiteral(ip, Smi::FromInt(0));
+  } else if (declaration_scope->is_eval_scope()) {
+    // Contexts created by a call to eval have the same closure as the
+    // context calling eval, not the anonymous closure containing the eval
+    // code.  Fetch it from the context.
+    __ LoadP(ip, ContextOperand(cp, Context::CLOSURE_INDEX));
+  } else {
+    ASSERT(declaration_scope->is_function_scope());
+    __ LoadP(ip, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  }
+  __ push(ip);
+}
+
+
+// ----------------------------------------------------------------------------
+// Non-local control flow support.
+
+void FullCodeGenerator::EnterFinallyBlock() {
+  ASSERT(!result_register().is(r4));
+  // Store result register while executing finally block.
+  __ push(result_register());
+  // Cook return address in link register to stack (smi encoded Code* delta)
+  __ mflr(r4);
+  __ mov(ip, Operand(masm_->CodeObject()));
+  __ sub(r4, r4, ip);
+  __ SmiTag(r4);
+
+  // Store result register while executing finally block.
+  __ push(r4);
+
+  // Store pending message while executing finally block.
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ mov(ip, Operand(pending_message_obj));
+  __ LoadP(r4, MemOperand(ip));
+  __ push(r4);
+
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ mov(ip, Operand(has_pending_message));
+  __ lbz(r4, MemOperand(ip));
+  __ SmiTag(r4);
+  __ push(r4);
+
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ mov(ip, Operand(pending_message_script));
+  __ LoadP(r4, MemOperand(ip));
+  __ push(r4);
+}
+
+
+void FullCodeGenerator::ExitFinallyBlock() {
+  ASSERT(!result_register().is(r4));
+  // Restore pending message from stack.
+  __ pop(r4);
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ mov(ip, Operand(pending_message_script));
+  __ StoreP(r4, MemOperand(ip));
+
+  __ pop(r4);
+  __ SmiUntag(r4);
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ mov(ip, Operand(has_pending_message));
+  __ stb(r4, MemOperand(ip));
+
+  __ pop(r4);
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ mov(ip, Operand(pending_message_obj));
+  __ StoreP(r4, MemOperand(ip));
+
+  // Restore result register from stack.
+  __ pop(r4);
+
+  // Uncook return address and return.
+  __ pop(result_register());
+  __ SmiUntag(r4);
+  __ mov(ip, Operand(masm_->CodeObject()));
+  __ add(ip, ip, r4);
+  __ mtctr(ip);
+  __ bcr();
+}
+
+
+#undef __
+
+#define __ ACCESS_MASM(masm())
+
+FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
+    int* stack_depth,
+    int* context_length) {
+  // The macros used here must preserve the result register.
+
+  // Because the handler block contains the context of the finally
+  // code, we can restore it directly from there for the finally code
+  // rather than iteratively unwinding contexts via their previous
+  // links.
+  __ Drop(*stack_depth);  // Down to the handler block.
+  if (*context_length > 0) {
+    // Restore the context to its dedicated register and the stack.
+    __ LoadP(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
+    __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  }
+  __ PopTryHandler();
+  __ b(finally_entry_, SetLK);
+
+  *stack_depth = 0;
+  *context_length = 0;
+  return previous_;
+}
+
+#undef __
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/ic-ppc.cc b/src/ppc/ic-ppc.cc
new file mode 100644
index 0000000..a824e76
--- /dev/null
+++ b/src/ppc/ic-ppc.cc
@@ -0,0 +1,1832 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "assembler-ppc.h"
+#include "code-stubs.h"
+#include "codegen.h"
+#include "disasm.h"
+#include "ic-inl.h"
+#include "runtime.h"
+#include "stub-cache.h"
+
+namespace v8 {
+namespace internal {
+
+
+// ----------------------------------------------------------------------------
+// Static IC stub generators.
+//
+
+#define __ ACCESS_MASM(masm)
+
+static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm,
+                                            Register type,
+                                            Label* global_object) {
+  // Register usage:
+  //   type: holds the receiver instance type on entry.
+  __ cmpi(type, Operand(JS_GLOBAL_OBJECT_TYPE));
+  __ beq(global_object);
+  __ cmpi(type, Operand(JS_BUILTINS_OBJECT_TYPE));
+  __ beq(global_object);
+  __ cmpi(type, Operand(JS_GLOBAL_PROXY_TYPE));
+  __ beq(global_object);
+}
+
+
+// Generated code falls through if the receiver is a regular non-global
+// JS object with slow properties and no interceptors.
+static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
+                                                  Register receiver,
+                                                  Register elements,
+                                                  Register t0,
+                                                  Register t1,
+                                                  Label* miss) {
+  // Register usage:
+  //   receiver: holds the receiver on entry and is unchanged.
+  //   elements: holds the property dictionary on fall through.
+  // Scratch registers:
+  //   t0: used to holds the receiver map.
+  //   t1: used to holds the receiver instance type, receiver bit mask and
+  //       elements map.
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, miss);
+
+  // Check that the receiver is a valid JS object.
+  __ CompareObjectType(receiver, t0, t1, FIRST_SPEC_OBJECT_TYPE);
+  __ blt(miss);
+
+  // If this assert fails, we have to check upper bound too.
+  STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
+
+  GenerateGlobalInstanceTypeCheck(masm, t1, miss);
+
+  // Check that the global object does not require access checks.
+  __ lbz(t1, FieldMemOperand(t0, Map::kBitFieldOffset));
+  __ andi(r0, t1, Operand((1 << Map::kIsAccessCheckNeeded) |
+                     (1 << Map::kHasNamedInterceptor)));
+  __ bne(miss, cr0);
+
+  __ LoadP(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+  __ LoadP(t1, FieldMemOperand(elements, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(t1, ip);
+  __ bne(miss);
+}
+
+
+// Helper function used from LoadIC/CallIC GenerateNormal.
+//
+// elements: Property dictionary. It is not clobbered if a jump to the miss
+//           label is done.
+// name:     Property name. It is not clobbered if a jump to the miss label is
+//           done
+// result:   Register for the result. It is only updated if a jump to the miss
+//           label is not done. Can be the same as elements or name clobbering
+//           one of these in the case of not jumping to the miss label.
+// The two scratch registers need to be different from elements, name and
+// result.
+// The generated code assumes that the receiver has slow properties,
+// is not a global object and does not have interceptors.
+static void GenerateDictionaryLoad(MacroAssembler* masm,
+                                   Label* miss,
+                                   Register elements,
+                                   Register name,
+                                   Register result,
+                                   Register scratch1,
+                                   Register scratch2) {
+  // Main use of the scratch registers.
+  // scratch1: Used as temporary and to hold the capacity of the property
+  //           dictionary.
+  // scratch2: Used as temporary.
+  Label done;
+
+  // Probe the dictionary.
+  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                     miss,
+                                                     &done,
+                                                     elements,
+                                                     name,
+                                                     scratch1,
+                                                     scratch2);
+
+  // If probing finds an entry check that the value is a normal
+  // property.
+  __ bind(&done);  // scratch2 == elements + 4 * index
+  const int kElementsStartOffset = StringDictionary::kHeaderSize +
+      StringDictionary::kElementsStartIndex * kPointerSize;
+  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
+  __ LoadP(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
+  __ mr(r0, scratch2);
+  __ LoadSmiLiteral(scratch2, Smi::FromInt(PropertyDetails::TypeField::kMask));
+  __ and_(scratch2, scratch1, scratch2, SetRC);
+  __ bne(miss, cr0);
+  __ mr(scratch2, r0);
+
+  // Get the value at the masked, scaled index and return.
+  __ LoadP(result,
+         FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize));
+}
+
+
+// Helper function used from StoreIC::GenerateNormal.
+//
+// elements: Property dictionary. It is not clobbered if a jump to the miss
+//           label is done.
+// name:     Property name. It is not clobbered if a jump to the miss label is
+//           done
+// value:    The value to store.
+// The two scratch registers need to be different from elements, name and
+// result.
+// The generated code assumes that the receiver has slow properties,
+// is not a global object and does not have interceptors.
+static void GenerateDictionaryStore(MacroAssembler* masm,
+                                    Label* miss,
+                                    Register elements,
+                                    Register name,
+                                    Register value,
+                                    Register scratch1,
+                                    Register scratch2) {
+  // Main use of the scratch registers.
+  // scratch1: Used as temporary and to hold the capacity of the property
+  //           dictionary.
+  // scratch2: Used as temporary.
+  Label done;
+
+  // Probe the dictionary.
+  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                     miss,
+                                                     &done,
+                                                     elements,
+                                                     name,
+                                                     scratch1,
+                                                     scratch2);
+
+  // If probing finds an entry in the dictionary check that the value
+  // is a normal property that is not read only.
+  __ bind(&done);  // scratch2 == elements + 4 * index
+  const int kElementsStartOffset = StringDictionary::kHeaderSize +
+      StringDictionary::kElementsStartIndex * kPointerSize;
+  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
+  int kTypeAndReadOnlyMask = PropertyDetails::TypeField::kMask |
+    PropertyDetails::AttributesField::encode(READ_ONLY);
+  __ LoadP(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
+  __ mr(r0, scratch2);
+  __ LoadSmiLiteral(scratch2, Smi::FromInt(kTypeAndReadOnlyMask));
+  __ and_(scratch2, scratch1, scratch2, SetRC);
+  __ bne(miss, cr0);
+  __ mr(scratch2, r0);
+
+  // Store the value at the masked, scaled index and return.
+  const int kValueOffset = kElementsStartOffset + kPointerSize;
+  __ addi(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag));
+  __ StoreP(value, MemOperand(scratch2));
+
+  // Update the write barrier. Make sure not to clobber the value.
+  __ mr(scratch1, value);
+  __ RecordWrite(
+      elements, scratch2, scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs);
+}
+
+
+void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- r3    : receiver
+  //  -- sp[0] : receiver
+  // -----------------------------------
+  Label miss;
+
+  StubCompiler::GenerateLoadArrayLength(masm, r3, r6, &miss);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+void LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- r3    : receiver
+  //  -- sp[0] : receiver
+  // -----------------------------------
+  Label miss;
+
+  StubCompiler::GenerateLoadStringLength(masm, r3, r4, r6, &miss,
+                                         support_wrappers);
+  // Cache miss: Jump to runtime.
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- r3    : receiver
+  //  -- sp[0] : receiver
+  // -----------------------------------
+  Label miss;
+
+  StubCompiler::GenerateLoadFunctionPrototype(masm, r3, r4, r6, &miss);
+  __ bind(&miss);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+}
+
+
+// Checks the receiver for special cases (value type, slow case bits).
+// Falls through for regular JS object.
+static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register map,
+                                           Register scratch,
+                                           int interceptor_bit,
+                                           Label* slow) {
+  // Check that the object isn't a smi.
+  __ JumpIfSmi(receiver, slow);
+  // Get the map of the receiver.
+  __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  // Check bit field.
+  __ lbz(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
+  ASSERT(((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)) < 0x8000);
+  __ andi(r0, scratch,
+          Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)));
+  __ bne(slow, cr0);
+  // Check that the object is some kind of JS object EXCEPT JS Value type.
+  // In the case that the object is a value-wrapper object,
+  // we enter the runtime system to make sure that indexing into string
+  // objects work as intended.
+  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
+  __ lbz(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  __ cmpi(scratch, Operand(JS_OBJECT_TYPE));
+  __ blt(slow);
+}
+
+
+// Loads an indexed element from a fast case array.
+// If not_fast_array is NULL, doesn't perform the elements map check.
+static void GenerateFastArrayLoad(MacroAssembler* masm,
+                                  Register receiver,
+                                  Register key,
+                                  Register elements,
+                                  Register scratch1,
+                                  Register scratch2,
+                                  Register result,
+                                  Label* not_fast_array,
+                                  Label* out_of_range) {
+  // Register use:
+  //
+  // receiver - holds the receiver on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // key      - holds the smi key on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // elements - holds the elements of the receiver on exit.
+  //
+  // result   - holds the result on exit if the load succeeded.
+  //            Allowed to be the the same as 'receiver' or 'key'.
+  //            Unchanged on bailout so 'receiver' and 'key' can be safely
+  //            used by further computation.
+  //
+  // Scratch registers:
+  //
+  // scratch1 - used to hold elements map and elements length.
+  //            Holds the elements map if not_fast_array branch is taken.
+  //
+  // scratch2 - used to hold the loaded value.
+
+  __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  if (not_fast_array != NULL) {
+    // Check that the object is in fast mode and writable.
+    __ LoadP(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
+    __ cmp(scratch1, ip);
+    __ bne(not_fast_array);
+  } else {
+    __ AssertFastElements(elements);
+  }
+  // Check that the key (index) is within bounds.
+  __ LoadP(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
+  __ cmpl(key, scratch1);
+  __ bge(out_of_range);
+  // Fast case: Do the load.
+  __ addi(scratch1, elements,
+          Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  // The key is a smi.
+  __ SmiToPtrArrayOffset(scratch2, key);
+  __ LoadPX(scratch2, MemOperand(scratch2, scratch1));
+  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  __ cmp(scratch2, ip);
+  // In case the loaded value is the_hole we have to consult GetProperty
+  // to ensure the prototype chain is searched.
+  __ beq(out_of_range);
+  __ mr(result, scratch2);
+}
+
+
+// Checks whether a key is an array index string or a symbol string.
+// Falls through if a key is a symbol.
+static void GenerateKeyStringCheck(MacroAssembler* masm,
+                                   Register key,
+                                   Register map,
+                                   Register hash,
+                                   Label* index_string,
+                                   Label* not_symbol) {
+  // assumes that r8 is free for scratch use
+  // The key is not a smi.
+  // Is it a string?
+  __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE);
+  __ bge(not_symbol);
+
+  // Is the string an array index, with cached numeric value?
+  __ lwz(hash, FieldMemOperand(key, String::kHashFieldOffset));
+  __ mov(r8, Operand(String::kContainsCachedArrayIndexMask));
+  __ and_(r0, hash, r8, SetRC);
+  __ beq(index_string, cr0);
+
+  // Is the string a symbol?
+  // map: key map
+  __ lbz(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  STATIC_ASSERT(kSymbolTag != 0);
+  __ andi(r0, hash, Operand(kIsSymbolMask));
+  __ beq(not_symbol, cr0);
+}
+
+
+// Defined in ic.cc.
+Object* CallIC_Miss(Arguments args);
+
+// The generated code does not accept smi keys.
+// The generated code falls through if both probes miss.
+void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
+                                               int argc,
+                                               Code::Kind kind,
+                                               Code::ExtraICState extra_state) {
+  // ----------- S t a t e -------------
+  //  -- r4    : receiver
+  //  -- r5    : name
+  // -----------------------------------
+  Label number, non_number, non_string, boolean, probe, miss;
+
+  // Probe the stub cache.
+  Code::Flags flags = Code::ComputeFlags(kind,
+                                         MONOMORPHIC,
+                                         extra_state,
+                                         Code::NORMAL,
+                                         argc);
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r4, r5, r6, r7, r8, r9);
+
+  // If the stub cache probing failed, the receiver might be a value.
+  // For value objects, we use the map of the prototype objects for
+  // the corresponding JSValue for the cache and that is what we need
+  // to probe.
+  //
+  // Check for number.
+  __ JumpIfSmi(r4, &number);
+  __ CompareObjectType(r4, r6, r6, HEAP_NUMBER_TYPE);
+  __ bne(&non_number);
+  __ bind(&number);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::NUMBER_FUNCTION_INDEX, r4);
+  __ b(&probe);
+
+  // Check for string.
+  __ bind(&non_number);
+  __ cmpli(r6, Operand(FIRST_NONSTRING_TYPE));
+  __ bge(&non_string);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::STRING_FUNCTION_INDEX, r4);
+  __ b(&probe);
+
+  // Check for boolean.
+  __ bind(&non_string);
+  __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+  __ cmp(r4, ip);
+  __ beq(&boolean);
+  __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+  __ cmp(r4, ip);
+  __ bne(&miss);
+  __ bind(&boolean);
+  StubCompiler::GenerateLoadGlobalFunctionPrototype(
+      masm, Context::BOOLEAN_FUNCTION_INDEX, r4);
+
+  // Probe the stub cache for the value object.
+  __ bind(&probe);
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r4, r5, r6, r7, r8, r9);
+
+  __ bind(&miss);
+}
+
+
+static void GenerateFunctionTailCall(MacroAssembler* masm,
+                                     int argc,
+                                     Label* miss,
+                                     Register scratch) {
+  // r4: function
+
+  // Check that the value isn't a smi.
+  __ JumpIfSmi(r4, miss);
+
+  // Check that the value is a JSFunction.
+  __ CompareObjectType(r4, scratch, scratch, JS_FUNCTION_TYPE);
+  __ bne(miss);
+
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(r4, actual, JUMP_FUNCTION,
+                    NullCallWrapper(), CALL_AS_METHOD);
+}
+
+
+void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Get the receiver of the function from the stack into r4.
+  __ LoadP(r4, MemOperand(sp, argc * kPointerSize), r0);
+
+  GenerateStringDictionaryReceiverCheck(masm, r4, r3, r6, r7, &miss);
+
+  // r3: elements
+  // Search the dictionary - put result in register r4.
+  GenerateDictionaryLoad(masm, &miss, r3, r5, r4, r6, r7);
+
+  GenerateFunctionTailCall(masm, argc, &miss, r7);
+
+  __ bind(&miss);
+}
+
+
+void CallICBase::GenerateMiss(MacroAssembler* masm,
+                              int argc,
+                              IC::UtilityId id,
+                              Code::ExtraICState extra_state) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Isolate* isolate = masm->isolate();
+
+  if (id == IC::kCallIC_Miss) {
+    __ IncrementCounter(isolate->counters()->call_miss(), 1, r6, r7);
+  } else {
+    __ IncrementCounter(isolate->counters()->keyed_call_miss(), 1, r6, r7);
+  }
+
+  // Get the receiver of the function from the stack.
+  __ LoadP(r6, MemOperand(sp, argc * kPointerSize), r0);
+
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+    // Push the receiver and the name of the function.
+    __ Push(r6, r5);
+
+    // Call the entry.
+    __ li(r3, Operand(2));
+    __ mov(r4, Operand(ExternalReference(IC_Utility(id), isolate)));
+
+    CEntryStub stub(1);
+    __ CallStub(&stub);
+
+    // Move result to r4 and leave the internal frame.
+    __ mr(r4, r3);
+  }
+
+  // Check if the receiver is a global object of some sort.
+  // This can happen only for regular CallIC but not KeyedCallIC.
+  if (id == IC::kCallIC_Miss) {
+    Label invoke, global;
+    __ LoadP(r5, MemOperand(sp, argc * kPointerSize), r0);  // receiver
+    __ JumpIfSmi(r5, &invoke);
+    __ CompareObjectType(r5, r6, r6, JS_GLOBAL_OBJECT_TYPE);
+    __ beq(&global);
+    __ cmpi(r6, Operand(JS_BUILTINS_OBJECT_TYPE));
+    __ bne(&invoke);
+
+    // Patch the receiver on the stack.
+    __ bind(&global);
+    __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalReceiverOffset));
+    __ StoreP(r5, MemOperand(sp, argc * kPointerSize), r0);
+    __ bind(&invoke);
+  }
+
+  // Invoke the function.
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  ParameterCount actual(argc);
+  __ InvokeFunction(r4,
+                    actual,
+                    JUMP_FUNCTION,
+                    NullCallWrapper(),
+                    call_kind);
+}
+
+
+void CallIC::GenerateMegamorphic(MacroAssembler* masm,
+                                 int argc,
+                                 Code::ExtraICState extra_ic_state) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack into r4.
+  __ LoadP(r4, MemOperand(sp, argc * kPointerSize), r0);
+  GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state);
+  GenerateMiss(masm, argc, extra_ic_state);
+}
+
+
+void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack into r4.
+  __ LoadP(r4, MemOperand(sp, argc * kPointerSize), r0);
+
+  Label do_call, slow_call, slow_load, slow_reload_receiver;
+  Label check_number_dictionary, check_string, lookup_monomorphic_cache;
+  Label index_smi, index_string;
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(r5, &check_string);
+  __ bind(&index_smi);
+  // Now the key is known to be a smi. This place is also jumped to from below
+  // where a numeric string is converted to a smi.
+
+  GenerateKeyedLoadReceiverCheck(
+      masm, r4, r3, r6, Map::kHasIndexedInterceptor, &slow_call);
+
+  GenerateFastArrayLoad(
+      masm, r4, r5, r7, r6, r3, r4, &check_number_dictionary, &slow_load);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->keyed_call_generic_smi_fast(), 1, r3, r6);
+
+  __ bind(&do_call);
+  // receiver in r4 is not used after this point.
+  // r5: key
+  // r4: function
+  GenerateFunctionTailCall(masm, argc, &slow_call, r3);
+
+  __ bind(&check_number_dictionary);
+  // r5: key
+  // r6: elements map
+  // r7: elements
+  // Check whether the elements is a number dictionary.
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(r6, ip);
+  __ bne(&slow_load);
+  __ SmiUntag(r3, r5);
+  // r3: untagged index
+  __ LoadFromNumberDictionary(&slow_load, r7, r5, r4, r3, r6, r8);
+  __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1, r3, r6);
+  __ b(&do_call);
+
+  __ bind(&slow_load);
+  // This branch is taken when calling KeyedCallIC_Miss is neither required
+  // nor beneficial.
+  __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1, r3, r6);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(r5);  // save the key
+    __ Push(r4, r5);  // pass the receiver and the key
+    __ CallRuntime(Runtime::kKeyedGetProperty, 2);
+    __ pop(r5);  // restore the key
+  }
+  __ mr(r4, r3);
+  __ b(&do_call);
+
+  __ bind(&check_string);
+  GenerateKeyStringCheck(masm, r5, r3, r6, &index_string, &slow_call);
+
+  // The key is known to be a symbol.
+  // If the receiver is a regular JS object with slow properties then do
+  // a quick inline probe of the receiver's dictionary.
+  // Otherwise do the monomorphic cache probe.
+  GenerateKeyedLoadReceiverCheck(
+      masm, r4, r3, r6, Map::kHasNamedInterceptor, &lookup_monomorphic_cache);
+
+  __ LoadP(r3, FieldMemOperand(r4, JSObject::kPropertiesOffset));
+  __ LoadP(r6, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(r6, ip);
+  __ bne(&lookup_monomorphic_cache);
+
+  GenerateDictionaryLoad(masm, &slow_load, r3, r5, r4, r6, r7);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_dict(), 1, r3, r6);
+  __ b(&do_call);
+
+  __ bind(&lookup_monomorphic_cache);
+  __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, r3, r6);
+  GenerateMonomorphicCacheProbe(masm,
+                                argc,
+                                Code::KEYED_CALL_IC,
+                                Code::kNoExtraICState);
+  // Fall through on miss.
+
+  __ bind(&slow_call);
+  // This branch is taken if:
+  // - the receiver requires boxing or access check,
+  // - the key is neither smi nor symbol,
+  // - the value loaded is not a function,
+  // - there is hope that the runtime will create a monomorphic call stub
+  //   that will get fetched next time.
+  __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r3, r6);
+  GenerateMiss(masm, argc);
+
+  __ bind(&index_string);
+  __ IndexFromHash(r6, r5);
+  // Now jump to the place where smi keys are handled.
+  __ b(&index_smi);
+}
+
+
+void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  // Check if the name is a string.
+  Label miss;
+  __ JumpIfSmi(r5, &miss);
+  __ IsObjectJSStringType(r5, r3, &miss);
+
+  CallICBase::GenerateNormal(masm, argc);
+  __ bind(&miss);
+  GenerateMiss(masm, argc);
+}
+
+
+// Defined in ic.cc.
+Object* LoadIC_Miss(Arguments args);
+
+void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- r3    : receiver
+  //  -- sp[0] : receiver
+  // -----------------------------------
+
+  // Probe the stub cache.
+  Code::Flags flags =
+      Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r3, r5, r6, r7, r8, r9);
+
+  // Cache miss: Jump to runtime.
+  GenerateMiss(masm);
+}
+
+
+void LoadIC::GenerateNormal(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- r3    : receiver
+  //  -- sp[0] : receiver
+  // -----------------------------------
+  Label miss;
+
+  GenerateStringDictionaryReceiverCheck(masm, r3, r4, r6, r7, &miss);
+
+  // r4: elements
+  GenerateDictionaryLoad(masm, &miss, r4, r5, r3, r6, r7);
+  __ Ret();
+
+  // Cache miss: Jump to runtime.
+  __ bind(&miss);
+  GenerateMiss(masm);
+}
+
+
+void LoadIC::GenerateMiss(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- r3    : receiver
+  //  -- sp[0] : receiver
+  // -----------------------------------
+  Isolate* isolate = masm->isolate();
+
+  __ IncrementCounter(isolate->counters()->load_miss(), 1, r6, r7);
+
+  __ Push(r3, r5);
+
+  // Perform tail call to the entry.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm,
+                                                Register object,
+                                                Register key,
+                                                Register scratch1,
+                                                Register scratch2,
+                                                Register scratch3,
+                                                Label* unmapped_case,
+                                                Label* slow_case) {
+  Heap* heap = masm->isolate()->heap();
+
+  // Check that the receiver is a JSObject. Because of the map check
+  // later, we do not need to check for interceptors or whether it
+  // requires access checks.
+  __ JumpIfSmi(object, slow_case);
+  // Check that the object is some kind of JSObject.
+  __ CompareObjectType(object, scratch1, scratch2, FIRST_JS_RECEIVER_TYPE);
+  __ blt(slow_case);
+
+  // Check that the key is a positive smi.
+  __ mov(scratch1, Operand(0x80000001));
+  __ and_(r0, key, scratch1, SetRC);
+  __ bne(slow_case, cr0);
+
+  // Load the elements into scratch1 and check its map.
+  Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
+  __ LoadP(scratch1, FieldMemOperand(object, JSObject::kElementsOffset));
+  __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK);
+
+  // Check if element is in the range of mapped arguments. If not, jump
+  // to the unmapped lookup with the parameter map in scratch1.
+  __ LoadP(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset));
+  __ SubSmiLiteral(scratch2, scratch2, Smi::FromInt(2), r0);
+  __ cmpl(key, scratch2);
+  __ bge(unmapped_case);
+
+  // Load element index and check whether it is the hole.
+  const int kOffset =
+      FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag;
+
+  __ SmiToPtrArrayOffset(scratch3, key);
+  __ addi(scratch3, scratch3, Operand(kOffset));
+
+  __ LoadPX(scratch2, MemOperand(scratch1, scratch3));
+  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
+  __ cmp(scratch2, scratch3);
+  __ beq(unmapped_case);
+
+  // Load value from context and return it. We can reuse scratch1 because
+  // we do not jump to the unmapped lookup (which requires the parameter
+  // map in scratch1).
+  __ LoadP(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
+  __ SmiToPtrArrayOffset(scratch3, scratch2);
+  __ addi(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag));
+  __ add(scratch1, scratch1, scratch3);
+  return MemOperand(scratch1);
+}
+
+
+static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
+                                                  Register key,
+                                                  Register parameter_map,
+                                                  Register scratch,
+                                                  Label* slow_case) {
+  // Element is in arguments backing store, which is referenced by the
+  // second element of the parameter_map. The parameter_map register
+  // must be loaded with the parameter map of the arguments object and is
+  // overwritten.
+  const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
+  Register backing_store = parameter_map;
+  __ LoadP(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset));
+  Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
+  __ CheckMap(backing_store, scratch, fixed_array_map, slow_case,
+              DONT_DO_SMI_CHECK);
+  __ LoadP(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset));
+  __ cmpl(key, scratch);
+  __ bge(slow_case);
+  __ SmiToPtrArrayOffset(scratch, key);
+  __ addi(scratch,
+          scratch,
+          Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ add(backing_store, backing_store, scratch);
+  return MemOperand(backing_store);
+}
+
+
+void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Label slow, notin;
+  MemOperand mapped_location =
+      GenerateMappedArgumentsLookup(masm, r4, r3, r5, r6, r7, &notin, &slow);
+  __ LoadP(r3, mapped_location);
+  __ Ret();
+  __ bind(&notin);
+  // The unmapped lookup expects that the parameter map is in r5.
+  MemOperand unmapped_location =
+      GenerateUnmappedArgumentsLookup(masm, r3, r5, r6, &slow);
+  __ LoadP(r5, unmapped_location);
+  __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
+  __ cmp(r5, r6);
+  __ beq(&slow);
+  __ mr(r3, r5);
+  __ Ret();
+  __ bind(&slow);
+  GenerateMiss(masm, false);
+}
+
+
+void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r3     : value
+  //  -- r4     : key
+  //  -- r5     : receiver
+  //  -- lr     : return address
+  // -----------------------------------
+  Label slow, notin;
+  MemOperand mapped_location =
+      GenerateMappedArgumentsLookup(masm, r5, r4, r6, r7, r8, &notin, &slow);
+  __ StoreP(r3, mapped_location);
+  __ mr(r9, r6);  // r6 is modified by GenerateMappedArgumentsLookup
+  __ mr(r22, r3);
+  __ RecordWrite(r6, r9, r22, kLRHasNotBeenSaved, kDontSaveFPRegs);
+  __ Ret();
+  __ bind(&notin);
+  // The unmapped lookup expects that the parameter map is in r6.
+  MemOperand unmapped_location =
+      GenerateUnmappedArgumentsLookup(masm, r4, r6, r7, &slow);
+  __ StoreP(r3, unmapped_location);
+  __ mr(r9, r6);  // r6 is modified by GenerateUnmappedArgumentsLookup
+  __ mr(r22, r3);
+  __ RecordWrite(r6, r9, r22, kLRHasNotBeenSaved, kDontSaveFPRegs);
+  __ Ret();
+  __ bind(&slow);
+  GenerateMiss(masm, false);
+}
+
+
+void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
+                                             int argc) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label slow, notin;
+  // Load receiver.
+  __ LoadP(r4, MemOperand(sp, argc * kPointerSize), r0);
+  MemOperand mapped_location =
+      GenerateMappedArgumentsLookup(masm, r4, r5, r6, r7, r8, &notin, &slow);
+  __ LoadP(r4, mapped_location);
+  GenerateFunctionTailCall(masm, argc, &slow, r6);
+  __ bind(&notin);
+  // The unmapped lookup expects that the parameter map is in r6.
+  MemOperand unmapped_location =
+      GenerateUnmappedArgumentsLookup(masm, r5, r6, r7, &slow);
+  __ LoadP(r4, unmapped_location);
+  __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
+  __ cmp(r4, r6);
+  __ beq(&slow);
+  GenerateFunctionTailCall(masm, argc, &slow, r3);
+  __ bind(&slow);
+  GenerateMiss(masm, argc);
+}
+
+
+Object* KeyedLoadIC_Miss(Arguments args);
+
+
+void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Isolate* isolate = masm->isolate();
+
+  __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r6, r7);
+
+  __ Push(r4, r3);
+
+  // Perform tail call to the entry.
+  ExternalReference ref = force_generic
+      ? ExternalReference(IC_Utility(kKeyedLoadIC_MissForceGeneric), isolate)
+      : ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
+
+  __ TailCallExternalReference(ref, 2, 1);
+}
+
+
+void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+
+  __ Push(r4, r3);
+
+  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+}
+
+
+void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Label slow, check_string, index_smi, index_string, property_array_property;
+  Label probe_dictionary, check_number_dictionary;
+
+  Register key = r3;
+  Register receiver = r4;
+
+  Isolate* isolate = masm->isolate();
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(key, &check_string);
+  __ bind(&index_smi);
+  // Now the key is known to be a smi. This place is also jumped to from below
+  // where a numeric string is converted to a smi.
+
+  GenerateKeyedLoadReceiverCheck(
+      masm, receiver, r5, r6, Map::kHasIndexedInterceptor, &slow);
+
+  // Check the receiver's map to see if it has fast elements.
+  __ CheckFastElements(r5, r6, &check_number_dictionary);
+
+  GenerateFastArrayLoad(
+      masm, receiver, key, r7, r6, r5, r3, NULL, &slow);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r5, r6);
+  __ Ret();
+
+  __ bind(&check_number_dictionary);
+  __ LoadP(r7, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ LoadP(r6, FieldMemOperand(r7, JSObject::kMapOffset));
+
+  // Check whether the elements is a number dictionary.
+  // r3: key
+  // r6: elements map
+  // r7: elements
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(r6, ip);
+  __ bne(&slow);
+  __ SmiUntag(r5, r3);
+  __ LoadFromNumberDictionary(&slow, r7, r3, r3, r5, r6, r8);
+  __ Ret();
+
+  // Slow case, key and receiver still in r3 and r4.
+  __ bind(&slow);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
+                      1, r5, r6);
+  GenerateRuntimeGetProperty(masm);
+
+  __ bind(&check_string);
+  GenerateKeyStringCheck(masm, key, r5, r6, &index_string, &slow);
+
+  GenerateKeyedLoadReceiverCheck(
+      masm, receiver, r5, r6, Map::kHasNamedInterceptor, &slow);
+
+  // If the receiver is a fast-case object, check the keyed lookup
+  // cache. Otherwise probe the dictionary.
+  __ LoadP(r6, FieldMemOperand(r4, JSObject::kPropertiesOffset));
+  __ LoadP(r7, FieldMemOperand(r6, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(r7, ip);
+  __ beq(&probe_dictionary);
+
+  // Load the map of the receiver, compute the keyed lookup cache hash
+  // based on 32 bits of the map pointer and the string hash.
+  __ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+  __ srawi(r6, r5, KeyedLookupCache::kMapHashShift);
+  __ lwz(r7, FieldMemOperand(r3, String::kHashFieldOffset));
+  __ srawi(r7, r7, String::kHashShift);
+  __ xor_(r6, r6, r7);
+  int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
+  __ mov(r7, Operand(mask));
+  __ and_(r6, r6, r7, LeaveRC);
+
+  // Load the key (consisting of map and symbol) from the cache and
+  // check for match.
+  Label load_in_object_property;
+  static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
+  Label hit_on_nth_entry[kEntriesPerBucket];
+  ExternalReference cache_keys =
+      ExternalReference::keyed_lookup_cache_keys(isolate);
+
+  __ mov(r7, Operand(cache_keys));
+  __ mr(r0, r5);
+  __ ShiftLeftImm(r5, r6, Operand(kPointerSizeLog2 + 1));
+  __ add(r7, r7, r5);
+  __ mr(r5, r0);
+
+  for (int i = 0; i < kEntriesPerBucket - 1; i++) {
+    Label try_next_entry;
+    // Load map and move r7 to next entry.
+    __ LoadP(r8, MemOperand(r7));
+    __ addi(r7, r7, Operand(kPointerSize * 2));
+    __ cmp(r5, r8);
+    __ bne(&try_next_entry);
+    __ LoadP(r8, MemOperand(r7, -kPointerSize));  // Load symbol
+    __ cmp(r3, r8);
+    __ beq(&hit_on_nth_entry[i]);
+    __ bind(&try_next_entry);
+  }
+
+  // Last entry: Load map and move r7 to symbol.
+  __ LoadP(r8, MemOperand(r7));
+  __ addi(r7, r7, Operand(kPointerSize));
+  __ cmp(r5, r8);
+  __ bne(&slow);
+  __ LoadP(r8, MemOperand(r7));
+  __ cmp(r3, r8);
+  __ bne(&slow);
+
+  // Get field offset.
+  // r3     : key
+  // r4     : receiver
+  // r5     : receiver's map
+  // r6     : lookup cache index
+  ExternalReference cache_field_offsets =
+      ExternalReference::keyed_lookup_cache_field_offsets(isolate);
+
+  // Hit on nth entry.
+  for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
+    __ bind(&hit_on_nth_entry[i]);
+    __ mov(r7, Operand(cache_field_offsets));
+    if (i != 0) {
+      __ addi(r6, r6, Operand(i));
+    }
+    __ ShiftLeftImm(r8, r6, Operand(2));
+    __ lwzx(r8, MemOperand(r8, r7));
+    __ lbz(r9, FieldMemOperand(r5, Map::kInObjectPropertiesOffset));
+    __ sub(r8, r8, r9);
+    __ cmpi(r8, Operand::Zero());
+    __ bge(&property_array_property);
+    if (i != 0) {
+      __ b(&load_in_object_property);
+    }
+  }
+
+  // Load in-object property.
+  __ bind(&load_in_object_property);
+  __ lbz(r9, FieldMemOperand(r5, Map::kInstanceSizeOffset));
+  __ add(r9, r9, r8);  // Index from start of object.
+  __ subi(r4, r4, Operand(kHeapObjectTag));  // Remove the heap tag.
+  __ ShiftLeftImm(r3, r9, Operand(kPointerSizeLog2));
+  __ LoadPX(r3, MemOperand(r3, r4));
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
+                      1, r5, r6);
+  __ Ret();
+
+  // Load property array property.
+  __ bind(&property_array_property);
+  __ LoadP(r4, FieldMemOperand(r4, JSObject::kPropertiesOffset));
+  __ addi(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ ShiftLeftImm(r3, r8, Operand(kPointerSizeLog2));
+  __ LoadPX(r3, MemOperand(r3, r4));
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
+                      1, r5, r6);
+  __ Ret();
+
+  // Do a quick inline probe of the receiver's dictionary, if it
+  // exists.
+  __ bind(&probe_dictionary);
+  // r4: receiver
+  // r3: key
+  // r6: elements
+  __ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+  __ lbz(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
+  GenerateGlobalInstanceTypeCheck(masm, r5, &slow);
+  // Load the property to r3.
+  GenerateDictionaryLoad(masm, &slow, r6, r3, r3, r5, r7);
+  __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(),
+                      1, r5, r6);
+  __ Ret();
+
+  __ bind(&index_string);
+  __ IndexFromHash(r6, key);
+  // Now jump to the place where smi keys are handled.
+  __ b(&index_smi);
+}
+
+
+void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key (index)
+  //  -- r4     : receiver
+  // -----------------------------------
+  Label miss;
+
+  Register receiver = r4;
+  Register index = r3;
+  Register scratch = r6;
+  Register result = r3;
+
+  StringCharAtGenerator char_at_generator(receiver,
+                                          index,
+                                          scratch,
+                                          result,
+                                          &miss,  // When not a string.
+                                          &miss,  // When not a number.
+                                          &miss,  // When index out of range.
+                                          STRING_INDEX_IS_ARRAY_INDEX);
+  char_at_generator.GenerateFast(masm);
+  __ Ret();
+
+  StubRuntimeCallHelper call_helper;
+  char_at_generator.GenerateSlow(masm, call_helper);
+
+  __ bind(&miss);
+  GenerateMiss(masm, false);
+}
+
+
+void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Label slow;
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(r4, &slow);
+
+  // Check that the key is an array index, that is Uint32.
+  __ TestIfPositiveSmi(r3, r0);
+  __ bne(&slow, cr0);
+
+  // Get the map of the receiver.
+  __ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+
+  // Check that it has indexed interceptor and access checks
+  // are not enabled for this object.
+  __ lbz(r6, FieldMemOperand(r5, Map::kBitFieldOffset));
+  __ andi(r6, r6, Operand(kSlowCaseBitFieldMask));
+  __ cmpi(r6, Operand(1 << Map::kHasIndexedInterceptor));
+  __ bne(&slow);
+
+  // Everything is fine, call runtime.
+  __ Push(r4, r3);  // Receiver, key.
+
+  // Perform tail call to the entry.
+  __ TailCallExternalReference(
+      ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
+                        masm->isolate()),
+      2,
+      1);
+
+  __ bind(&slow);
+  GenerateMiss(masm, false);
+}
+
+
+void KeyedStoreIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
+  // ---------- S t a t e --------------
+  //  -- r3     : value
+  //  -- r4     : key
+  //  -- r5     : receiver
+  //  -- lr     : return address
+  // -----------------------------------
+
+  // Push receiver, key and value for runtime call.
+  __ Push(r5, r4, r3);
+
+  ExternalReference ref = force_generic
+      ? ExternalReference(IC_Utility(kKeyedStoreIC_MissForceGeneric),
+                          masm->isolate())
+      : ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
+  __ TailCallExternalReference(ref, 3, 1);
+}
+
+
+void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r3     : value
+  //  -- r4     : key
+  //  -- r5     : receiver
+  //  -- lr     : return address
+  // -----------------------------------
+
+  // Push receiver, key and value for runtime call.
+  __ Push(r5, r4, r3);
+
+  // The slow case calls into the runtime to complete the store without causing
+  // an IC miss that would otherwise cause a transition to the generic stub.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
+  __ TailCallExternalReference(ref, 3, 1);
+}
+
+
+void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r5     : receiver
+  //  -- r6     : target map
+  //  -- lr     : return address
+  // -----------------------------------
+  // Must return the modified receiver in r0.
+  if (!FLAG_trace_elements_transitions) {
+    Label fail;
+    ElementsTransitionGenerator::GenerateSmiToDouble(masm, &fail);
+    __ mr(r3, r5);
+    __ Ret();
+    __ bind(&fail);
+  }
+
+  __ push(r5);
+  __ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
+}
+
+
+void KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
+    MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r5     : receiver
+  //  -- r6     : target map
+  //  -- lr     : return address
+  // -----------------------------------
+  // Must return the modified receiver in r3.
+  if (!FLAG_trace_elements_transitions) {
+    Label fail;
+    ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
+    __ mr(r3, r5);
+    __ Ret();
+    __ bind(&fail);
+  }
+
+  __ push(r5);
+  __ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
+}
+
+
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
+  // ---------- S t a t e --------------
+  //  -- r3     : value
+  //  -- r4     : key
+  //  -- r5     : receiver
+  //  -- lr     : return address
+  // -----------------------------------
+
+  // Push receiver, key and value for runtime call.
+  __ Push(r5, r4, r3);
+
+  __ LoadSmiLiteral(r4, Smi::FromInt(NONE));          // PropertyAttributes
+  __ LoadSmiLiteral(r3, Smi::FromInt(strict_mode));   // Strict mode.
+  __ Push(r4, r3);
+
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
+}
+
+
+static void KeyedStoreGenerateGenericHelper(
+    MacroAssembler* masm,
+    Label* fast_object,
+    Label* fast_double,
+    Label* slow,
+    KeyedStoreCheckMap check_map,
+    KeyedStoreIncrementLength increment_length,
+    Register value,
+    Register key,
+    Register receiver,
+    Register receiver_map,
+    Register elements_map,
+    Register elements) {
+  Label transition_smi_elements;
+  Label finish_object_store, non_double_value, transition_double_elements;
+  Label fast_double_without_map_check;
+
+  // Fast case: Do the store, could be either Object or double.
+  __ bind(fast_object);
+  Register scratch_value = r7;
+  Register address = r8;
+  if (check_map == kCheckMap) {
+    __ LoadP(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
+    __ mov(scratch_value,
+            Operand(masm->isolate()->factory()->fixed_array_map()));
+    __ cmp(elements_map, scratch_value);
+    __ bne(fast_double);
+  }
+  // Smi stores don't require further checks.
+  Label non_smi_value;
+  __ JumpIfNotSmi(value, &non_smi_value);
+
+  if (increment_length == kIncrementLength) {
+    // Add 1 to receiver->length.
+    __ AddSmiLiteral(scratch_value, key, Smi::FromInt(1), r0);
+    __ StoreP(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset),
+              r0);
+  }
+  // It's irrelevant whether array is smi-only or not when writing a smi.
+  __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ SmiToPtrArrayOffset(scratch_value, key);
+  __ StorePX(value, MemOperand(address, scratch_value));
+  __ Ret();
+
+  __ bind(&non_smi_value);
+  // Escape to elements kind transition case.
+  __ CheckFastObjectElements(receiver_map, scratch_value,
+                             &transition_smi_elements);
+
+  // Fast elements array, store the value to the elements backing store.
+  __ bind(&finish_object_store);
+  if (increment_length == kIncrementLength) {
+    // Add 1 to receiver->length.
+    __ AddSmiLiteral(scratch_value, key, Smi::FromInt(1), r0);
+    __ StoreP(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset),
+              r0);
+  }
+  __ addi(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ SmiToPtrArrayOffset(scratch_value, key);
+  __ StorePUX(value, MemOperand(address, scratch_value));
+  // Update write barrier for the elements array address.
+  __ mr(scratch_value, value);  // Preserve the value which is returned.
+  __ RecordWrite(elements,
+                 address,
+                 scratch_value,
+                 kLRHasNotBeenSaved,
+                 kDontSaveFPRegs,
+                 EMIT_REMEMBERED_SET,
+                 OMIT_SMI_CHECK);
+  __ Ret();
+
+  __ bind(fast_double);
+  if (check_map == kCheckMap) {
+    // Check for fast double array case. If this fails, call through to the
+    // runtime.
+    __ CompareRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex);
+    __ bne(slow);
+  }
+  __ bind(&fast_double_without_map_check);
+  __ StoreNumberToDoubleElements(value,
+                                 key,
+                                 receiver,
+                                 elements,  // Overwritten.
+                                 r6,        // Scratch regs...
+                                 r7,
+                                 r8,
+                                 r9,
+                                 &transition_double_elements);
+  if (increment_length == kIncrementLength) {
+    // Add 1 to receiver->length.
+    __ AddSmiLiteral(scratch_value, key, Smi::FromInt(1), r0);
+    __ StoreP(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset),
+              r0);
+  }
+  __ Ret();
+
+  __ bind(&transition_smi_elements);
+  // Transition the array appropriately depending on the value type.
+  __ LoadP(r7, FieldMemOperand(value, HeapObject::kMapOffset));
+  __ CompareRoot(r7, Heap::kHeapNumberMapRootIndex);
+  __ bne(&non_double_value);
+
+  // Value is a double. Transition FAST_SMI_ELEMENTS ->
+  // FAST_DOUBLE_ELEMENTS and complete the store.
+  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
+                                         FAST_DOUBLE_ELEMENTS,
+                                         receiver_map,
+                                         r7,
+                                         slow);
+  ASSERT(receiver_map.is(r6));  // Transition code expects map in r6
+  ElementsTransitionGenerator::GenerateSmiToDouble(masm, slow);
+  __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ b(&fast_double_without_map_check);
+
+  __ bind(&non_double_value);
+  // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
+  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
+                                         FAST_ELEMENTS,
+                                         receiver_map,
+                                         r7,
+                                         slow);
+  ASSERT(receiver_map.is(r6));  // Transition code expects map in r6
+  ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm);
+  __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ b(&finish_object_store);
+
+  __ bind(&transition_double_elements);
+  // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
+  // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
+  // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
+  __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
+                                         FAST_ELEMENTS,
+                                         receiver_map,
+                                         r7,
+                                         slow);
+  ASSERT(receiver_map.is(r6));  // Transition code expects map in r6
+  ElementsTransitionGenerator::GenerateDoubleToObject(masm, slow);
+  __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ b(&finish_object_store);
+}
+
+
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
+  // ---------- S t a t e --------------
+  //  -- r3     : value
+  //  -- r4     : key
+  //  -- r5     : receiver
+  //  -- lr     : return address
+  // -----------------------------------
+  Label slow, fast_object, fast_object_grow;
+  Label fast_double, fast_double_grow;
+  Label array, extra, check_if_double_array;
+
+  // Register usage.
+  Register value = r3;
+  Register key = r4;
+  Register receiver = r5;
+  Register receiver_map = r6;
+  Register elements_map = r9;
+  Register elements = r10;  // Elements array of the receiver.
+  // r7 and r8 are used as general scratch registers.
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(key, &slow);
+  // Check that the object isn't a smi.
+  __ JumpIfSmi(receiver, &slow);
+  // Get the map of the object.
+  __ LoadP(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  // Check that the receiver does not require access checks.  We need
+  // to do this because this generic stub does not perform map checks.
+  __ lbz(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
+  __ andi(r0, ip, Operand(1 << Map::kIsAccessCheckNeeded));
+  __ bne(&slow, cr0);
+  // Check if the object is a JS array or not.
+  __ lbz(r7, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
+  __ cmpi(r7, Operand(JS_ARRAY_TYPE));
+  __ beq(&array);
+  // Check that the object is some kind of JSObject.
+  __ cmpi(r7, Operand(FIRST_JS_OBJECT_TYPE));
+  __ blt(&slow);
+
+  // Object case: Check key against length in the elements array.
+  __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  // Check array bounds. Both the key and the length of FixedArray are smis.
+  __ LoadP(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
+  __ cmpl(key, ip);
+  __ blt(&fast_object);
+
+  // Slow case, handle jump to runtime.
+  __ bind(&slow);
+  // Entry registers are intact.
+  // r3: value.
+  // r4: key.
+  // r5: receiver.
+  GenerateRuntimeSetProperty(masm, strict_mode);
+
+  // Extra capacity case: Check if there is extra capacity to
+  // perform the store and update the length. Used for adding one
+  // element to the array by writing to array[array.length].
+  __ bind(&extra);
+  // Condition code from comparing key and array length is still available.
+  __ bne(&slow);  // Only support writing to writing to array[array.length].
+  // Check for room in the elements backing store.
+  // Both the key and the length of FixedArray are smis.
+  __ LoadP(ip, FieldMemOperand(elements, FixedArray::kLengthOffset));
+  __ cmpl(key, ip);
+  __ bge(&slow);
+  __ LoadP(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
+  __ mov(ip, Operand(masm->isolate()->factory()->fixed_array_map()));
+  __ cmp(elements_map, ip);  // PPC - I think I can re-use ip here
+  __ bne(&check_if_double_array);
+  __ b(&fast_object_grow);
+
+  __ bind(&check_if_double_array);
+  __ mov(ip, Operand(masm->isolate()->factory()->fixed_double_array_map()));
+  __ cmp(elements_map, ip);  // PPC - another ip re-use
+  __ bne(&slow);
+  __ b(&fast_double_grow);
+
+  // Array case: Get the length and the elements array from the JS
+  // array. Check that the array is in fast mode (and writable); if it
+  // is the length is always a smi.
+  __ bind(&array);
+  __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+
+  // Check the key against the length in the array.
+  __ LoadP(ip, FieldMemOperand(receiver, JSArray::kLengthOffset));
+  __ cmpl(key, ip);
+  __ bge(&extra);
+
+  KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double,
+                                  &slow, kCheckMap, kDontIncrementLength,
+                                  value, key, receiver, receiver_map,
+                                  elements_map, elements);
+  KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
+                                  &slow, kDontCheckMap, kIncrementLength,
+                                  value, key, receiver, receiver_map,
+                                  elements_map, elements);
+}
+
+
+void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  // Get the receiver from the stack and probe the stub cache.
+  Code::Flags flags =
+      Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
+
+  Isolate::Current()->stub_cache()->GenerateProbe(
+      masm, flags, r4, r5, r6, r7, r8, r9);
+
+  // Cache miss: Jump to runtime.
+  GenerateMiss(masm);
+}
+
+
+void StoreIC::GenerateMiss(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  __ Push(r4, r5, r3);
+
+  // Perform tail call to the entry.
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
+  __ TailCallExternalReference(ref, 3, 1);
+}
+
+
+void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  //
+  // This accepts as a receiver anything JSArray::SetElementsLength accepts
+  // (currently anything except for external arrays which means anything with
+  // elements of FixedArray type).  Value must be a number, but only smis are
+  // accepted as the most common case.
+
+  Label miss;
+
+  Register receiver = r4;
+  Register value = r3;
+  Register scratch = r6;
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, &miss);
+
+  // Check that the object is a JS array.
+  __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
+  __ bne(&miss);
+
+  // Check that elements are FixedArray.
+  // We rely on StoreIC_ArrayLength below to deal with all types of
+  // fast elements (including COW).
+  __ LoadP(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset));
+  __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE);
+  __ bne(&miss);
+
+  // Check that the array has fast properties, otherwise the length
+  // property might have been redefined.
+  __ LoadP(scratch, FieldMemOperand(receiver, JSArray::kPropertiesOffset));
+  __ LoadP(scratch, FieldMemOperand(scratch, FixedArray::kMapOffset));
+  __ CompareRoot(scratch, Heap::kHashTableMapRootIndex);
+  __ beq(&miss);
+
+  // Check that value is a smi.
+  __ JumpIfNotSmi(value, &miss);
+
+  // Prepare tail call to StoreIC_ArrayLength.
+  __ Push(receiver, value);
+
+  ExternalReference ref =
+      ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
+  __ TailCallExternalReference(ref, 2, 1);
+
+  __ bind(&miss);
+
+  GenerateMiss(masm);
+}
+
+
+void StoreIC::GenerateNormal(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  GenerateStringDictionaryReceiverCheck(masm, r4, r6, r7, r8, &miss);
+
+  GenerateDictionaryStore(masm, &miss, r6, r5, r3, r7, r8);
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->store_normal_hit(), 1, r7, r8);
+  __ Ret();
+
+  __ bind(&miss);
+  __ IncrementCounter(counters->store_normal_miss(), 1, r7, r8);
+  GenerateMiss(masm);
+}
+
+
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  __ Push(r4, r5, r3);
+
+  __ LoadSmiLiteral(r4, Smi::FromInt(NONE));  // PropertyAttributes
+  __ LoadSmiLiteral(r3, Smi::FromInt(strict_mode));
+  __ Push(r4, r3);
+
+  // Do tail-call to runtime routine.
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
+}
+
+
+#undef __
+
+
+Condition CompareIC::ComputeCondition(Token::Value op) {
+  switch (op) {
+    case Token::EQ_STRICT:
+    case Token::EQ:
+      return eq;
+    case Token::LT:
+      return lt;
+    case Token::GT:
+      return gt;
+    case Token::LTE:
+      return le;
+    case Token::GTE:
+      return ge;
+    default:
+      UNREACHABLE();
+      return kNoCondition;
+  }
+}
+
+
+void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
+  HandleScope scope;
+  Handle<Code> rewritten;
+  State previous_state = GetState();
+  State state = TargetState(previous_state, false, x, y);
+  if (state == GENERIC) {
+    CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r4, r3);
+    rewritten = stub.GetCode();
+  } else {
+    ICCompareStub stub(op_, state);
+    if (state == KNOWN_OBJECTS) {
+      stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
+    }
+    rewritten = stub.GetCode();
+  }
+  set_target(*rewritten);
+
+#ifdef DEBUG
+  if (FLAG_trace_ic) {
+    PrintF("[CompareIC (%s->%s)#%s]\n",
+           GetStateName(previous_state),
+           GetStateName(state),
+           Token::Name(op_));
+  }
+#endif
+
+  // Activate inlined smi code.
+  if (previous_state == UNINITIALIZED) {
+    PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
+  }
+}
+
+//
+// This code is paired with the JumpPatchSite class in full-codegen-ppc.cc
+//
+void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) {
+  Address cmp_instruction_address =
+      address + Assembler::kCallTargetAddressOffset;
+
+  // If the instruction following the call is not a cmp rx, #yyy, nothing
+  // was inlined.
+  Instr instr = Assembler::instr_at(cmp_instruction_address);
+  if (!Assembler::IsCmpImmediate(instr)) {
+    return;
+  }
+
+  // The delta to the start of the map check instruction and the
+  // condition code uses at the patched jump.
+  int delta = Assembler::GetCmpImmediateRawImmediate(instr);
+  delta +=
+      Assembler::GetCmpImmediateRegister(instr).code() * kOff16Mask;
+  // If the delta is 0 the instruction is cmp r0, #0 which also signals that
+  // nothing was inlined.
+  if (delta == 0) {
+    return;
+  }
+
+#ifdef DEBUG
+  if (FLAG_trace_ic) {
+    PrintF("[  patching ic at %p, cmp=%p, delta=%d\n",
+           address, cmp_instruction_address, delta);
+  }
+#endif
+
+  Address patch_address =
+      cmp_instruction_address - delta * Instruction::kInstrSize;
+  Instr instr_at_patch = Assembler::instr_at(patch_address);
+  Instr branch_instr =
+      Assembler::instr_at(patch_address + Instruction::kInstrSize);
+  // This is patching a conditional "jump if not smi/jump if smi" site.
+  // Enabling by changing from
+  //   cmp cr0, rx, rx
+  // to
+  //  rlwinm(r0, value, 0, 31, 31, SetRC);
+  //  bc(label, BT/BF, 2)
+  // and vice-versa to be disabled again.
+  CodePatcher patcher(patch_address, 2);
+  Register reg = Assembler::GetRA(instr_at_patch);
+  if (check == ENABLE_INLINED_SMI_CHECK) {
+    ASSERT(Assembler::IsCmpRegister(instr_at_patch));
+    ASSERT_EQ(Assembler::GetRA(instr_at_patch).code(),
+              Assembler::GetRB(instr_at_patch).code());
+    patcher.masm()->TestIfSmi(reg, r0);
+  } else {
+    ASSERT(check == DISABLE_INLINED_SMI_CHECK);
+#if V8_TARGET_ARCH_PPC64
+    ASSERT(Assembler::IsRldicl(instr_at_patch));
+#else
+    ASSERT(Assembler::IsRlwinm(instr_at_patch));
+#endif
+    patcher.masm()->cmp(reg, reg, cr0);
+  }
+
+  ASSERT(Assembler::IsBranch(branch_instr));
+
+  // Invert the logic of the branch
+  if (Assembler::GetCondition(branch_instr) == eq) {
+    patcher.EmitCondition(ne);
+  } else {
+    ASSERT(Assembler::GetCondition(branch_instr) == ne);
+    patcher.EmitCondition(eq);
+  }
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/lithium-codegen-ppc.cc b/src/ppc/lithium-codegen-ppc.cc
new file mode 100644
index 0000000..20abd34
--- /dev/null
+++ b/src/ppc/lithium-codegen-ppc.cc
@@ -0,0 +1,5715 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#include "v8.h"
+
+#include "ppc/lithium-codegen-ppc.h"
+#include "ppc/lithium-gap-resolver-ppc.h"
+#include "code-stubs.h"
+#include "stub-cache.h"
+
+namespace v8 {
+namespace internal {
+
+
+class SafepointGenerator : public CallWrapper {
+ public:
+  SafepointGenerator(LCodeGen* codegen,
+                     LPointerMap* pointers,
+                     Safepoint::DeoptMode mode)
+      : codegen_(codegen),
+        pointers_(pointers),
+        deopt_mode_(mode) { }
+  virtual ~SafepointGenerator() { }
+
+  virtual void BeforeCall(int call_size) const { }
+
+  virtual void AfterCall() const {
+    codegen_->RecordSafepoint(pointers_, deopt_mode_);
+  }
+
+ private:
+  LCodeGen* codegen_;
+  LPointerMap* pointers_;
+  Safepoint::DeoptMode deopt_mode_;
+};
+
+
+#define __ masm()->
+
+bool LCodeGen::GenerateCode() {
+  HPhase phase("Z_Code generation", chunk());
+  ASSERT(is_unused());
+  status_ = GENERATING;
+
+  CodeStub::GenerateFPStubs();
+
+  // Open a frame scope to indicate that there is a frame on the stack.  The
+  // NONE indicates that the scope shouldn't actually generate code to set up
+  // the frame (that is done in GeneratePrologue).
+  FrameScope frame_scope(masm_, StackFrame::NONE);
+
+  return GeneratePrologue() &&
+      GenerateBody() &&
+      GenerateDeferredCode() &&
+      GenerateDeoptJumpTable() &&
+      GenerateSafepointTable();
+}
+
+
+void LCodeGen::FinishCode(Handle<Code> code) {
+  ASSERT(is_done());
+  code->set_stack_slots(GetStackSlotCount());
+  code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
+  PopulateDeoptimizationData(code);
+}
+
+
+void LCodeGen::Abort(const char* reason) {
+  info()->set_bailout_reason(reason);
+  status_ = ABORTED;
+}
+
+
+void LCodeGen::Comment(const char* format, ...) {
+  if (!FLAG_code_comments) return;
+  char buffer[4 * KB];
+  StringBuilder builder(buffer, ARRAY_SIZE(buffer));
+  va_list arguments;
+  va_start(arguments, format);
+  builder.AddFormattedList(format, arguments);
+  va_end(arguments);
+
+  // Copy the string before recording it in the assembler to avoid
+  // issues when the stack allocated buffer goes out of scope.
+  size_t length = builder.position();
+  Vector<char> copy = Vector<char>::New(length + 1);
+  memcpy(copy.start(), builder.Finalize(), copy.length());
+  masm()->RecordComment(copy.start());
+}
+
+
+bool LCodeGen::GeneratePrologue() {
+  ASSERT(is_generating());
+
+  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
+
+#ifdef DEBUG
+  if (strlen(FLAG_stop_at) > 0 &&
+      info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
+    __ stop("stop_at");
+  }
+#endif
+
+  // r4: Callee's JS function.
+  // cp: Callee's context.
+  // fp: Caller's frame pointer.
+  // lr: Caller's pc.
+
+  // Strict mode functions and builtins need to replace the receiver
+  // with undefined when called as functions (without an explicit
+  // receiver object). r8 is zero for method calls and non-zero for
+  // function calls.
+  if (!info_->is_classic_mode() || info_->is_native()) {
+    Label ok;
+    __ cmpi(r8, Operand::Zero());
+    __ beq(&ok);
+    int receiver_offset = scope()->num_parameters() * kPointerSize;
+    __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+    __ StoreP(r5, MemOperand(sp, receiver_offset));
+    __ bind(&ok);
+  }
+
+  __ mflr(r0);
+  __ Push(r0, fp, cp, r4);
+  __ addi(fp, sp, Operand(2 * kPointerSize));  // Adjust FP to point to saved FP
+
+  // Reserve space for the stack slots needed by the code.
+  int slots = GetStackSlotCount();
+  if (slots > 0) {
+    if (FLAG_debug_code) {
+      __ mov(r3, Operand(slots));
+      __ mov(r5, Operand(kSlotsZapValue));
+      __ mtctr(r3);
+      Label loop;
+      __ bind(&loop);
+      __ push(r5);
+      __ bdnz(&loop);
+    } else {
+      __ addi(sp, sp, Operand(-slots * kPointerSize));
+    }
+  }
+
+  // Possibly allocate a local context.
+  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  if (heap_slots > 0) {
+    Comment(";;; Allocate local context");
+    // Argument to NewContext is the function, which is in r4.
+    __ push(r4);
+    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+      FastNewContextStub stub(heap_slots);
+      __ CallStub(&stub);
+    } else {
+      __ CallRuntime(Runtime::kNewFunctionContext, 1);
+    }
+    RecordSafepoint(Safepoint::kNoLazyDeopt);
+    // Context is returned in both r3 and cp.  It replaces the context
+    // passed to us.  It's saved in the stack and kept live in cp.
+    __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+    // Copy any necessary parameters into the context.
+    int num_parameters = scope()->num_parameters();
+    for (int i = 0; i < num_parameters; i++) {
+      Variable* var = scope()->parameter(i);
+      if (var->IsContextSlot()) {
+        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
+            (num_parameters - 1 - i) * kPointerSize;
+        // Load parameter from stack.
+        __ LoadP(r3, MemOperand(fp, parameter_offset));
+        // Store it in the context.
+        MemOperand target = ContextOperand(cp, var->index());
+        __ StoreP(r3, target, r0);
+        // Update the write barrier. This clobbers r6 and r3.
+        __ RecordWriteContextSlot(
+            cp, target.offset(), r3, r6, kLRHasBeenSaved, kSaveFPRegs);
+      }
+    }
+    Comment(";;; End allocate local context");
+  }
+
+  // Trace the call.
+  if (FLAG_trace) {
+    __ CallRuntime(Runtime::kTraceEnter, 0);
+  }
+  return !is_aborted();
+}
+
+
+bool LCodeGen::GenerateBody() {
+  ASSERT(is_generating());
+  bool emit_instructions = true;
+  for (current_instruction_ = 0;
+       !is_aborted() && current_instruction_ < instructions_->length();
+       current_instruction_++) {
+    LInstruction* instr = instructions_->at(current_instruction_);
+    if (instr->IsLabel()) {
+      LLabel* label = LLabel::cast(instr);
+      emit_instructions = !label->HasReplacement();
+    }
+
+    if (emit_instructions) {
+      Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic());
+      instr->CompileToNative(this);
+    }
+  }
+  EnsureSpaceForLazyDeopt();
+  return !is_aborted();
+}
+
+
+bool LCodeGen::GenerateDeferredCode() {
+  ASSERT(is_generating());
+  if (deferred_.length() > 0) {
+    for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
+      LDeferredCode* code = deferred_[i];
+      __ bind(code->entry());
+      Comment(";;; Deferred code @%d: %s.",
+              code->instruction_index(),
+              code->instr()->Mnemonic());
+      code->Generate();
+      __ b(code->exit());
+    }
+  }
+
+  return !is_aborted();
+}
+
+bool LCodeGen::GenerateDeoptJumpTable() {
+  __ RecordComment("[ Deoptimisation jump table");
+  for (int i = 0; i < deopt_jump_table_.length(); i++) {
+    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
+    __ bind(&deopt_jump_table_[i].label);
+    __ Jump(deopt_jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
+  }
+  __ RecordComment("]");
+
+  // The deoptimization jump table is the last part of the instruction
+  // sequence. Mark the generated code as done unless we bailed out.
+  if (!is_aborted()) status_ = DONE;
+  return !is_aborted();
+}
+
+
+bool LCodeGen::GenerateSafepointTable() {
+  ASSERT(is_done());
+  safepoints_.Emit(masm(), GetStackSlotCount());
+  return !is_aborted();
+}
+
+
+Register LCodeGen::ToRegister(int index) const {
+  return Register::FromAllocationIndex(index);
+}
+
+
+DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
+  return DoubleRegister::FromAllocationIndex(index);
+}
+
+
+Register LCodeGen::ToRegister(LOperand* op) const {
+  ASSERT(op->IsRegister());
+  return ToRegister(op->index());
+}
+
+
+Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
+  if (op->IsRegister()) {
+    return ToRegister(op->index());
+  } else if (op->IsConstantOperand()) {
+    LConstantOperand* const_op = LConstantOperand::cast(op);
+    HConstant* constant = chunk_->LookupConstant(const_op);
+    Handle<Object> literal = constant->handle();
+    Representation r = chunk_->LookupLiteralRepresentation(const_op);
+    if (r.IsInteger32()) {
+      ASSERT(literal->IsNumber());
+      __ LoadIntLiteral(scratch, static_cast<intptr_t>(literal->Number()));
+    } else if (r.IsDouble()) {
+      Abort("EmitLoadRegister: Unsupported double immediate.");
+    } else {
+      ASSERT(r.IsTagged());
+      if (literal->IsSmi()) {
+        __ mov(scratch, Operand(literal));
+      } else {
+       __ LoadHeapObject(scratch, Handle<HeapObject>::cast(literal));
+      }
+    }
+    return scratch;
+  } else if (op->IsStackSlot() || op->IsArgument()) {
+    __ LoadP(scratch, ToMemOperand(op));
+    return scratch;
+  }
+  UNREACHABLE();
+  return scratch;
+}
+
+
+DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
+  ASSERT(op->IsDoubleRegister());
+  return ToDoubleRegister(op->index());
+}
+
+
+Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
+  return constant->handle();
+}
+
+
+bool LCodeGen::IsInteger32(LConstantOperand* op) const {
+  return chunk_->LookupLiteralRepresentation(op).IsInteger32();
+}
+
+
+int LCodeGen::ToInteger32(LConstantOperand* op) const {
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
+  ASSERT(constant->HasInteger32Value());
+  return constant->Integer32Value();
+}
+
+
+double LCodeGen::ToDouble(LConstantOperand* op) const {
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(constant->HasDoubleValue());
+  return constant->DoubleValue();
+}
+
+
+Operand LCodeGen::ToOperand(LOperand* op) {
+  if (op->IsConstantOperand()) {
+    LConstantOperand* const_op = LConstantOperand::cast(op);
+    HConstant* constant = chunk()->LookupConstant(const_op);
+    Representation r = chunk_->LookupLiteralRepresentation(const_op);
+    if (r.IsInteger32()) {
+      ASSERT(constant->HasInteger32Value());
+      return Operand(constant->Integer32Value());
+    } else if (r.IsDouble()) {
+      Abort("ToOperand Unsupported double immediate.");
+    }
+    ASSERT(r.IsTagged());
+    return Operand(constant->handle());
+  } else if (op->IsRegister()) {
+    return Operand(ToRegister(op));
+  } else if (op->IsDoubleRegister()) {
+    Abort("ToOperand IsDoubleRegister unimplemented");
+    return Operand::Zero();
+  }
+  // Stack slots not implemented, use ToMemOperand instead.
+  UNREACHABLE();
+  return Operand::Zero();
+}
+
+
+MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
+  ASSERT(!op->IsRegister());
+  ASSERT(!op->IsDoubleRegister());
+  ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
+  int index = op->index();
+  if (index >= 0) {
+    // Local or spill slot. Skip the frame pointer, function, and
+    // context in the fixed part of the frame.
+    return MemOperand(fp, -(index + 3) * kPointerSize);
+  } else {
+    // Incoming parameter. Skip the return address.
+    return MemOperand(fp, -(index - 1) * kPointerSize);
+  }
+}
+
+
+MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
+  ASSERT(op->IsDoubleStackSlot());
+  int index = op->index();
+  if (index >= 0) {
+    // Local or spill slot. Skip the frame pointer, function, context,
+    // and the first word of the double in the fixed part of the frame.
+    return MemOperand(fp, -(index + 3) * kPointerSize + kIntSize);
+  } else {
+    // Incoming parameter. Skip the return address and the first word of
+    // the double.
+    return MemOperand(fp, -(index - 1) * kPointerSize + kIntSize);
+  }
+}
+
+
+void LCodeGen::WriteTranslation(LEnvironment* environment,
+                                Translation* translation,
+                                int* arguments_index,
+                                int* arguments_count) {
+  if (environment == NULL) return;
+
+  // The translation includes one command per value in the environment.
+  int translation_size = environment->values()->length();
+  // The output frame height does not include the parameters.
+  int height = translation_size - environment->parameter_count();
+
+  // Function parameters are arguments to the outermost environment. The
+  // arguments index points to the first element of a sequence of tagged
+  // values on the stack that represent the arguments. This needs to be
+  // kept in sync with the LArgumentsElements implementation.
+  *arguments_index = -environment->parameter_count();
+  *arguments_count = environment->parameter_count();
+
+  WriteTranslation(environment->outer(),
+                   translation,
+                   arguments_index,
+                   arguments_count);
+  int closure_id = *info()->closure() != *environment->closure()
+      ? DefineDeoptimizationLiteral(environment->closure())
+      : Translation::kSelfLiteralId;
+
+  switch (environment->frame_type()) {
+    case JS_FUNCTION:
+      translation->BeginJSFrame(environment->ast_id(), closure_id, height);
+      break;
+    case JS_CONSTRUCT:
+      translation->BeginConstructStubFrame(closure_id, translation_size);
+      break;
+    case JS_GETTER:
+      ASSERT(translation_size == 1);
+      ASSERT(height == 0);
+      translation->BeginGetterStubFrame(closure_id);
+      break;
+    case JS_SETTER:
+      ASSERT(translation_size == 2);
+      ASSERT(height == 0);
+      translation->BeginSetterStubFrame(closure_id);
+      break;
+    case ARGUMENTS_ADAPTOR:
+      translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
+      break;
+  }
+
+  // Inlined frames which push their arguments cause the index to be
+  // bumped and a new stack area to be used for materialization.
+  if (environment->entry() != NULL &&
+      environment->entry()->arguments_pushed()) {
+    *arguments_index = *arguments_index < 0
+        ? GetStackSlotCount()
+        : *arguments_index + *arguments_count;
+    *arguments_count = environment->entry()->arguments_count() + 1;
+  }
+
+  for (int i = 0; i < translation_size; ++i) {
+    LOperand* value = environment->values()->at(i);
+    // spilled_registers_ and spilled_double_registers_ are either
+    // both NULL or both set.
+    if (environment->spilled_registers() != NULL && value != NULL) {
+      if (value->IsRegister() &&
+          environment->spilled_registers()[value->index()] != NULL) {
+        translation->MarkDuplicate();
+        AddToTranslation(translation,
+                         environment->spilled_registers()[value->index()],
+                         environment->HasTaggedValueAt(i),
+                         environment->HasUint32ValueAt(i),
+                         *arguments_index,
+                         *arguments_count);
+      } else if (
+          value->IsDoubleRegister() &&
+          environment->spilled_double_registers()[value->index()] != NULL) {
+        translation->MarkDuplicate();
+        AddToTranslation(
+            translation,
+            environment->spilled_double_registers()[value->index()],
+            false,
+            false,
+            *arguments_index,
+            *arguments_count);
+      }
+    }
+
+    AddToTranslation(translation,
+                     value,
+                     environment->HasTaggedValueAt(i),
+                     environment->HasUint32ValueAt(i),
+                     *arguments_index,
+                     *arguments_count);
+  }
+}
+
+
+void LCodeGen::AddToTranslation(Translation* translation,
+                                LOperand* op,
+                                bool is_tagged,
+                                bool is_uint32,
+                                int arguments_index,
+                                int arguments_count) {
+  if (op == NULL) {
+    // TODO(twuerthinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    translation->StoreArgumentsObject(arguments_index, arguments_count);
+  } else if (op->IsStackSlot()) {
+    if (is_tagged) {
+      translation->StoreStackSlot(op->index());
+    } else if (is_uint32) {
+      translation->StoreUint32StackSlot(op->index());
+    } else {
+      translation->StoreInt32StackSlot(op->index());
+    }
+  } else if (op->IsDoubleStackSlot()) {
+    translation->StoreDoubleStackSlot(op->index());
+  } else if (op->IsArgument()) {
+    ASSERT(is_tagged);
+    int src_index = GetStackSlotCount() + op->index();
+    translation->StoreStackSlot(src_index);
+  } else if (op->IsRegister()) {
+    Register reg = ToRegister(op);
+    if (is_tagged) {
+      translation->StoreRegister(reg);
+    } else if (is_uint32) {
+      translation->StoreUint32Register(reg);
+    } else {
+      translation->StoreInt32Register(reg);
+    }
+  } else if (op->IsDoubleRegister()) {
+    DoubleRegister reg = ToDoubleRegister(op);
+    translation->StoreDoubleRegister(reg);
+  } else if (op->IsConstantOperand()) {
+    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
+    int src_index = DefineDeoptimizationLiteral(constant->handle());
+    translation->StoreLiteral(src_index);
+  } else {
+    UNREACHABLE();
+  }
+}
+
+
+void LCodeGen::CallCode(Handle<Code> code,
+                        RelocInfo::Mode mode,
+                        LInstruction* instr) {
+  CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
+}
+
+
+void LCodeGen::CallCodeGeneric(Handle<Code> code,
+                               RelocInfo::Mode mode,
+                               LInstruction* instr,
+                               SafepointMode safepoint_mode) {
+  ASSERT(instr != NULL);
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+  __ Call(code, mode);
+  RecordSafepointWithLazyDeopt(instr, safepoint_mode);
+
+  // Signal that we don't inline smi code before these stubs in the
+  // optimizing code generator.
+  if (code->kind() == Code::BINARY_OP_IC ||
+      code->kind() == Code::COMPARE_IC) {
+    __ nop();
+  }
+}
+
+
+void LCodeGen::CallRuntime(const Runtime::Function* function,
+                           int num_arguments,
+                           LInstruction* instr) {
+  ASSERT(instr != NULL);
+  LPointerMap* pointers = instr->pointer_map();
+  ASSERT(pointers != NULL);
+  RecordPosition(pointers->position());
+
+  __ CallRuntime(function, num_arguments);
+  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
+}
+
+
+void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
+                                       int argc,
+                                       LInstruction* instr) {
+  __ CallRuntimeSaveDoubles(id);
+  RecordSafepointWithRegisters(
+      instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
+}
+
+
+void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
+                                                    Safepoint::DeoptMode mode) {
+  if (!environment->HasBeenRegistered()) {
+    // Physical stack frame layout:
+    // -x ............. -4  0 ..................................... y
+    // [incoming arguments] [spill slots] [pushed outgoing arguments]
+
+    // Layout of the environment:
+    // 0 ..................................................... size-1
+    // [parameters] [locals] [expression stack including arguments]
+
+    // Layout of the translation:
+    // 0 ........................................................ size - 1 + 4
+    // [expression stack including arguments] [locals] [4 words] [parameters]
+    // |>------------  translation_size ------------<|
+
+    int frame_count = 0;
+    int jsframe_count = 0;
+    int args_index = 0;
+    int args_count = 0;
+    for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
+      ++frame_count;
+      if (e->frame_type() == JS_FUNCTION) {
+        ++jsframe_count;
+      }
+    }
+    Translation translation(&translations_, frame_count, jsframe_count, zone());
+    WriteTranslation(environment, &translation, &args_index, &args_count);
+    int deoptimization_index = deoptimizations_.length();
+    int pc_offset = masm()->pc_offset();
+    environment->Register(deoptimization_index,
+                          translation.index(),
+                          (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
+    deoptimizations_.Add(environment, zone());
+  }
+}
+
+
+void LCodeGen::DeoptimizeIf(Condition cond, LEnvironment* environment,
+                            CRegister cr) {
+  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
+  ASSERT(environment->HasBeenRegistered());
+  int id = environment->deoptimization_index();
+  Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
+  if (entry == NULL) {
+    Abort("bailout was not prepared");
+    return;
+  }
+
+  ASSERT(FLAG_deopt_every_n_times < 2);  // Other values not supported on PPC.
+
+  if (FLAG_deopt_every_n_times == 1 &&
+      info_->shared_info()->opt_count() == id) {
+    __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
+    return;
+  }
+
+  if (FLAG_trap_on_deopt) __ stop("trap_on_deopt", cond, kDefaultStopCode, cr);
+
+  if (cond == al) {
+    __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
+  } else {
+    // We often have several deopts to the same entry, reuse the last
+    // jump entry if this is the case.
+    if (deopt_jump_table_.is_empty() ||
+        (deopt_jump_table_.last().address != entry)) {
+      deopt_jump_table_.Add(JumpTableEntry(entry), zone());
+    }
+    __ b(cond, &deopt_jump_table_.last().label, cr);
+  }
+}
+
+
+void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
+  int length = deoptimizations_.length();
+  if (length == 0) return;
+  Handle<DeoptimizationInputData> data =
+      factory()->NewDeoptimizationInputData(length, TENURED);
+
+  Handle<ByteArray> translations = translations_.CreateByteArray();
+  data->SetTranslationByteArray(*translations);
+  data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
+
+  Handle<FixedArray> literals =
+      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
+  for (int i = 0; i < deoptimization_literals_.length(); i++) {
+    literals->set(i, *deoptimization_literals_[i]);
+  }
+  data->SetLiteralArray(*literals);
+
+  data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
+  data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
+
+  // Populate the deoptimization entries.
+  for (int i = 0; i < length; i++) {
+    LEnvironment* env = deoptimizations_[i];
+    data->SetAstId(i, env->ast_id());
+    data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
+    data->SetArgumentsStackHeight(i,
+                                  Smi::FromInt(env->arguments_stack_height()));
+    data->SetPc(i, Smi::FromInt(env->pc_offset()));
+  }
+  code->set_deoptimization_data(*data);
+}
+
+
+int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
+  int result = deoptimization_literals_.length();
+  for (int i = 0; i < deoptimization_literals_.length(); ++i) {
+    if (deoptimization_literals_[i].is_identical_to(literal)) return i;
+  }
+  deoptimization_literals_.Add(literal, zone());
+  return result;
+}
+
+
+void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
+  ASSERT(deoptimization_literals_.length() == 0);
+
+  const ZoneList<Handle<JSFunction> >* inlined_closures =
+      chunk()->inlined_closures();
+
+  for (int i = 0, length = inlined_closures->length();
+       i < length;
+       i++) {
+    DefineDeoptimizationLiteral(inlined_closures->at(i));
+  }
+
+  inlined_function_count_ = deoptimization_literals_.length();
+}
+
+
+void LCodeGen::RecordSafepointWithLazyDeopt(
+    LInstruction* instr, SafepointMode safepoint_mode) {
+  if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
+    RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
+  } else {
+    ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+    RecordSafepointWithRegisters(
+        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
+  }
+}
+
+
+void LCodeGen::RecordSafepoint(
+    LPointerMap* pointers,
+    Safepoint::Kind kind,
+    int arguments,
+    Safepoint::DeoptMode deopt_mode) {
+  ASSERT(expected_safepoint_kind_ == kind);
+
+  const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
+  Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
+      kind, arguments, deopt_mode);
+  for (int i = 0; i < operands->length(); i++) {
+    LOperand* pointer = operands->at(i);
+    if (pointer->IsStackSlot()) {
+      safepoint.DefinePointerSlot(pointer->index(), zone());
+    } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
+      safepoint.DefinePointerRegister(ToRegister(pointer), zone());
+    }
+  }
+  if (kind & Safepoint::kWithRegisters) {
+    // Register cp always contains a pointer to the context.
+    safepoint.DefinePointerRegister(cp, zone());
+  }
+}
+
+
+void LCodeGen::RecordSafepoint(LPointerMap* pointers,
+                               Safepoint::DeoptMode deopt_mode) {
+  RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
+}
+
+
+void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
+  LPointerMap empty_pointers(RelocInfo::kNoPosition, zone());
+  RecordSafepoint(&empty_pointers, deopt_mode);
+}
+
+
+void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
+                                            int arguments,
+                                            Safepoint::DeoptMode deopt_mode) {
+  RecordSafepoint(
+      pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
+}
+
+
+void LCodeGen::RecordPosition(int position) {
+  if (position == RelocInfo::kNoPosition) return;
+  masm()->positions_recorder()->RecordPosition(position);
+}
+
+
+void LCodeGen::DoLabel(LLabel* label) {
+  if (label->is_loop_header()) {
+    Comment(";;; B%d - LOOP entry", label->block_id());
+  } else {
+    Comment(";;; B%d", label->block_id());
+  }
+  __ bind(label->label());
+  current_block_ = label->block_id();
+  DoGap(label);
+}
+
+
+void LCodeGen::DoParallelMove(LParallelMove* move) {
+  resolver_.Resolve(move);
+}
+
+
+void LCodeGen::DoGap(LGap* gap) {
+  for (int i = LGap::FIRST_INNER_POSITION;
+       i <= LGap::LAST_INNER_POSITION;
+       i++) {
+    LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
+    LParallelMove* move = gap->GetParallelMove(inner_pos);
+    if (move != NULL) DoParallelMove(move);
+  }
+}
+
+
+void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
+  DoGap(instr);
+}
+
+
+void LCodeGen::DoParameter(LParameter* instr) {
+  // Nothing to do.
+}
+
+
+void LCodeGen::DoCallStub(LCallStub* instr) {
+  ASSERT(ToRegister(instr->result()).is(r3));
+  switch (instr->hydrogen()->major_key()) {
+    case CodeStub::RegExpConstructResult: {
+      RegExpConstructResultStub stub;
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+      break;
+    }
+    case CodeStub::RegExpExec: {
+      RegExpExecStub stub;
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+      break;
+    }
+    case CodeStub::SubString: {
+      SubStringStub stub;
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+      break;
+    }
+    case CodeStub::NumberToString: {
+      NumberToStringStub stub;
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+      break;
+    }
+    case CodeStub::StringAdd: {
+      StringAddStub stub(NO_STRING_ADD_FLAGS);
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+      break;
+    }
+    case CodeStub::StringCompare: {
+      StringCompareStub stub;
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+      break;
+    }
+    case CodeStub::TranscendentalCache: {
+      __ LoadP(r3, MemOperand(sp, 0));
+      TranscendentalCacheStub stub(instr->transcendental_type(),
+                                   TranscendentalCacheStub::TAGGED);
+      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+
+
+void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
+  // Nothing to do.
+}
+
+
+void LCodeGen::DoModI(LModI* instr) {
+  Register dividend = ToRegister(instr->left());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+  Label done;
+
+  if (instr->hydrogen()->HasPowerOf2Divisor()) {
+    int32_t divisor =
+        HConstant::cast(instr->hydrogen()->right())->Integer32Value();
+
+    if (divisor < 0) divisor = -divisor;
+
+    Label positive_dividend;
+    __ cmpi(dividend, Operand::Zero());
+    __ bge(&positive_dividend);
+    __ neg(result, dividend);
+    __ mov(scratch, Operand(divisor - 1));
+    __ and_(result, result, scratch, SetRC);
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      DeoptimizeIf(eq, instr->environment(), cr0);
+    }
+    __ neg(result, result);
+    __ b(&done);
+    __ bind(&positive_dividend);
+    __ mov(scratch, Operand(divisor - 1));
+    __ and_(result, dividend, scratch);
+  } else {
+    Register divisor = ToRegister(instr->right());
+
+    __ divw(scratch, dividend, divisor);
+
+    // Check for x % 0.
+    if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+        __ cmpi(divisor, Operand::Zero());
+        DeoptimizeIf(eq, instr->environment());
+    }
+
+#if V8_TARGET_ARCH_PPC64
+    __ extsw(scratch, scratch);
+#endif
+    __ Mul(scratch, divisor, scratch);
+    __ sub(result, dividend, scratch, LeaveOE, SetRC);
+
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ cmpi(dividend, Operand::Zero());
+      __ bge(&done);
+      DeoptimizeIf(eq, instr->environment(), cr0);
+    }
+  }
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoDivI(LDivI* instr) {
+  const Register left = ToRegister(instr->left());
+  const Register right = ToRegister(instr->right());
+  const Register scratch = scratch0();
+  const Register result = ToRegister(instr->result());
+
+  __ divw(result, left, right);
+
+  // Check for x / 0.
+  if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+    __ cmpi(right, Operand::Zero());
+    DeoptimizeIf(eq, instr->environment());
+  }
+
+  // Check for (0 / -x) that will produce negative zero.
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    Label left_not_zero;
+    __ cmpi(left, Operand::Zero());
+    __ bne(&left_not_zero);
+    __ cmpi(right, Operand::Zero());
+    DeoptimizeIf(lt, instr->environment());
+    __ bind(&left_not_zero);
+  }
+
+  // Check for (-kMinInt / -1).
+  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+    Label left_not_min_int;
+    __ Cmpi(left, Operand(kMinInt), r0);
+    __ bne(&left_not_min_int);
+    __ cmpi(right, Operand(-1));
+    DeoptimizeIf(eq, instr->environment());
+    __ bind(&left_not_min_int);
+  }
+
+#if V8_TARGET_ARCH_PPC64
+  __ extsw(result, result);
+#endif
+
+  // Deoptimize on non-zero remainder
+  __ Mul(scratch, right, result);
+  __ cmp(left, scratch);
+  DeoptimizeIf(ne, instr->environment());
+}
+
+
+void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
+  ASSERT(instr->right()->IsConstantOperand());
+
+  const Register dividend = ToRegister(instr->left());
+  int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
+  const Register result = ToRegister(instr->result());
+
+  switch (divisor) {
+    case 0:
+      DeoptimizeIf(al, instr->environment());
+      return;
+
+    case 1:
+      __ Move(result, dividend);
+      return;
+
+    case -1: {
+      OEBit oe;
+      if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+        __ li(r0, Operand::Zero());  // clear xer
+        __ mtxer(r0);
+        oe = SetOE;
+      } else {
+        oe = LeaveOE;
+      }
+      __ neg(result, dividend, oe, SetRC);
+      if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+        DeoptimizeIf(eq, instr->environment(), cr0);
+      }
+      if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+        DeoptimizeIf(overflow, instr->environment(), cr0);
+      }
+      return;
+    }
+  }
+
+  uint32_t divisor_abs = abs(divisor);
+  if (IsPowerOf2(divisor_abs)) {
+    int32_t power = WhichPowerOf2(divisor_abs);
+    if (divisor < 0) {
+      __ neg(result, dividend, LeaveOE, SetRC);
+      if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+        DeoptimizeIf(eq, instr->environment(), cr0);
+      }
+      __ ShiftRightArithImm(result, result, power);
+    } else {
+      __ ShiftRightArithImm(result, dividend, power);
+    }
+  } else {
+    Register scratch = ToRegister(instr->temp());
+
+    // Find b which: 2^b < divisor_abs < 2^(b+1).
+    unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs);
+    unsigned shift = 32 + b;  // Precision +1bit (effectively).
+    double multiplier_f =
+        static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs;
+    int64_t multiplier;
+    if (multiplier_f - floor(multiplier_f) < 0.5) {
+        multiplier = static_cast<int64_t>(floor(multiplier_f));
+    } else {
+        multiplier = static_cast<int64_t>(floor(multiplier_f)) + 1;
+    }
+    // The multiplier is a uint32.
+    ASSERT(multiplier > 0 &&
+           multiplier < (static_cast<int64_t>(1) << 32));
+#if V8_TARGET_ARCH_PPC64
+    __ extsw(scratch, dividend);
+    if (divisor < 0 &&
+        instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ neg(scratch, scratch, LeaveOE, SetRC);
+      DeoptimizeIf(eq, instr->environment(), cr0);
+    }
+    __ mov(result, Operand(multiplier));
+    __ Mul(result, result, scratch);
+    __ addis(result, result, Operand(0x4000));
+    __ ShiftRightArithImm(result, result, shift);
+#else
+    if (divisor < 0 &&
+        instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ cmpi(dividend, Operand::Zero());
+      DeoptimizeIf(eq, instr->environment());
+    }
+    __ mov(result, Operand(multiplier));
+    __ mullw(ip, result, dividend);
+    __ mulhw(result, result, dividend);
+
+    if (static_cast<int32_t>(multiplier) < 0) {
+      __ add(result, result, dividend);
+    }
+    if (divisor < 0) {
+      __ neg(result, result);
+
+      // Subtract one from result if -(low word) < 0xC0000000
+      __ neg(ip, ip);
+      __ srwi(scratch, ip, Operand(30));
+      __ addi(scratch, scratch, Operand(1));
+      __ srwi(scratch, scratch, Operand(2));
+      __ addi(scratch, scratch, Operand(-1));
+      __ add(result, result, scratch);
+    } else {
+      // Add one to result if low word >= 0xC0000000
+      __ srwi(scratch, ip, Operand(30));
+      __ addi(scratch, scratch, Operand(1));
+      __ srwi(scratch, scratch, Operand(2));
+      __ add(result, result, scratch);
+    }
+    __ ShiftRightArithImm(result, result, shift - 32);
+#endif
+  }
+}
+
+
+void LCodeGen::DoMulI(LMulI* instr) {
+  Register scratch = scratch0();
+  Register result = ToRegister(instr->result());
+  // Note that result may alias left.
+  Register left = ToRegister(instr->left());
+  LOperand* right_op = instr->right();
+
+  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+  bool bailout_on_minus_zero =
+    instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
+
+  if (right_op->IsConstantOperand() && !can_overflow) {
+    // Use optimized code for specific constants.
+    int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
+
+    if (bailout_on_minus_zero && (constant < 0)) {
+      // The case of a null constant will be handled separately.
+      // If constant is negative and left is null, the result should be -0.
+      __ cmpi(left, Operand::Zero());
+      DeoptimizeIf(eq, instr->environment());
+    }
+
+    switch (constant) {
+      case -1:
+        __ neg(result, left);
+        break;
+      case 0:
+        if (bailout_on_minus_zero) {
+          // If left is strictly negative and the constant is null, the
+          // result is -0. Deoptimize if required, otherwise return 0.
+          __ cmpi(left, Operand::Zero());
+          DeoptimizeIf(lt, instr->environment());
+        }
+        __ li(result, Operand::Zero());
+        break;
+      case 1:
+        __ Move(result, left);
+        break;
+      default:
+        // Multiplying by powers of two and powers of two plus or minus
+        // one can be done faster with shifted operands.
+        // For other constants we emit standard code.
+        int32_t mask = constant >> 31;
+        uint32_t constant_abs = (constant + mask) ^ mask;
+
+        if (IsPowerOf2(constant_abs) ||
+            IsPowerOf2(constant_abs - 1) ||
+            IsPowerOf2(constant_abs + 1)) {
+          if (IsPowerOf2(constant_abs)) {
+            int32_t shift = WhichPowerOf2(constant_abs);
+            __ ShiftLeftImm(result, left, Operand(shift));
+          } else if (IsPowerOf2(constant_abs - 1)) {
+            int32_t shift = WhichPowerOf2(constant_abs - 1);
+            __ ShiftLeftImm(scratch, left, Operand(shift));
+            __ add(result, scratch, left);
+          } else if (IsPowerOf2(constant_abs + 1)) {
+            int32_t shift = WhichPowerOf2(constant_abs + 1);
+            __ ShiftLeftImm(scratch, left, Operand(shift));
+            __ sub(result, scratch, left);
+          }
+
+          // Correct the sign of the result is the constant is negative.
+          if (constant < 0)  __ neg(result, result);
+
+        } else {
+          // Generate standard code.
+          __ mov(ip, Operand(constant));
+          __ Mul(result, left, ip);
+        }
+    }
+
+  } else {
+    Register right = EmitLoadRegister(right_op, ip);
+    if (bailout_on_minus_zero) {
+      __ orx(ToRegister(instr->temp()), left, right);
+    }
+
+    if (can_overflow) {
+      // scratch:result = left * right.
+#if V8_TARGET_ARCH_PPC64
+      __ Mul(result, left, right);
+      __ TestIfInt32(result, scratch, r0);
+      DeoptimizeIf(ne, instr->environment());
+#else
+      __ mulhw(scratch, left, right);
+      __ mullw(result, left, right);
+      __ TestIfInt32(scratch, result, r0);
+      DeoptimizeIf(ne, instr->environment());
+#endif
+    } else {
+      __ Mul(result, left, right);
+    }
+
+    if (bailout_on_minus_zero) {
+      // Bail out if the result is supposed to be negative zero.
+      Label done;
+      __ cmpi(result, Operand::Zero());
+      __ bne(&done);
+      __ cmpi(ToRegister(instr->temp()), Operand::Zero());
+      DeoptimizeIf(lt, instr->environment());
+      __ bind(&done);
+    }
+  }
+}
+
+
+void LCodeGen::DoBitI(LBitI* instr) {
+  LOperand* left_op = instr->left();
+  LOperand* right_op = instr->right();
+  ASSERT(left_op->IsRegister());
+  Register left = ToRegister(left_op);
+  Register result = ToRegister(instr->result());
+  Operand right(no_reg);
+
+  if (right_op->IsStackSlot() || right_op->IsArgument()) {
+    right = Operand(EmitLoadRegister(right_op, ip));
+  } else {
+    ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
+
+    if (right_op->IsConstantOperand() &&
+        is_uint16(ToInteger32(LConstantOperand::cast(right_op)))) {
+      switch (instr->op()) {
+        case Token::BIT_AND:
+          __ andi(result, left,
+                  Operand(ToInteger32(LConstantOperand::cast(right_op))));
+          break;
+        case Token::BIT_OR:
+          __ ori(result, left,
+                 Operand(ToInteger32(LConstantOperand::cast(right_op))));
+          break;
+        case Token::BIT_XOR:
+          __ xori(result, left,
+                  Operand(ToInteger32(LConstantOperand::cast(right_op))));
+          break;
+        default:
+          UNREACHABLE();
+          break;
+      }
+      return;
+    }
+    right = ToOperand(right_op);
+  }
+
+  switch (instr->op()) {
+    case Token::BIT_AND:
+      __ And(result, left, right);
+      break;
+    case Token::BIT_OR:
+      __ Or(result, left, right);
+      break;
+    case Token::BIT_XOR:
+      __ Xor(result, left, right);
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void LCodeGen::DoShiftI(LShiftI* instr) {
+  // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so
+  // result may alias either of them.
+  LOperand* right_op = instr->right();
+  Register left = ToRegister(instr->left());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+  if (right_op->IsRegister()) {
+    // Mask the right_op operand.
+    __ andi(scratch, ToRegister(right_op), Operand(0x1F));
+    switch (instr->op()) {
+      case Token::SAR:
+        __ sraw(result, left, scratch);
+#if V8_TARGET_ARCH_PPC64
+        __ extsw(result, result);
+#endif
+        break;
+      case Token::SHR:
+        if (instr->can_deopt()) {
+          __ srw(result, left, scratch, SetRC);
+#if V8_TARGET_ARCH_PPC64
+          __ extsw(result, result, SetRC);
+#endif
+          DeoptimizeIf(lt, instr->environment(), cr0);
+        } else {
+          __ srw(result, left, scratch);
+        }
+        break;
+      case Token::SHL:
+        __ slw(result, left, scratch);
+#if V8_TARGET_ARCH_PPC64
+        __ extsw(result, result);
+#endif
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  } else {
+    // Mask the right_op operand.
+    int value = ToInteger32(LConstantOperand::cast(right_op));
+    uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
+    switch (instr->op()) {
+      case Token::SAR:
+        if (shift_count != 0) {
+          __ srawi(result, left, shift_count);
+#if V8_TARGET_ARCH_PPC64
+          __ extsw(result, result);
+#endif
+        } else {
+          __ Move(result, left);
+        }
+        break;
+      case Token::SHR:
+        if (shift_count != 0) {
+          __ srwi(result, left, Operand(shift_count));
+        } else {
+          if (instr->can_deopt()) {
+            __ TestSignBit32(left, r0);
+            DeoptimizeIf(ne, instr->environment(), cr0);
+          }
+          __ Move(result, left);
+        }
+        break;
+      case Token::SHL:
+        if (shift_count != 0) {
+          __ slwi(result, left, Operand(shift_count));
+#if V8_TARGET_ARCH_PPC64
+          __ extsw(result, result);
+#endif
+        } else {
+          __ Move(result, left);
+        }
+        break;
+      default:
+        UNREACHABLE();
+        break;
+    }
+  }
+}
+
+
+void LCodeGen::DoSubI(LSubI* instr) {
+  LOperand* left = instr->left();
+  LOperand* right = instr->right();
+  LOperand* result = instr->result();
+  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+  if (!can_overflow && right->IsConstantOperand()) {
+    if (is_int16(ToInteger32(LConstantOperand::cast(right)))) {
+      __ subi(ToRegister(result), ToRegister(left),
+              Operand(ToInteger32(LConstantOperand::cast(right))));
+      return;
+    }
+  }
+  Register right_reg = EmitLoadRegister(right, ip);
+
+  if (!can_overflow) {
+    __ sub(ToRegister(result), ToRegister(left), right_reg);
+  } else {
+    __ SubAndCheckForOverflow(ToRegister(result),
+                              ToRegister(left),
+                              right_reg,
+                              scratch0(), r0);
+    // Doptimize on overflow
+#if V8_TARGET_ARCH_PPC64
+    __ extsw(scratch0(), scratch0(), SetRC);
+#endif
+    DeoptimizeIf(lt, instr->environment(), cr0);
+  }
+}
+
+
+void LCodeGen::DoConstantI(LConstantI* instr) {
+  ASSERT(instr->result()->IsRegister());
+  __ mov(ToRegister(instr->result()), Operand(instr->value()));
+}
+
+// TODO(penguin): put const to constant pool instead
+// of storing double to stack
+void LCodeGen::DoConstantD(LConstantD* instr) {
+  ASSERT(instr->result()->IsDoubleRegister());
+  DwVfpRegister result = ToDoubleRegister(instr->result());
+  double v = instr->value();
+  __ LoadDoubleLiteral(result, v, scratch0());
+}
+
+void LCodeGen::DoConstantT(LConstantT* instr) {
+  Handle<Object> value = instr->value();
+  if (value->IsSmi()) {
+    __ mov(ToRegister(instr->result()), Operand(value));
+  } else {
+    __ LoadHeapObject(ToRegister(instr->result()),
+                      Handle<HeapObject>::cast(value));
+  }
+}
+
+
+void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
+  Register result = ToRegister(instr->result());
+  Register array = ToRegister(instr->value());
+  __ LoadP(result, FieldMemOperand(array, JSArray::kLengthOffset));
+}
+
+
+void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) {
+  Register result = ToRegister(instr->result());
+  Register array = ToRegister(instr->value());
+  __ LoadP(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset));
+}
+
+
+void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) {
+  Register result = ToRegister(instr->result());
+  Register map = ToRegister(instr->value());
+  __ EnumLength(result, map);
+}
+
+
+void LCodeGen::DoElementsKind(LElementsKind* instr) {
+  Register result = ToRegister(instr->result());
+  Register input = ToRegister(instr->value());
+
+  // Load map into |result|.
+  __ LoadP(result, FieldMemOperand(input, HeapObject::kMapOffset));
+  // Load the map's "bit field 2" into |result|
+  __ lbz(result, FieldMemOperand(result, Map::kBitField2Offset));
+  // Retrieve elements_kind from bit field 2.
+  __ ExtractBitMask(result, result, Map::kElementsKindMask);
+}
+
+
+void LCodeGen::DoValueOf(LValueOf* instr) {
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  Register map = ToRegister(instr->temp());
+  Label done, is_smi_or_object;
+
+  // If the object is a smi return the object.
+  __ JumpIfSmi(input, &is_smi_or_object);
+
+  // If the object is not a value type, return the object.
+  __ CompareObjectType(input, map, map, JS_VALUE_TYPE);
+  __ bne(&is_smi_or_object);
+
+  __ LoadP(result, FieldMemOperand(input, JSValue::kValueOffset));
+  __ b(&done);
+
+  __ bind(&is_smi_or_object);
+  __ Move(result, input);
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoDateField(LDateField* instr) {
+  Register object = ToRegister(instr->date());
+  Register result = ToRegister(instr->result());
+  Register scratch = ToRegister(instr->temp());
+  Smi* index = instr->index();
+  Label runtime, done;
+  ASSERT(object.is(result));
+  ASSERT(object.is(r3));
+  ASSERT(!scratch.is(scratch0()));
+  ASSERT(!scratch.is(object));
+
+  __ TestIfSmi(object, r0);
+  DeoptimizeIf(eq, instr->environment(), cr0);
+  __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
+  DeoptimizeIf(ne, instr->environment());
+
+  if (index->value() == 0) {
+    __ LoadP(result, FieldMemOperand(object, JSDate::kValueOffset));
+  } else {
+    if (index->value() < JSDate::kFirstUncachedField) {
+      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
+      __ mov(scratch, Operand(stamp));
+      __ LoadP(scratch, MemOperand(scratch));
+      __ LoadP(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
+      __ cmp(scratch, scratch0());
+      __ bne(&runtime);
+      __ LoadP(result, FieldMemOperand(object, JSDate::kValueOffset +
+                                       kPointerSize * index->value()));
+      __ b(&done);
+    }
+    __ bind(&runtime);
+    __ PrepareCallCFunction(2, scratch);
+    __ LoadSmiLiteral(r4, index);
+    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
+    __ bind(&done);
+  }
+}
+
+
+void LCodeGen::DoBitNotI(LBitNotI* instr) {
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  __ notx(result, input);
+}
+
+
+void LCodeGen::DoThrow(LThrow* instr) {
+  Register input_reg = EmitLoadRegister(instr->value(), ip);
+  __ push(input_reg);
+  CallRuntime(Runtime::kThrow, 1, instr);
+
+  if (FLAG_debug_code) {
+    __ stop("Unreachable code.");
+  }
+}
+
+
+void LCodeGen::DoAddI(LAddI* instr) {
+  LOperand* left = instr->left();
+  LOperand* right = instr->right();
+  LOperand* result = instr->result();
+  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+
+  if (!can_overflow && right->IsConstantOperand()) {
+    if (is_int16(ToInteger32(LConstantOperand::cast(right)))) {
+      __ addi(ToRegister(result), ToRegister(left),
+              Operand(ToInteger32(LConstantOperand::cast(right))));
+      return;
+    }
+  }
+
+  if (!can_overflow) {
+    Register right_reg = EmitLoadRegister(right, ip);
+    __ add(ToRegister(result), ToRegister(left), right_reg);
+  } else {  // can_overflow.
+    Register right_reg = EmitLoadRegister(right, ip);
+    __ AddAndCheckForOverflow(ToRegister(result),
+                              ToRegister(left),
+                              right_reg,
+                              scratch0(), r0);
+#if V8_TARGET_ARCH_PPC64
+    __ extsw(scratch0(), scratch0(), SetRC);
+#endif
+    // Doptimize on overflow
+    DeoptimizeIf(lt, instr->environment(), cr0);
+  }
+}
+
+
+void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
+  LOperand* left = instr->left();
+  LOperand* right = instr->right();
+  HMathMinMax::Operation operation = instr->hydrogen()->operation();
+  Condition cond = (operation == HMathMinMax::kMathMin) ? le : ge;
+  if (instr->hydrogen()->representation().IsInteger32()) {
+    Register left_reg = ToRegister(left);
+    Register right_reg = EmitLoadRegister(right, ip);
+    Register result_reg = ToRegister(instr->result());
+    Label return_left, done;
+    __ cmp(left_reg, right_reg);
+    __ b(cond, &return_left);
+    __ Move(result_reg, right_reg);
+    __ b(&done);
+    __ bind(&return_left);
+    __ Move(result_reg, left_reg);
+    __ bind(&done);
+  } else {
+    ASSERT(instr->hydrogen()->representation().IsDouble());
+    DoubleRegister left_reg = ToDoubleRegister(left);
+    DoubleRegister right_reg = ToDoubleRegister(right);
+    DoubleRegister result_reg = ToDoubleRegister(instr->result());
+    Label check_nan_left, check_zero, return_left, return_right, done;
+    __ fcmpu(left_reg, right_reg);
+    __ bunordered(&check_nan_left);
+    __ beq(&check_zero);
+    __ b(cond, &return_left);
+    __ b(&return_right);
+
+    __ bind(&check_zero);
+    __ fcmpu(left_reg, kDoubleRegZero);
+    __ bne(&return_left);  // left == right != 0.
+
+    // At this point, both left and right are either 0 or -0.
+    // N.B. The following works because +0 + -0 == +0
+    if (operation == HMathMinMax::kMathMin) {
+      // For min we want logical-or of sign bit: -(-L + -R)
+      __ fneg(left_reg, left_reg);
+      __ fsub(result_reg, left_reg, right_reg);
+      __ fneg(result_reg, result_reg);
+    } else {
+      // For max we want logical-and of sign bit: (L + R)
+      __ fadd(result_reg, left_reg, right_reg);
+    }
+    __ b(&done);
+
+    __ bind(&check_nan_left);
+    __ fcmpu(left_reg, left_reg);
+    __ bunordered(&return_left);  // left == NaN.
+
+    __ bind(&return_right);
+    if (!right_reg.is(result_reg)) {
+      __ fmr(result_reg, right_reg);
+    }
+    __ b(&done);
+
+    __ bind(&return_left);
+    if (!left_reg.is(result_reg)) {
+      __ fmr(result_reg, left_reg);
+    }
+    __ bind(&done);
+  }
+}
+
+
+void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
+  DoubleRegister left = ToDoubleRegister(instr->left());
+  DoubleRegister right = ToDoubleRegister(instr->right());
+  DoubleRegister result = ToDoubleRegister(instr->result());
+  switch (instr->op()) {
+    case Token::ADD:
+      __ fadd(result, left, right);
+      break;
+    case Token::SUB:
+      __ fsub(result, left, right);
+      break;
+    case Token::MUL:
+      __ fmul(result, left, right);
+      break;
+    case Token::DIV:
+      __ fdiv(result, left, right);
+      break;
+    case Token::MOD: {
+      // Save r3-r6 on the stack.
+      __ MultiPush(r3.bit() | r4.bit() | r5.bit() | r6.bit());
+
+      __ PrepareCallCFunction(0, 2, scratch0());
+      __ SetCallCDoubleArguments(left, right);
+      __ CallCFunction(
+          ExternalReference::double_fp_operation(Token::MOD, isolate()),
+          0, 2);
+      // Move the result in the double result register.
+      __ GetCFunctionDoubleResult(result);
+
+      // Restore r3-r6.
+      __ MultiPop(r3.bit() | r4.bit() | r5.bit() | r6.bit());
+      break;
+    }
+    default:
+      UNREACHABLE();
+      break;
+  }
+}
+
+
+void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
+  ASSERT(ToRegister(instr->left()).is(r4));
+  ASSERT(ToRegister(instr->right()).is(r3));
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  BinaryOpStub stub(instr->op(), NO_OVERWRITE);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  __ nop();  // Signals no inlined code.
+}
+
+
+int LCodeGen::GetNextEmittedBlock(int block) {
+  for (int i = block + 1; i < graph()->blocks()->length(); ++i) {
+    LLabel* label = chunk_->GetLabel(i);
+    if (!label->HasReplacement()) return i;
+  }
+  return -1;
+}
+
+
+void LCodeGen::EmitBranch(int left_block, int right_block, Condition cond,
+                          CRegister cr) {
+  int next_block = GetNextEmittedBlock(current_block_);
+  right_block = chunk_->LookupDestination(right_block);
+  left_block = chunk_->LookupDestination(left_block);
+
+  if (right_block == left_block) {
+    EmitGoto(left_block);
+  } else if (left_block == next_block) {
+    __ b(NegateCondition(cond), chunk_->GetAssemblyLabel(right_block), cr);
+  } else if (right_block == next_block) {
+    __ b(cond, chunk_->GetAssemblyLabel(left_block), cr);
+  } else {
+    __ b(cond, chunk_->GetAssemblyLabel(left_block), cr);
+    __ b(chunk_->GetAssemblyLabel(right_block));
+  }
+}
+
+
+void LCodeGen::DoBranch(LBranch* instr) {
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  Representation r = instr->hydrogen()->value()->representation();
+  if (r.IsInteger32()) {
+    Register reg = ToRegister(instr->value());
+    __ cmpi(reg, Operand::Zero());
+    EmitBranch(true_block, false_block, ne);
+  } else if (r.IsDouble()) {
+    DoubleRegister reg = ToDoubleRegister(instr->value());
+    Register scratch = scratch0();
+
+    // Test the double value. Zero and NaN are false.
+    uint crBits = (1 << (31 - Assembler::encode_crbit(cr7, CR_EQ)) |
+                   1 << (31 - Assembler::encode_crbit(cr7, CR_FU)));
+    __ fcmpu(reg, kDoubleRegZero, cr7);
+    __ mfcr(scratch);
+    __ andi(scratch, scratch, Operand(crBits));
+    EmitBranch(true_block, false_block, eq, cr0);
+  } else {
+    ASSERT(r.IsTagged());
+    Register reg = ToRegister(instr->value());
+    HType type = instr->hydrogen()->value()->type();
+    if (type.IsBoolean()) {
+      __ CompareRoot(reg, Heap::kTrueValueRootIndex);
+      EmitBranch(true_block, false_block, eq);
+    } else if (type.IsSmi()) {
+      __ cmpi(reg, Operand::Zero());
+      EmitBranch(true_block, false_block, ne);
+    } else {
+      Label* true_label = chunk_->GetAssemblyLabel(true_block);
+      Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+      ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
+      // Avoid deopts in the case where we've never executed this path before.
+      if (expected.IsEmpty()) expected = ToBooleanStub::all_types();
+
+      if (expected.Contains(ToBooleanStub::UNDEFINED)) {
+        // undefined -> false.
+        __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
+        __ beq(false_label);
+      }
+      if (expected.Contains(ToBooleanStub::BOOLEAN)) {
+        // Boolean -> its value.
+        __ CompareRoot(reg, Heap::kTrueValueRootIndex);
+        __ beq(true_label);
+        __ CompareRoot(reg, Heap::kFalseValueRootIndex);
+        __ beq(false_label);
+      }
+      if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
+        // 'null' -> false.
+        __ CompareRoot(reg, Heap::kNullValueRootIndex);
+        __ beq(false_label);
+      }
+
+      if (expected.Contains(ToBooleanStub::SMI)) {
+        // Smis: 0 -> false, all other -> true.
+        __ cmpi(reg, Operand::Zero());
+        __ beq(false_label);
+        __ JumpIfSmi(reg, true_label);
+      } else if (expected.NeedsMap()) {
+        // If we need a map later and have a Smi -> deopt.
+        __ TestIfSmi(reg, r0);
+        DeoptimizeIf(eq, instr->environment(), cr0);
+      }
+
+      const Register map = scratch0();
+      if (expected.NeedsMap()) {
+        __ LoadP(map, FieldMemOperand(reg, HeapObject::kMapOffset));
+
+        if (expected.CanBeUndetectable()) {
+          // Undetectable -> false.
+          __ lbz(ip, FieldMemOperand(map, Map::kBitFieldOffset));
+          __ TestBit(ip, Map::kIsUndetectable, r0);
+          __ bne(false_label, cr0);
+        }
+      }
+
+      if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
+        // spec object -> true.
+        __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
+        __ bge(true_label);
+      }
+
+      if (expected.Contains(ToBooleanStub::STRING)) {
+        // String value -> false iff empty.
+        Label not_string;
+        __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
+        __ bge(&not_string);
+        __ LoadP(ip, FieldMemOperand(reg, String::kLengthOffset));
+        __ cmpi(ip, Operand::Zero());
+        __ bne(true_label);
+        __ b(false_label);
+        __ bind(&not_string);
+      }
+
+      if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
+        // heap number -> false iff +0, -0, or NaN.
+        DoubleRegister dbl_scratch = double_scratch0();
+        Label not_heap_number;
+        __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+        __ bne(&not_heap_number);
+        __ lfd(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
+        __ fcmpu(dbl_scratch, kDoubleRegZero);
+        __ bunordered(false_label);  // NaN -> false.
+        __ beq(false_label);  // +0, -0 -> false.
+        __ b(true_label);
+        __ bind(&not_heap_number);
+      }
+
+      // We've seen something for the first time -> deopt.
+      DeoptimizeIf(al, instr->environment());
+    }
+  }
+}
+
+
+void LCodeGen::EmitGoto(int block) {
+  block = chunk_->LookupDestination(block);
+  int next_block = GetNextEmittedBlock(current_block_);
+  if (block != next_block) {
+    __ b(chunk_->GetAssemblyLabel(block));
+  }
+}
+
+
+void LCodeGen::DoGoto(LGoto* instr) {
+  EmitGoto(instr->block_id());
+}
+
+
+Condition LCodeGen::TokenToCondition(Token::Value op) {
+  Condition cond = kNoCondition;
+  switch (op) {
+    case Token::EQ:
+    case Token::EQ_STRICT:
+      cond = eq;
+      break;
+    case Token::LT:
+      cond =  lt;
+      break;
+    case Token::GT:
+      cond = gt;
+      break;
+    case Token::LTE:
+      cond = le;
+      break;
+    case Token::GTE:
+      cond = ge;
+      break;
+    case Token::IN:
+    case Token::INSTANCEOF:
+    default:
+      UNREACHABLE();
+  }
+  return cond;
+}
+
+
+void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
+  LOperand* left = instr->left();
+  LOperand* right = instr->right();
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  Condition cond = TokenToCondition(instr->op());
+
+  if (left->IsConstantOperand() && right->IsConstantOperand()) {
+    // We can statically evaluate the comparison.
+    double left_val = ToDouble(LConstantOperand::cast(left));
+    double right_val = ToDouble(LConstantOperand::cast(right));
+    int next_block =
+      EvalComparison(instr->op(), left_val, right_val) ? true_block
+                                                       : false_block;
+    EmitGoto(next_block);
+  } else {
+    if (instr->is_double()) {
+      // Compare left and right operands as doubles and load the
+      // resulting flags into the normal status register.
+      __ fcmpu(ToDoubleRegister(left), ToDoubleRegister(right));
+      // If a NaN is involved, i.e. the result is unordered,
+      // jump to false block label.
+      __ bunordered(chunk_->GetAssemblyLabel(false_block));
+    } else {
+      if (right->IsConstantOperand()) {
+        __ Cmpi(ToRegister(left),
+                Operand(ToInteger32(LConstantOperand::cast(right))), r0);
+      } else if (left->IsConstantOperand()) {
+        __ Cmpi(ToRegister(right),
+                Operand(ToInteger32(LConstantOperand::cast(left))), r0);
+        // We transposed the operands. Reverse the condition.
+        cond = ReverseCondition(cond);
+      } else {
+        __ cmp(ToRegister(left), ToRegister(right));
+      }
+    }
+    EmitBranch(true_block, false_block, cond);
+  }
+}
+
+
+void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
+  Register left = ToRegister(instr->left());
+  Register right = ToRegister(instr->right());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+
+  __ cmp(left, right);
+  EmitBranch(true_block, false_block, eq);
+}
+
+
+void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
+  Register left = ToRegister(instr->left());
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  __ Cmpi(left, Operand(instr->hydrogen()->right()), r0);
+  EmitBranch(true_block, false_block, eq);
+}
+
+
+void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) {
+  Register scratch = scratch0();
+  Register reg = ToRegister(instr->value());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  // If the expression is known to be untagged or a smi, then it's definitely
+  // not null, and it can't be a an undetectable object.
+  if (instr->hydrogen()->representation().IsSpecialization() ||
+      instr->hydrogen()->type().IsSmi()) {
+    EmitGoto(false_block);
+    return;
+  }
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  Heap::RootListIndex nil_value = instr->nil() == kNullValue ?
+      Heap::kNullValueRootIndex :
+      Heap::kUndefinedValueRootIndex;
+  __ LoadRoot(ip, nil_value);
+  __ cmp(reg, ip);
+  if (instr->kind() == kStrictEquality) {
+    EmitBranch(true_block, false_block, eq);
+  } else {
+    Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ?
+        Heap::kUndefinedValueRootIndex :
+        Heap::kNullValueRootIndex;
+    Label* true_label = chunk_->GetAssemblyLabel(true_block);
+    Label* false_label = chunk_->GetAssemblyLabel(false_block);
+    __ beq(true_label);
+    __ LoadRoot(ip, other_nil_value);
+    __ cmp(reg, ip);
+    __ beq(true_label);
+    __ JumpIfSmi(reg, false_label);
+    // Check for undetectable objects by looking in the bit field in
+    // the map. The object has already been smi checked.
+    __ LoadP(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
+    __ lbz(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
+    __ TestBit(scratch, Map::kIsUndetectable, r0);
+    EmitBranch(true_block, false_block, ne, cr0);
+  }
+}
+
+
+Condition LCodeGen::EmitIsObject(Register input,
+                                 Register temp1,
+                                 Label* is_not_object,
+                                 Label* is_object) {
+  Register temp2 = scratch0();
+  __ JumpIfSmi(input, is_not_object);
+
+  __ LoadRoot(temp2, Heap::kNullValueRootIndex);
+  __ cmp(input, temp2);
+  __ beq(is_object);
+
+  // Load map.
+  __ LoadP(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
+  // Undetectable objects behave like undefined.
+  __ lbz(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
+  __ TestBit(temp2, Map::kIsUndetectable, r0);
+  __ bne(is_not_object, cr0);
+
+  // Load instance type and check that it is in object type range.
+  __ lbz(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
+  __ cmpi(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+  __ blt(is_not_object);
+  __ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
+  return le;
+}
+
+
+void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
+  Register reg = ToRegister(instr->value());
+  Register temp1 = ToRegister(instr->temp());
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+  Label* true_label = chunk_->GetAssemblyLabel(true_block);
+  Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+  Condition true_cond =
+      EmitIsObject(reg, temp1, false_label, true_label);
+
+  EmitBranch(true_block, false_block, true_cond);
+}
+
+
+Condition LCodeGen::EmitIsString(Register input,
+                                 Register temp1,
+                                 Label* is_not_string) {
+  __ JumpIfSmi(input, is_not_string);
+  __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE);
+
+  return lt;
+}
+
+
+void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
+  Register reg = ToRegister(instr->value());
+  Register temp1 = ToRegister(instr->temp());
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+  Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+  Condition true_cond =
+      EmitIsString(reg, temp1, false_label);
+
+  EmitBranch(true_block, false_block, true_cond);
+}
+
+
+void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  Register input_reg = EmitLoadRegister(instr->value(), ip);
+  __ TestIfSmi(input_reg, r0);
+  EmitBranch(true_block, false_block, eq, cr0);
+}
+
+
+void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
+  Register input = ToRegister(instr->value());
+  Register temp = ToRegister(instr->temp());
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
+  __ LoadP(temp, FieldMemOperand(input, HeapObject::kMapOffset));
+  __ lbz(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
+  __ TestBit(temp, Map::kIsUndetectable, r0);
+  EmitBranch(true_block, false_block, ne, cr0);
+}
+
+
+static Condition ComputeCompareCondition(Token::Value op) {
+  switch (op) {
+    case Token::EQ_STRICT:
+    case Token::EQ:
+      return eq;
+    case Token::LT:
+      return lt;
+    case Token::GT:
+      return gt;
+    case Token::LTE:
+      return le;
+    case Token::GTE:
+      return ge;
+    default:
+      UNREACHABLE();
+      return kNoCondition;
+  }
+}
+
+
+void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
+  Token::Value op = instr->op();
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  Handle<Code> ic = CompareIC::GetUninitialized(op);
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+  // This instruction also signals no smi code inlined
+  __ cmpi(r3, Operand::Zero());
+
+  Condition condition = ComputeCompareCondition(op);
+
+  EmitBranch(true_block, false_block, condition);
+}
+
+
+static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
+  InstanceType from = instr->from();
+  InstanceType to = instr->to();
+  if (from == FIRST_TYPE) return to;
+  ASSERT(from == to || to == LAST_TYPE);
+  return from;
+}
+
+
+static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
+  InstanceType from = instr->from();
+  InstanceType to = instr->to();
+  if (from == to) return eq;
+  if (to == LAST_TYPE) return ge;
+  if (from == FIRST_TYPE) return le;
+  UNREACHABLE();
+  return eq;
+}
+
+
+void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
+  Register scratch = scratch0();
+  Register input = ToRegister(instr->value());
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+  __ JumpIfSmi(input, false_label);
+
+  __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
+  EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
+}
+
+
+void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+
+  __ AssertString(input);
+
+  __ lwz(result, FieldMemOperand(input, String::kHashFieldOffset));
+  __ IndexFromHash(result, result);
+}
+
+
+void LCodeGen::DoHasCachedArrayIndexAndBranch(
+    LHasCachedArrayIndexAndBranch* instr) {
+  Register input = ToRegister(instr->value());
+  Register scratch = scratch0();
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  __ lwz(scratch,
+         FieldMemOperand(input, String::kHashFieldOffset));
+  __ mov(r0, Operand(String::kContainsCachedArrayIndexMask));
+  __ and_(r0, scratch, r0, SetRC);
+  EmitBranch(true_block, false_block, eq, cr0);
+}
+
+
+// Branches to a label or falls through with the answer in flags.  Trashes
+// the temp registers, but not the input.
+void LCodeGen::EmitClassOfTest(Label* is_true,
+                               Label* is_false,
+                               Handle<String>class_name,
+                               Register input,
+                               Register temp,
+                               Register temp2) {
+  ASSERT(!input.is(temp));
+  ASSERT(!input.is(temp2));
+  ASSERT(!temp.is(temp2));
+
+  __ JumpIfSmi(input, is_false);
+
+  if (class_name->IsEqualTo(CStrVector("Function"))) {
+    // Assuming the following assertions, we can use the same compares to test
+    // for both being a function type and being in the object type range.
+    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
+    STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
+                  FIRST_SPEC_OBJECT_TYPE + 1);
+    STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
+                  LAST_SPEC_OBJECT_TYPE - 1);
+    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
+    __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE);
+    __ blt(is_false);
+    __ beq(is_true);
+    __ cmpi(temp2, Operand(LAST_SPEC_OBJECT_TYPE));
+    __ beq(is_true);
+  } else {
+    // Faster code path to avoid two compares: subtract lower bound from the
+    // actual type and do a signed compare with the width of the type range.
+    __ LoadP(temp, FieldMemOperand(input, HeapObject::kMapOffset));
+    __ lbz(temp2, FieldMemOperand(temp, Map::kInstanceTypeOffset));
+    __ subi(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+    __ cmpi(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
+                          FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+    __ bgt(is_false);
+  }
+
+  // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
+  // Check if the constructor in the map is a function.
+  __ LoadP(temp, FieldMemOperand(temp, Map::kConstructorOffset));
+
+  // Objects with a non-function constructor have class 'Object'.
+  __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE);
+  if (class_name->IsEqualTo(CStrVector("Object"))) {
+    __ bne(is_true);
+  } else {
+    __ bne(is_false);
+  }
+
+  // temp now contains the constructor function. Grab the
+  // instance class name from there.
+  __ LoadP(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(temp, FieldMemOperand(temp,
+                                 SharedFunctionInfo::kInstanceClassNameOffset));
+  // The class name we are testing against is a symbol because it's a literal.
+  // The name in the constructor is a symbol because of the way the context is
+  // booted.  This routine isn't expected to work for random API-created
+  // classes and it doesn't have to because you can't access it with natives
+  // syntax.  Since both sides are symbols it is sufficient to use an identity
+  // comparison.
+  __ Cmpi(temp, Operand(class_name), r0);
+  // End with the answer in flags.
+}
+
+
+void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
+  Register input = ToRegister(instr->value());
+  Register temp = scratch0();
+  Register temp2 = ToRegister(instr->temp());
+  Handle<String> class_name = instr->hydrogen()->class_name();
+
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  Label* true_label = chunk_->GetAssemblyLabel(true_block);
+  Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+  EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
+
+  EmitBranch(true_block, false_block, eq);
+}
+
+
+void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
+  Register reg = ToRegister(instr->value());
+  Register temp = ToRegister(instr->temp());
+  int true_block = instr->true_block_id();
+  int false_block = instr->false_block_id();
+
+  __ LoadP(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
+  __ Cmpi(temp, Operand(instr->map()), r0);
+  EmitBranch(true_block, false_block, eq);
+}
+
+
+void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
+  ASSERT(ToRegister(instr->left()).is(r3));  // Object is in r3.
+  ASSERT(ToRegister(instr->right()).is(r4));  // Function is in r4.
+
+  InstanceofStub stub(InstanceofStub::kArgsInRegisters);
+  Label equal, done;
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+
+  __ cmpi(r3, Operand::Zero());
+  __ beq(&equal);
+  __ mov(r3, Operand(factory()->false_value()));
+  __ b(&done);
+
+  __ bind(&equal);
+  __ mov(r3, Operand(factory()->true_value()));
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
+  class DeferredInstanceOfKnownGlobal: public LDeferredCode {
+   public:
+    DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
+                                  LInstanceOfKnownGlobal* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() {
+      codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
+    }
+    virtual LInstruction* instr() { return instr_; }
+    Label* map_check() { return &map_check_; }
+   private:
+    LInstanceOfKnownGlobal* instr_;
+    Label map_check_;
+  };
+
+  DeferredInstanceOfKnownGlobal* deferred;
+  deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr);
+
+  Label done, false_result;
+  Register object = ToRegister(instr->value());
+  Register temp = ToRegister(instr->temp());
+  Register result = ToRegister(instr->result());
+
+  ASSERT(object.is(r3));
+  ASSERT(result.is(r3));
+
+  // A Smi is not instance of anything.
+  __ JumpIfSmi(object, &false_result);
+
+  // This is the inlined call site instanceof cache. The two occurences of the
+  // hole value will be patched to the last map/result pair generated by the
+  // instanceof stub.
+  Label cache_miss;
+  Register map = temp;
+  __ LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
+  {
+    // Block constant pool emission to ensure the positions of instructions are
+    // as expected by the patcher. See InstanceofStub::Generate().
+    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
+    __ bind(deferred->map_check());  // Label for calculating code patching.
+    // We use Factory::the_hole_value() on purpose instead of loading from the
+    // root array to force relocation to be able to later patch with
+    // the cached map.
+    Handle<JSGlobalPropertyCell> cell =
+        factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
+    __ mov(ip, Operand(Handle<Object>(cell)));
+    __ LoadP(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
+    __ cmp(map, ip);
+    __ bne(&cache_miss);
+    // We use Factory::the_hole_value() on purpose instead of loading from the
+    // root array to force relocation to be able to later patch
+    // with true or false.
+    __ mov(result, Operand(factory()->the_hole_value()));
+  }
+  __ b(&done);
+
+  // The inlined call site cache did not match. Check null and string before
+  // calling the deferred code.
+  __ bind(&cache_miss);
+  // Null is not instance of anything.
+  __ LoadRoot(ip, Heap::kNullValueRootIndex);
+  __ cmp(object, ip);
+  __ beq(&false_result);
+
+  // String values is not instance of anything.
+  Condition is_string = masm_->IsObjectStringType(object, temp);
+  __ b(is_string, &false_result, cr0);
+
+  // Go to the deferred code.
+  __ b(deferred->entry());
+
+  __ bind(&false_result);
+  __ LoadRoot(result, Heap::kFalseValueRootIndex);
+
+  // Here result has either true or false. Deferred code also produces true or
+  // false object.
+  __ bind(deferred->exit());
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+                                               Label* map_check) {
+  Register result = ToRegister(instr->result());
+  ASSERT(result.is(r3));
+
+  InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
+  flags = static_cast<InstanceofStub::Flags>(
+      flags | InstanceofStub::kArgsInRegisters);
+  flags = static_cast<InstanceofStub::Flags>(
+      flags | InstanceofStub::kCallSiteInlineCheck);
+  flags = static_cast<InstanceofStub::Flags>(
+      flags | InstanceofStub::kReturnTrueFalseObject);
+  InstanceofStub stub(flags);
+
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+
+  // Get the temp register reserved by the instruction. This needs to be r7 as
+  // its slot of the pushing of safepoint registers is used to communicate the
+  // offset to the location of the map check.
+  Register temp = ToRegister(instr->temp());
+  ASSERT(temp.is(r7));
+  __ LoadHeapObject(InstanceofStub::right(), instr->function());
+#if V8_TARGET_ARCH_PPC64
+  static const int kAdditionalDelta = 13;
+#else
+  static const int kAdditionalDelta = 7;
+#endif
+  int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
+  Label before_push_delta;
+  __ bind(&before_push_delta);
+  {
+    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
+    __ mov(temp, Operand(delta * Instruction::kInstrSize));
+    __ StoreToSafepointRegisterSlot(temp, temp);
+  }
+  CallCodeGeneric(stub.GetCode(),
+                  RelocInfo::CODE_TARGET,
+                  instr,
+                  RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+  ASSERT(delta == masm_->InstructionsGeneratedSince(map_check));
+  LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
+  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
+  // Put the result value into the result register slot and
+  // restore all registers.
+  __ StoreToSafepointRegisterSlot(result, result);
+}
+
+
+void LCodeGen::DoCmpT(LCmpT* instr) {
+  Token::Value op = instr->op();
+
+  Handle<Code> ic = CompareIC::GetUninitialized(op);
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+  // This instruction also signals no smi code inlined
+  __ cmpi(r3, Operand::Zero());
+
+  Condition condition = ComputeCompareCondition(op);
+  Label true_value, done;
+
+  __ b(condition, &true_value);
+
+  __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
+  __ b(&done);
+
+  __ bind(&true_value);
+  __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoReturn(LReturn* instr) {
+  if (FLAG_trace) {
+    // Push the return value on the stack as the parameter.
+    // Runtime::TraceExit returns its parameter in r3.
+    __ push(r3);
+    __ CallRuntime(Runtime::kTraceExit, 1);
+  }
+  int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize;
+  __ mr(sp, fp);
+  __ Pop(r0, fp);
+  __ mtlr(r0);
+  __ addi(sp, sp, Operand(sp_delta));
+  __ blr();
+}
+
+
+void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
+  Register result = ToRegister(instr->result());
+  __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
+  __ LoadP(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+    __ cmp(result, ip);
+    DeoptimizeIf(eq, instr->environment());
+  }
+}
+
+
+void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
+  ASSERT(ToRegister(instr->global_object()).is(r3));
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  __ mov(r5, Operand(instr->name()));
+  RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET
+                                             : RelocInfo::CODE_TARGET_CONTEXT;
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+  CallCode(ic, mode, instr);
+}
+
+
+void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
+  Register value = ToRegister(instr->value());
+  Register cell = scratch0();
+
+  // Load the cell.
+  __ mov(cell, Operand(instr->hydrogen()->cell()));
+
+  // If the cell we are storing to contains the hole it could have
+  // been deleted from the property dictionary. In that case, we need
+  // to update the property details in the property dictionary to mark
+  // it as no longer deleted.
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    // We use a temp to check the payload (CompareRoot might clobber ip).
+    Register payload = ToRegister(instr->temp());
+    __ LoadP(payload,
+             FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
+    __ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
+    DeoptimizeIf(eq, instr->environment());
+  }
+
+  // Store the value.
+  __ StoreP(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset),
+            r0);
+  // Cells are always rescanned, so no write barrier here.
+}
+
+
+void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
+  ASSERT(ToRegister(instr->global_object()).is(r4));
+  ASSERT(ToRegister(instr->value()).is(r3));
+
+  __ mov(r5, Operand(instr->name()));
+  Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
+  CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
+}
+
+
+void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
+  Register context = ToRegister(instr->context());
+  Register result = ToRegister(instr->result());
+  __ LoadP(result, ContextOperand(context, instr->slot_index()));
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+    __ cmp(result, ip);
+    if (instr->hydrogen()->DeoptimizesOnHole()) {
+      DeoptimizeIf(eq, instr->environment());
+    } else {
+      Label skip;
+      __ bne(&skip);
+      __ mov(result, Operand(factory()->undefined_value()));
+      __ bind(&skip);
+    }
+  }
+}
+
+
+void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
+  Register context = ToRegister(instr->context());
+  Register value = ToRegister(instr->value());
+  Register scratch = scratch0();
+  MemOperand target = ContextOperand(context, instr->slot_index());
+
+  Label skip_assignment;
+
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    __ LoadP(scratch, target);
+    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+    __ cmp(scratch, ip);
+    if (instr->hydrogen()->DeoptimizesOnHole()) {
+      DeoptimizeIf(eq, instr->environment());
+    } else {
+      __ bne(&skip_assignment);
+    }
+  }
+
+  __ StoreP(value, target, r0);
+  if (instr->hydrogen()->NeedsWriteBarrier()) {
+    HType type = instr->hydrogen()->value()->type();
+    SmiCheck check_needed =
+        type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
+    __ RecordWriteContextSlot(context,
+                              target.offset(),
+                              value,
+                              scratch,
+                              kLRHasBeenSaved,
+                              kSaveFPRegs,
+                              EMIT_REMEMBERED_SET,
+                              check_needed);
+  }
+
+  __ bind(&skip_assignment);
+}
+
+
+void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
+  Register object = ToRegister(instr->object());
+  Register result = ToRegister(instr->result());
+  if (instr->hydrogen()->is_in_object()) {
+    __ LoadP(result, FieldMemOperand(object, instr->hydrogen()->offset()));
+  } else {
+    __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+    __ LoadP(result, FieldMemOperand(result, instr->hydrogen()->offset()));
+  }
+}
+
+
+void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
+                                               Register object,
+                                               Handle<Map> type,
+                                               Handle<String> name,
+                                               LEnvironment* env) {
+  LookupResult lookup(isolate());
+  type->LookupDescriptor(NULL, *name, &lookup);
+  ASSERT(lookup.IsFound() || lookup.IsCacheable());
+  if (lookup.IsField()) {
+    int index = lookup.GetLocalFieldIndexFromMap(*type);
+    int offset = index * kPointerSize;
+    if (index < 0) {
+      // Negative property indices are in-object properties, indexed
+      // from the end of the fixed part of the object.
+      __ LoadP(result, FieldMemOperand(object, offset + type->instance_size()));
+    } else {
+      // Non-negative property indices are in the properties array.
+      __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+      __ LoadP(result,
+               FieldMemOperand(result, offset + FixedArray::kHeaderSize));
+    }
+  } else if (lookup.IsConstantFunction()) {
+    Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
+    __ LoadHeapObject(result, function);
+  } else {
+    // Negative lookup.
+    // Check prototypes.
+    Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
+    Heap* heap = type->GetHeap();
+    while (*current != heap->null_value()) {
+      __ LoadHeapObject(result, current);
+      __ LoadP(result, FieldMemOperand(result, HeapObject::kMapOffset));
+      __ Cmpi(result, Operand(Handle<Map>(current->map())), r0);
+      DeoptimizeIf(ne, env);
+      current =
+          Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
+    }
+    __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
+  }
+}
+
+
+void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
+  Register object = ToRegister(instr->object());
+  Register result = ToRegister(instr->result());
+  Register object_map = scratch0();
+
+  int map_count = instr->hydrogen()->types()->length();
+  bool need_generic = instr->hydrogen()->need_generic();
+
+  if (map_count == 0 && !need_generic) {
+    DeoptimizeIf(al, instr->environment());
+    return;
+  }
+  Handle<String> name = instr->hydrogen()->name();
+  Label done;
+  __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
+  for (int i = 0; i < map_count; ++i) {
+    bool last = (i == map_count - 1);
+    Handle<Map> map = instr->hydrogen()->types()->at(i);
+    Label check_passed;
+    __ CompareMap(
+        object_map, map, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS);
+    if (last && !need_generic) {
+      DeoptimizeIf(ne, instr->environment());
+      __ bind(&check_passed);
+      EmitLoadFieldOrConstantFunction(
+          result, object, map, name, instr->environment());
+    } else {
+      Label next;
+      __ bne(&next);
+      __ bind(&check_passed);
+      EmitLoadFieldOrConstantFunction(
+          result, object, map, name, instr->environment());
+      __ b(&done);
+      __ bind(&next);
+    }
+  }
+  if (need_generic) {
+    __ mov(r5, Operand(name));
+    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+    CallCode(ic, RelocInfo::CODE_TARGET, instr);
+  }
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
+  ASSERT(ToRegister(instr->object()).is(r3));
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  // Name is always in r5.
+  __ mov(r5, Operand(instr->name()));
+  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
+  Register scratch = scratch0();
+  Register function = ToRegister(instr->function());
+  Register result = ToRegister(instr->result());
+
+  // Check that the function really is a function. Load map into the
+  // result register.
+  __ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
+  DeoptimizeIf(ne, instr->environment());
+
+  // Make sure that the function has an instance prototype.
+  Label non_instance;
+  __ lbz(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
+  __ TestBit(scratch, Map::kHasNonInstancePrototype, r0);
+  __ bne(&non_instance, cr0);
+
+  // Get the prototype or initial map from the function.
+  __ LoadP(result,
+           FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // Check that the function has a prototype or an initial map.
+  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  __ cmp(result, ip);
+  DeoptimizeIf(eq, instr->environment());
+
+  // If the function does not have an initial map, we're done.
+  Label done;
+  __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
+  __ bne(&done);
+
+  // Get the prototype from the initial map.
+  __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
+  __ b(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in initial map.
+  __ bind(&non_instance);
+  __ LoadP(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoLoadElements(LLoadElements* instr) {
+  Register result = ToRegister(instr->result());
+  Register input = ToRegister(instr->object());
+  Register scratch = scratch0();
+
+  __ LoadP(result, FieldMemOperand(input, JSObject::kElementsOffset));
+  if (FLAG_debug_code) {
+    Label done, fail;
+    __ LoadP(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
+    __ cmp(scratch, ip);
+    __ beq(&done);
+    __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
+    __ cmp(scratch, ip);
+    __ beq(&done);
+    // |scratch| still contains |input|'s map.
+    __ lbz(scratch, FieldMemOperand(scratch, Map::kBitField2Offset));
+    __ ExtractBitMask(scratch, scratch, Map::kElementsKindMask);
+    __ cmpi(scratch, Operand(GetInitialFastElementsKind()));
+    __ blt(&fail);
+    __ cmpi(scratch, Operand(TERMINAL_FAST_ELEMENTS_KIND));
+    __ ble(&done);
+    __ cmpi(scratch, Operand(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND));
+    __ blt(&fail);
+    __ cmpi(scratch, Operand(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND));
+    __ ble(&done);
+    __ bind(&fail);
+    __ Abort("Check for fast or external elements failed.");
+    __ bind(&done);
+  }
+}
+
+
+void LCodeGen::DoLoadExternalArrayPointer(
+    LLoadExternalArrayPointer* instr) {
+  Register to_reg = ToRegister(instr->result());
+  Register from_reg  = ToRegister(instr->object());
+  __ LoadP(to_reg, FieldMemOperand(from_reg,
+                                   ExternalArray::kExternalPointerOffset));
+}
+
+
+void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
+  Register arguments = ToRegister(instr->arguments());
+  Register length = ToRegister(instr->length());
+  Register index = ToRegister(instr->index());
+  Register result = ToRegister(instr->result());
+
+  // There are two words between the frame pointer and the last argument.
+  // Subtracting from length accounts for one of them add one more.
+  __ sub(length, length, index);
+  __ addi(length, length, Operand(1));
+  __ ShiftLeftImm(r0, length, Operand(kPointerSizeLog2));
+  __ LoadPX(result, MemOperand(arguments, r0));
+}
+
+
+void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
+  Register elements = ToRegister(instr->elements());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+  Register store_base = scratch;
+  int offset = 0;
+
+  if (instr->key()->IsConstantOperand()) {
+    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
+    offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
+                                           instr->additional_index());
+    store_base = elements;
+  } else {
+    Register key = EmitLoadRegister(instr->key(), scratch0());
+    // Even though the HLoadKeyedFastElement instruction forces the input
+    // representation for the key to be an integer, the input gets replaced
+    // during bound check elimination with the index argument to the bounds
+    // check, which can be tagged, so that case must be handled here, too.
+    if (instr->hydrogen()->key()->representation().IsTagged()) {
+      __ SmiToPtrArrayOffset(r0, key);
+    } else {
+      __ ShiftLeftImm(r0, key, Operand(kPointerSizeLog2));
+    }
+    __ add(scratch, elements, r0);
+    offset = FixedArray::OffsetOfElementAt(instr->additional_index());
+  }
+  __ LoadP(result, FieldMemOperand(store_base, offset));
+
+  // Check for the hole value.
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
+      __ TestIfSmi(result, r0);
+      DeoptimizeIf(ne, instr->environment(), cr0);
+    } else {
+      __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
+      __ cmp(result, scratch);
+      DeoptimizeIf(eq, instr->environment());
+    }
+  }
+}
+
+
+void LCodeGen::DoLoadKeyedFastDoubleElement(
+    LLoadKeyedFastDoubleElement* instr) {
+  Register elements = ToRegister(instr->elements());
+  bool key_is_constant = instr->key()->IsConstantOperand();
+  Register key = no_reg;
+  DwVfpRegister result = ToDoubleRegister(instr->result());
+  Register scratch = scratch0();
+
+  int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
+  bool key_is_tagged = instr->hydrogen()->key()->representation().IsTagged();
+  int constant_key = 0;
+  int address_offset = 0;
+  if (key_is_constant) {
+    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+    if (constant_key & 0xF0000000) {
+      Abort("array index constant value too big.");
+    }
+  } else {
+    key = ToRegister(instr->key());
+  }
+
+  if (key_is_constant) {
+    __ Add(elements, elements,
+           (FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
+           ((constant_key + instr->additional_index()) << element_size_shift),
+           r0);
+  } else {
+    __ IndexToArrayOffset(r0, key, element_size_shift, key_is_tagged);
+    __ add(elements, elements, r0);
+    address_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) +
+                     (instr->additional_index() << element_size_shift);
+
+    if (!is_int16((address_offset))) {
+      __ mov(r0, Operand(address_offset));
+      __ add(elements, elements, r0);
+      address_offset = 0;
+    }
+  }
+
+  if (instr->hydrogen()->RequiresHoleCheck()) {
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    if (address_offset) {
+      if (is_int16(address_offset + sizeof(kHoleNanLower32))) {
+        __ lwz(scratch, MemOperand(elements,
+                                   address_offset + sizeof(kHoleNanLower32)));
+      } else {
+        __ li(r0, Operand(address_offset));
+        __ add(scratch, elements, r0);
+        __ lwz(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
+      }
+    } else {
+      __ lwz(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
+    }
+#else
+    __ lwz(scratch, MemOperand(elements, address_offset));
+#endif
+    __ Cmpi(scratch, Operand(kHoleNanUpper32), r0);
+    DeoptimizeIf(eq, instr->environment());
+  }
+
+  __ lfd(result, MemOperand(elements, address_offset));
+}
+
+
+MemOperand LCodeGen::PrepareKeyedOperand(Register key,
+                                         Register base,
+                                         bool key_is_constant,
+                                         bool key_is_tagged,
+                                         int constant_key,
+                                         int element_size_shift,
+                                         int additional_index,
+                                         int additional_offset) {
+  Register scratch = scratch0();
+
+  ASSERT(!(key_is_constant && key_is_tagged));
+
+  if (key_is_constant) {
+    return MemOperand(base,
+                      (constant_key << element_size_shift) + additional_offset);
+  }
+
+  bool needs_shift = (element_size_shift != (key_is_tagged ?
+                                             kSmiTagSize + kSmiShiftSize : 0));
+
+  if (!(additional_index || needs_shift)) {
+      return MemOperand(base, key);
+  }
+
+  if (additional_index) {
+    if (key_is_tagged) {
+#if V8_TARGET_ARCH_PPC64
+      // more efficient to just untag
+      __ SmiUntag(scratch, key);
+      key_is_tagged = false;
+      needs_shift = (element_size_shift != 0);
+      key = scratch;
+#else
+      additional_index <<= kSmiTagSize + kSmiShiftSize;
+#endif
+    }
+
+    __ Add(scratch, key, additional_index, r0);
+    key = scratch;
+  }
+
+  if (needs_shift) {
+    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_tagged);
+  }
+
+  return MemOperand(base, scratch);
+}
+
+
+void LCodeGen::DoLoadKeyedSpecializedArrayElement(
+    LLoadKeyedSpecializedArrayElement* instr) {
+  Register external_pointer = ToRegister(instr->external_pointer());
+  Register key = no_reg;
+  ElementsKind elements_kind = instr->elements_kind();
+  bool key_is_constant = instr->key()->IsConstantOperand();
+  int constant_key = 0;
+  if (key_is_constant) {
+    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+    if (constant_key & 0xF0000000) {
+      Abort("array index constant value too big.");
+    }
+  } else {
+    key = ToRegister(instr->key());
+  }
+  int element_size_shift = ElementsKindToShiftSize(elements_kind);
+  bool key_is_tagged = instr->hydrogen()->key()->representation().IsTagged();
+  int additional_offset = instr->additional_index() << element_size_shift;
+
+  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+      elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+    DwVfpRegister result = ToDoubleRegister(instr->result());
+    if (key_is_constant) {
+      __ Add(scratch0(), external_pointer,
+             constant_key << element_size_shift,
+             r0);
+    } else {
+      __ IndexToArrayOffset(r0, key, element_size_shift, key_is_tagged);
+      __ add(scratch0(), external_pointer, r0);
+    }
+    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+      __ lfs(result, MemOperand(scratch0(), additional_offset));
+    } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
+      __ lfd(result, MemOperand(scratch0(), additional_offset));
+    }
+  } else {
+    Register result = ToRegister(instr->result());
+    MemOperand mem_operand = PrepareKeyedOperand(
+      key, external_pointer, key_is_constant, key_is_tagged, constant_key,
+      element_size_shift, instr->additional_index(), additional_offset);
+    switch (elements_kind) {
+      case EXTERNAL_BYTE_ELEMENTS:
+        if (key_is_constant) {
+          __ LoadByte(result, mem_operand, r0);
+        } else {
+          __ lbzx(result, mem_operand);
+        }
+        __ extsb(result, result);
+        break;
+      case EXTERNAL_PIXEL_ELEMENTS:
+      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+        if (key_is_constant) {
+          __ LoadByte(result, mem_operand, r0);
+        } else {
+          __ lbzx(result, mem_operand);
+        }
+        break;
+      case EXTERNAL_SHORT_ELEMENTS:
+        if (key_is_constant) {
+          __ LoadHalfWord(result, mem_operand, r0);
+        } else {
+          __ lhzx(result, mem_operand);
+        }
+        __ extsh(result, result);
+        break;
+      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+        if (key_is_constant) {
+          __ LoadHalfWord(result, mem_operand, r0);
+        } else {
+          __ lhzx(result, mem_operand);
+        }
+        break;
+      case EXTERNAL_INT_ELEMENTS:
+        if (key_is_constant) {
+          __ LoadWord(result, mem_operand, r0);
+        } else {
+          __ lwzx(result, mem_operand);
+        }
+#if V8_TARGET_ARCH_PPC64
+        __ extsw(result, result);
+#endif
+        break;
+      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+        if (key_is_constant) {
+          __ LoadWord(result, mem_operand, r0);
+        } else {
+          __ lwzx(result, mem_operand);
+        }
+        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
+          __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000)));
+          __ cmpl(result, r0);
+          DeoptimizeIf(ge, instr->environment());
+        }
+        break;
+      case EXTERNAL_FLOAT_ELEMENTS:
+      case EXTERNAL_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_ELEMENTS:
+      case FAST_HOLEY_SMI_ELEMENTS:
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_ELEMENTS:
+      case FAST_SMI_ELEMENTS:
+      case DICTIONARY_ELEMENTS:
+      case NON_STRICT_ARGUMENTS_ELEMENTS:
+        UNREACHABLE();
+        break;
+    }
+  }
+}
+
+
+void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
+  ASSERT(ToRegister(instr->object()).is(r4));
+  ASSERT(ToRegister(instr->key()).is(r3));
+
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
+  Register scratch = scratch0();
+  Register result = ToRegister(instr->result());
+
+  if (instr->hydrogen()->from_inlined()) {
+    __ subi(result, sp, Operand(2 * kPointerSize));
+  } else {
+    // Check if the calling frame is an arguments adaptor frame.
+    Label done, adapted;
+    __ LoadP(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+    __ LoadP(result,
+             MemOperand(scratch, StandardFrameConstants::kContextOffset));
+    __ CmpSmiLiteral(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+
+    // Result is the frame pointer for the frame if not adapted and for the real
+    // frame below the adaptor frame if adapted.
+    __ beq(&adapted);
+    __ mr(result, fp);
+    __ b(&done);
+
+    __ bind(&adapted);
+    __ mr(result, scratch);
+    __ bind(&done);
+  }
+}
+
+
+void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
+  Register elem = ToRegister(instr->elements());
+  Register result = ToRegister(instr->result());
+
+  Label done;
+
+  // If no arguments adaptor frame the number of arguments is fixed.
+  __ cmp(fp, elem);
+  __ mov(result, Operand(scope()->num_parameters()));
+  __ beq(&done);
+
+  // Arguments adaptor frame present. Get argument length from there.
+  __ LoadP(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(result,
+           MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
+  __ SmiUntag(result);
+
+  // Argument length is in result register.
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
+  Register receiver = ToRegister(instr->receiver());
+  Register function = ToRegister(instr->function());
+  Register scratch = scratch0();
+
+  // If the receiver is null or undefined, we have to pass the global
+  // object as a receiver to normal functions. Values have to be
+  // passed unchanged to builtins and strict-mode functions.
+  Label global_object, receiver_ok;
+
+  // Do not transform the receiver to object for strict mode
+  // functions.
+  __ LoadP(scratch,
+           FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
+  __ lwz(scratch,
+         FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
+  __ TestBit(scratch,
+#if V8_TARGET_ARCH_PPC64
+             SharedFunctionInfo::kStrictModeFunction,
+#else
+             SharedFunctionInfo::kStrictModeFunction + kSmiTagSize,
+#endif
+             r0);
+  __ bne(&receiver_ok, cr0);
+
+  // Do not transform the receiver to object for builtins.
+  __ TestBit(scratch,
+#if V8_TARGET_ARCH_PPC64
+             SharedFunctionInfo::kNative,
+#else
+             SharedFunctionInfo::kNative + kSmiTagSize,
+#endif
+             r0);
+  __ bne(&receiver_ok, cr0);
+
+  // Normal function. Replace undefined or null with global receiver.
+  __ LoadRoot(scratch, Heap::kNullValueRootIndex);
+  __ cmp(receiver, scratch);
+  __ beq(&global_object);
+  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ cmp(receiver, scratch);
+  __ beq(&global_object);
+
+  // Deoptimize if the receiver is not a JS object.
+  __ TestIfSmi(receiver, r0);
+  DeoptimizeIf(eq, instr->environment(), cr0);
+  __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
+  DeoptimizeIf(lt, instr->environment());
+  __ b(&receiver_ok);
+
+  __ bind(&global_object);
+  __ LoadP(receiver, GlobalObjectOperand());
+  __ LoadP(receiver,
+           FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
+  __ bind(&receiver_ok);
+}
+
+
+void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
+  Register receiver = ToRegister(instr->receiver());
+  Register function = ToRegister(instr->function());
+  Register length = ToRegister(instr->length());
+  Register elements = ToRegister(instr->elements());
+  Register scratch = scratch0();
+  ASSERT(receiver.is(r3));  // Used for parameter count.
+  ASSERT(function.is(r4));  // Required by InvokeFunction.
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  // Copy the arguments to this function possibly from the
+  // adaptor frame below it.
+  const uint32_t kArgumentsLimit = 1 * KB;
+  __ cmpli(length, Operand(kArgumentsLimit));
+  DeoptimizeIf(gt, instr->environment());
+
+  // Push the receiver and use the register to keep the original
+  // number of arguments.
+  __ push(receiver);
+  __ mr(receiver, length);
+  // The arguments are at a one pointer size offset from elements.
+  __ addi(elements, elements, Operand(1 * kPointerSize));
+
+  // Loop through the arguments pushing them onto the execution
+  // stack.
+  Label invoke, loop;
+  // length is a small non-negative integer, due to the test above.
+  __ cmpi(length, Operand::Zero());
+  __ beq(&invoke);
+  __ mtctr(length);
+  __ bind(&loop);
+  __ ShiftLeftImm(r0, length, Operand(kPointerSizeLog2));
+  __ LoadPX(scratch, MemOperand(elements, r0));
+  __ push(scratch);
+  __ addi(length, length, Operand(-1));
+  __ bdnz(&loop);
+
+  __ bind(&invoke);
+  ASSERT(instr->HasPointerMap());
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+  SafepointGenerator safepoint_generator(
+      this, pointers, Safepoint::kLazyDeopt);
+  // The number of arguments is stored in receiver which is r3, as expected
+  // by InvokeFunction.
+  ParameterCount actual(receiver);
+  __ InvokeFunction(function, actual, CALL_FUNCTION,
+                    safepoint_generator, CALL_AS_METHOD);
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
+
+
+void LCodeGen::DoPushArgument(LPushArgument* instr) {
+  LOperand* argument = instr->value();
+  if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
+    Abort("DoPushArgument not implemented for double type.");
+  } else {
+    Register argument_reg = EmitLoadRegister(argument, ip);
+    __ push(argument_reg);
+  }
+}
+
+
+void LCodeGen::DoDrop(LDrop* instr) {
+  __ Drop(instr->count());
+}
+
+
+void LCodeGen::DoThisFunction(LThisFunction* instr) {
+  Register result = ToRegister(instr->result());
+  __ LoadP(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+}
+
+
+void LCodeGen::DoContext(LContext* instr) {
+  Register result = ToRegister(instr->result());
+  __ mr(result, cp);
+}
+
+
+void LCodeGen::DoOuterContext(LOuterContext* instr) {
+  Register context = ToRegister(instr->context());
+  Register result = ToRegister(instr->result());
+  __ LoadP(result,
+           MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
+}
+
+
+void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
+  __ push(cp);  // The context is the first argument.
+  __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs());
+  __ push(scratch0());
+  __ LoadSmiLiteral(scratch0(), Smi::FromInt(instr->hydrogen()->flags()));
+  __ push(scratch0());
+  CallRuntime(Runtime::kDeclareGlobals, 3, instr);
+}
+
+
+void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+  Register result = ToRegister(instr->result());
+  __ LoadP(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
+}
+
+
+void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
+  Register global = ToRegister(instr->global_object());
+  Register result = ToRegister(instr->result());
+  __ LoadP(result,
+           FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset));
+}
+
+
+void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
+                                 int arity,
+                                 LInstruction* instr,
+                                 CallKind call_kind,
+                                 R4State r4_state) {
+  bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
+      function->shared()->formal_parameter_count() == arity;
+
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+
+  if (can_invoke_directly) {
+    if (r4_state == R4_UNINITIALIZED) {
+      __ LoadHeapObject(r4, function);
+    }
+
+    // Change context.
+    __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+
+    // Set r3 to arguments count if adaption is not needed. Assumes that r3
+    // is available to write to at this point.
+    if (!function->NeedsArgumentsAdaption()) {
+      __ mov(r3, Operand(arity));
+    }
+
+    // Invoke function.
+    __ SetCallKind(r8, call_kind);
+    if (*function == *info()->closure()) {
+      __ CallSelf();
+    } else {
+      __ LoadP(ip, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
+      __ Call(ip);
+    }
+
+    // Set up deoptimization.
+    RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
+  } else {
+    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
+    ParameterCount count(arity);
+    __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
+  }
+
+  // Restore context.
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
+
+
+void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
+  ASSERT(ToRegister(instr->result()).is(r3));
+  CallKnownFunction(instr->function(),
+                    instr->arity(),
+                    instr,
+                    CALL_AS_METHOD,
+                    R4_UNINITIALIZED);
+}
+
+
+void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+
+  // Deoptimize if not a heap number.
+  __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+  __ cmp(scratch, ip);
+  DeoptimizeIf(ne, instr->environment());
+
+  Label done;
+  Register exponent = scratch0();
+  scratch = no_reg;
+  __ lwz(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
+  // Check the sign of the argument. If the argument is positive, just
+  // return it.
+  __ TestSignBit32(exponent, r0);
+  // Move the input to the result if necessary.
+  __ Move(result, input);
+  __ beq(&done, cr0);
+
+  // Input is negative. Reverse its sign.
+  // Preserve the value of all registers.
+  {
+    PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+
+    // Registers were saved at the safepoint, so we can use
+    // many scratch registers.
+    Register tmp1 = input.is(r4) ? r3 : r4;
+    Register tmp2 = input.is(r5) ? r3 : r5;
+    Register tmp3 = input.is(r6) ? r3 : r6;
+    Register tmp4 = input.is(r7) ? r3 : r7;
+
+    // exponent: floating point exponent value.
+
+    Label allocated, slow;
+    __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
+    __ b(&allocated);
+
+    // Slow case: Call the runtime system to do the number allocation.
+    __ bind(&slow);
+
+    CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
+    // Set the pointer to the new heap number in tmp.
+    if (!tmp1.is(r3)) __ mr(tmp1, r3);
+    // Restore input_reg after call to runtime.
+    __ LoadFromSafepointRegisterSlot(input, input);
+    __ lwz(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
+
+    __ bind(&allocated);
+    // exponent: floating point exponent value.
+    // tmp1: allocated heap number.
+    STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
+    __ clrlwi(exponent, exponent, Operand(1));  // clear sign bit
+    __ stw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
+    __ lwz(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
+    __ stw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
+
+    __ StoreToSafepointRegisterSlot(tmp1, result);
+  }
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  Label done;
+  __ cmpi(input, Operand::Zero());
+  __ Move(result, input);
+  __ bge(&done);
+  __ li(r0, Operand::Zero());  // clear xer
+  __ mtxer(r0);
+  __ neg(result, result, SetOE, SetRC);
+  // Deoptimize on overflow.
+  DeoptimizeIf(overflow, instr->environment(), cr0);
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
+  // Class for deferred case.
+  class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
+   public:
+    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
+                                    LUnaryMathOperation* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() {
+      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
+    }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LUnaryMathOperation* instr_;
+  };
+
+  Representation r = instr->hydrogen()->value()->representation();
+  if (r.IsDouble()) {
+    DwVfpRegister input = ToDoubleRegister(instr->value());
+    DwVfpRegister result = ToDoubleRegister(instr->result());
+    __ fabs(result, input);
+  } else if (r.IsInteger32()) {
+    EmitIntegerMathAbs(instr);
+  } else {
+    // Representation is tagged.
+    DeferredMathAbsTaggedHeapNumber* deferred =
+        new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
+    Register input = ToRegister(instr->value());
+    // Smi check.
+    __ JumpIfNotSmi(input, deferred->entry());
+    // If smi, handle it directly.
+    EmitIntegerMathAbs(instr);
+    __ bind(deferred->exit());
+  }
+}
+
+
+void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
+  DoubleRegister input = ToDoubleRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+
+  __ EmitVFPTruncate(kRoundToMinusInf,
+                     result,
+                     input,
+                     scratch,
+                     double_scratch0());
+  DeoptimizeIf(ne, instr->environment());
+
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    // Test for -0.
+    Label done;
+    __ cmpi(result, Operand::Zero());
+    __ bne(&done);
+    // Move high word to scrach and test sign bit
+    __ subi(sp, sp, Operand(8));
+    __ stfd(input, MemOperand(sp));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    __ lwz(scratch, MemOperand(sp, 4));
+#else
+    __ lwz(scratch, MemOperand(sp, 0));
+#endif
+    __ addi(sp, sp, Operand(8));
+    __ TestSignBit32(scratch, r0);
+    DeoptimizeIf(ne, instr->environment(), cr0);
+    __ bind(&done);
+  }
+}
+
+
+void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
+  DoubleRegister input = ToDoubleRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
+  Register scratch = scratch0();
+  Label done, check_sign_on_zero, skip1, skip2;
+
+  // Extract exponent bits.
+  __ subi(sp, sp, Operand(8));
+  __ stfd(input, MemOperand(sp));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ lwz(result, MemOperand(sp, 4));
+#else
+  __ lwz(result, MemOperand(sp, 0));
+#endif
+  __ addi(sp, sp, Operand(8));
+  __ ExtractBitMask(scratch, result, HeapNumber::kExponentMask);
+
+  // If the number is in ]-0.5, +0.5[, the result is +/- 0.
+  __ cmpi(scratch, Operand(HeapNumber::kExponentBias - 2));
+  __ bgt(&skip1);
+  __ li(result, Operand::Zero());
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    __ b(&check_sign_on_zero);
+  } else {
+    __ b(&done);
+  }
+
+  // The following conversion will not work with numbers
+  // outside of ]-2^32, 2^32[.
+  __ bind(&skip1);
+  __ cmpi(scratch, Operand(HeapNumber::kExponentBias + 32));
+  DeoptimizeIf(ge, instr->environment());
+
+  __ LoadDoubleLiteral(double_scratch0(), 0.5, scratch);
+  __ fadd(double_scratch0(), input, double_scratch0());
+
+  // Save the original sign for later comparison.
+  STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
+  __ clrrwi(scratch, result, Operand(31));
+
+  // Check sign of the result: if the sign changed, the input
+  // value was in ]0.5, 0[ and the result should be -0.
+  __ subi(sp, sp, Operand(8));
+  __ stfd(double_scratch0(), MemOperand(sp, 0));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ lwz(result, MemOperand(sp, 4));
+#else
+  __ lwz(result, MemOperand(sp, 0));
+#endif
+  __ addi(sp, sp, Operand(8));
+  __ xor_(result, result, scratch, SetRC);
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    DeoptimizeIf(lt, instr->environment(), cr0);
+  } else {
+    __ bge(&skip2);
+    __ li(result, Operand::Zero());
+    __ b(&done);
+    __ bind(&skip2);
+  }
+
+  __ EmitVFPTruncate(kRoundToMinusInf,
+                     result,
+                     double_scratch0(),
+                     scratch,
+                     double_scratch1);
+  DeoptimizeIf(ne, instr->environment());
+
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    // Test for -0.
+    __ cmpi(result, Operand::Zero());
+    __ bne(&done);
+    __ bind(&check_sign_on_zero);
+    // Move high word to scrach and test sign bit
+    __ subi(sp, sp, Operand(8));
+    __ stfd(input, MemOperand(sp));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    __ lwz(scratch, MemOperand(sp, 4));
+#else
+    __ lwz(scratch, MemOperand(sp, 0));
+#endif
+    __ addi(sp, sp, Operand(8));
+    __ TestSignBit32(scratch, r0);
+    DeoptimizeIf(ne, instr->environment(), cr0);
+  }
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
+  DoubleRegister input = ToDoubleRegister(instr->value());
+  DoubleRegister result = ToDoubleRegister(instr->result());
+  __ fsqrt(result, input);
+}
+
+
+void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
+  DoubleRegister input = ToDoubleRegister(instr->value());
+  DoubleRegister result = ToDoubleRegister(instr->result());
+  DoubleRegister temp = ToDoubleRegister(instr->temp());
+
+  // Note that according to ECMA-262 15.8.2.13:
+  // Math.pow(-Infinity, 0.5) == Infinity
+  // Math.sqrt(-Infinity) == NaN
+  Label skip, done;
+
+  __ LoadDoubleLiteral(temp, -V8_INFINITY, scratch0());
+  __ fcmpu(input, temp);
+  __ bne(&skip);
+  __ fneg(result, temp);
+  __ b(&done);
+
+  // Add +0 to convert -0 to +0.
+  __ bind(&skip);
+  __ fadd(result, input, kDoubleRegZero);
+  __ fsqrt(result, result);
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoPower(LPower* instr) {
+  Representation exponent_type = instr->hydrogen()->right()->representation();
+  // Having marked this as a call, we can use any registers.
+  // Just make sure that the input/output registers are the expected ones.
+  ASSERT(!instr->right()->IsDoubleRegister() ||
+         ToDoubleRegister(instr->right()).is(d2));
+  ASSERT(!instr->right()->IsRegister() ||
+         ToRegister(instr->right()).is(r5));
+  ASSERT(ToDoubleRegister(instr->left()).is(d1));
+  ASSERT(ToDoubleRegister(instr->result()).is(d3));
+
+  if (exponent_type.IsTagged()) {
+    Label no_deopt;
+    __ JumpIfSmi(r5, &no_deopt);
+    __ LoadP(r10, FieldMemOperand(r5, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+    __ cmp(r10, ip);
+    DeoptimizeIf(ne, instr->environment());
+    __ bind(&no_deopt);
+    MathPowStub stub(MathPowStub::TAGGED);
+    __ CallStub(&stub);
+  } else if (exponent_type.IsInteger32()) {
+    MathPowStub stub(MathPowStub::INTEGER);
+    __ CallStub(&stub);
+  } else {
+    ASSERT(exponent_type.IsDouble());
+    MathPowStub stub(MathPowStub::DOUBLE);
+    __ CallStub(&stub);
+  }
+}
+
+
+void LCodeGen::DoRandom(LRandom* instr) {
+  class DeferredDoRandom: public LDeferredCode {
+   public:
+    DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredRandom(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LRandom* instr_;
+  };
+
+  DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr);
+
+  // Having marked this instruction as a call we can use any
+  // registers.
+  ASSERT(ToDoubleRegister(instr->result()).is(d7));
+  ASSERT(ToRegister(instr->global_object()).is(r3));
+
+  static const int kSeedSize = sizeof(uint32_t);
+#ifndef V8_TARGET_ARCH_PPC64  // todo fix (currently fails on 64bit)
+  STATIC_ASSERT(kPointerSize == kSeedSize);
+#endif
+
+  __ LoadP(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
+  static const int kRandomSeedOffset =
+      FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
+  __ LoadP(r5, FieldMemOperand(r3, kRandomSeedOffset));
+  // r5: FixedArray of the native context's random seeds
+
+  // Load state[0].
+  __ lwz(r4, FieldMemOperand(r5, ByteArray::kHeaderSize));
+  __ cmpi(r4, Operand::Zero());
+  __ beq(deferred->entry());
+  // Load state[1].
+  __ lwz(r3, FieldMemOperand(r5, ByteArray::kHeaderSize + kSeedSize));
+  // r4: state[0].
+  // r3: state[1].
+
+  // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
+  __ andi(r6, r4, Operand(0xFFFF));
+  __ li(r7, Operand(18273));
+  __ Mul(r6, r6, r7);
+  __ srwi(r4, r4, Operand(16));
+  __ add(r4, r6, r4);
+  // Save state[0].
+  __ stw(r4, FieldMemOperand(r5, ByteArray::kHeaderSize));
+
+  // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
+  __ andi(r6, r3, Operand(0xFFFF));
+  __ mov(r7, Operand(36969));
+  __ Mul(r6, r6, r7);
+  __ srwi(r3, r3, Operand(16));
+  __ add(r3, r6, r3);
+  // Save state[1].
+  __ stw(r3, FieldMemOperand(r5, ByteArray::kHeaderSize + kSeedSize));
+
+  // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
+  __ ExtractBitMask(r3, r3, 0x3FFFF);
+  __ slwi(r0, r4, Operand(14));
+  __ add(r3, r3, r0);
+
+  __ bind(deferred->exit());
+
+  // Allocate temp stack space to for double
+  __ addi(sp, sp, Operand(-8));
+
+  // 0x41300000 is the top half of 1.0 x 2^20 as a double.
+  __ lis(r4, Operand(0x4130));
+
+  // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ stw(r3, MemOperand(sp, 0));
+  __ stw(r4, MemOperand(sp, 4));
+#else
+  __ stw(r4, MemOperand(sp, 0));
+  __ stw(r3, MemOperand(sp, 4));
+#endif
+  __ lfd(d7, MemOperand(sp, 0));
+
+  // Move 0x4130000000000000 to VFP.
+  __ li(r3, Operand::Zero());
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ stw(r3, MemOperand(sp, 0));
+  __ stw(r4, MemOperand(sp, 4));
+#else
+  __ stw(r4, MemOperand(sp, 0));
+  __ stw(r3, MemOperand(sp, 4));
+#endif
+  __ lfd(d8, MemOperand(sp, 0));
+
+  __ addi(sp, sp, Operand(8));
+
+  // Subtract and store the result in the heap number.
+  __ fsub(d7, d7, d8);
+}
+
+
+void LCodeGen::DoDeferredRandom(LRandom* instr) {
+  __ PrepareCallCFunction(1, scratch0());
+  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+  // Return value is in r3.
+}
+
+
+void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathTan(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  TranscendentalCacheStub stub(TranscendentalCache::TAN,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(d2));
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
+  switch (instr->op()) {
+    case kMathAbs:
+      DoMathAbs(instr);
+      break;
+    case kMathFloor:
+      DoMathFloor(instr);
+      break;
+    case kMathRound:
+      DoMathRound(instr);
+      break;
+    case kMathSqrt:
+      DoMathSqrt(instr);
+      break;
+    case kMathPowHalf:
+      DoMathPowHalf(instr);
+      break;
+    case kMathCos:
+      DoMathCos(instr);
+      break;
+    case kMathSin:
+      DoMathSin(instr);
+      break;
+    case kMathTan:
+      DoMathTan(instr);
+      break;
+    case kMathLog:
+      DoMathLog(instr);
+      break;
+    default:
+      Abort("Unimplemented type of LUnaryMathOperation.");
+      UNREACHABLE();
+  }
+}
+
+
+void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
+  ASSERT(ToRegister(instr->function()).is(r4));
+  ASSERT(instr->HasPointerMap());
+
+  if (instr->known_function().is_null()) {
+    LPointerMap* pointers = instr->pointer_map();
+    RecordPosition(pointers->position());
+    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
+    ParameterCount count(instr->arity());
+    __ InvokeFunction(r4, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
+    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  } else {
+    CallKnownFunction(instr->known_function(),
+                      instr->arity(),
+                      instr,
+                      CALL_AS_METHOD,
+                      R4_CONTAINS_TARGET);
+  }
+}
+
+
+void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  int arity = instr->arity();
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
+
+
+void LCodeGen::DoCallNamed(LCallNamed* instr) {
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  int arity = instr->arity();
+  RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
+  __ mov(r5, Operand(instr->name()));
+  CallCode(ic, mode, instr);
+  // Restore context register.
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
+
+
+void LCodeGen::DoCallFunction(LCallFunction* instr) {
+  ASSERT(ToRegister(instr->function()).is(r4));
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  int arity = instr->arity();
+  CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
+
+
+void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  int arity = instr->arity();
+  RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
+  Handle<Code> ic =
+      isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
+  __ mov(r5, Operand(instr->name()));
+  CallCode(ic, mode, instr);
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
+
+
+void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
+  ASSERT(ToRegister(instr->result()).is(r3));
+  CallKnownFunction(instr->target(),
+                    instr->arity(),
+                    instr,
+                    CALL_AS_FUNCTION,
+                    R4_UNINITIALIZED);
+}
+
+
+void LCodeGen::DoCallNew(LCallNew* instr) {
+  ASSERT(ToRegister(instr->constructor()).is(r4));
+  ASSERT(ToRegister(instr->result()).is(r3));
+
+  CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
+  __ mov(r3, Operand(instr->arity()));
+  CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
+}
+
+
+void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
+  CallRuntime(instr->function(), instr->arity(), instr);
+}
+
+
+void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
+  Register object = ToRegister(instr->object());
+  Register value = ToRegister(instr->value());
+  Register scratch = scratch0();
+  int offset = instr->offset();
+
+  ASSERT(!object.is(value));
+
+  if (!instr->transition().is_null()) {
+    __ mov(scratch, Operand(instr->transition()));
+    __ StoreP(scratch, FieldMemOperand(object, HeapObject::kMapOffset), r0);
+    if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
+      Register temp = ToRegister(instr->temp());
+      // Update the write barrier for the map field.
+      __ RecordWriteField(object,
+                          HeapObject::kMapOffset,
+                          scratch,
+                          temp,
+                          kLRHasBeenSaved,
+                          kSaveFPRegs,
+                          OMIT_REMEMBERED_SET,
+                          OMIT_SMI_CHECK);
+    }
+  }
+
+  // Do the store.
+  HType type = instr->hydrogen()->value()->type();
+  SmiCheck check_needed =
+      type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
+  if (instr->is_in_object()) {
+    __ StoreP(value, FieldMemOperand(object, offset), r0);
+    if (instr->hydrogen()->NeedsWriteBarrier()) {
+      // Update the write barrier for the object for in-object properties.
+      __ RecordWriteField(object,
+                          offset,
+                          value,
+                          scratch,
+                          kLRHasBeenSaved,
+                          kSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          check_needed);
+    }
+  } else {
+    __ LoadP(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
+    __ StoreP(value, FieldMemOperand(scratch, offset), r0);
+    if (instr->hydrogen()->NeedsWriteBarrier()) {
+      // Update the write barrier for the properties array.
+      // object is used as a scratch register.
+      __ RecordWriteField(scratch,
+                          offset,
+                          value,
+                          object,
+                          kLRHasBeenSaved,
+                          kSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          check_needed);
+    }
+  }
+}
+
+
+void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
+  ASSERT(ToRegister(instr->object()).is(r4));
+  ASSERT(ToRegister(instr->value()).is(r3));
+
+  // Name is always in r5.
+  __ mov(r5, Operand(instr->name()));
+  Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+      ? isolate()->builtins()->StoreIC_Initialize_Strict()
+      : isolate()->builtins()->StoreIC_Initialize();
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DeoptIfTaggedButNotSmi(LEnvironment* environment,
+                                      HValue* value,
+                                      LOperand* operand) {
+  if (value->representation().IsTagged() && !value->type().IsSmi()) {
+    if (operand->IsRegister()) {
+      __ TestIfSmi(ToRegister(operand), r0);
+    } else {
+      __ mov(ip, ToOperand(operand));
+      __ TestIfSmi(ip, r0);
+    }
+    DeoptimizeIf(ne, environment, cr0);
+  }
+}
+
+
+void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
+  DeoptIfTaggedButNotSmi(instr->environment(),
+                         instr->hydrogen()->length(),
+                         instr->length());
+  DeoptIfTaggedButNotSmi(instr->environment(),
+                         instr->hydrogen()->index(),
+                         instr->index());
+  if (instr->index()->IsConstantOperand()) {
+    int constant_index =
+        ToInteger32(LConstantOperand::cast(instr->index()));
+    if (instr->hydrogen()->length()->representation().IsTagged()) {
+      __ LoadSmiLiteral(ip, Smi::FromInt(constant_index));
+    } else {
+      __ mov(ip, Operand(constant_index));
+    }
+    __ cmpl(ip, ToRegister(instr->length()));
+  } else {
+    __ cmpl(ToRegister(instr->index()), ToRegister(instr->length()));
+  }
+  DeoptimizeIf(ge, instr->environment());
+}
+
+
+void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
+  Register value = ToRegister(instr->value());
+  Register elements = ToRegister(instr->object());
+  Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
+  Register scratch = scratch0();
+  Register store_base = scratch;
+  int offset = 0;
+
+  // Do the store.
+  if (instr->key()->IsConstantOperand()) {
+    ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
+    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
+    offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) +
+                                           instr->additional_index());
+    store_base = elements;
+  } else {
+    // Even though the HLoadKeyedFastElement instruction forces the input
+    // representation for the key to be an integer, the input gets replaced
+    // during bound check elimination with the index argument to the bounds
+    // check, which can be tagged, so that case must be handled here, too.
+    if (instr->hydrogen()->key()->representation().IsTagged()) {
+      __ SmiToPtrArrayOffset(scratch, key);
+    } else {
+      __ ShiftLeftImm(scratch, key, Operand(kPointerSizeLog2));
+    }
+    __ add(scratch, elements, scratch);
+    offset = FixedArray::OffsetOfElementAt(instr->additional_index());
+  }
+  __ StoreP(value, FieldMemOperand(store_base, offset), r0);
+
+  if (instr->hydrogen()->NeedsWriteBarrier()) {
+    HType type = instr->hydrogen()->value()->type();
+    SmiCheck check_needed =
+        type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
+    // Compute address of modified element and store it into key register.
+    __ Add(key, store_base, offset - kHeapObjectTag, r0);
+    __ RecordWrite(elements,
+                   key,
+                   value,
+                   kLRHasBeenSaved,
+                   kSaveFPRegs,
+                   EMIT_REMEMBERED_SET,
+                   check_needed);
+  }
+}
+
+
+void LCodeGen::DoStoreKeyedFastDoubleElement(
+    LStoreKeyedFastDoubleElement* instr) {
+  DwVfpRegister value = ToDoubleRegister(instr->value());
+  Register elements = ToRegister(instr->elements());
+  Register key = no_reg;
+  Register scratch = scratch0();
+  bool key_is_constant = instr->key()->IsConstantOperand();
+  int constant_key = 0;
+  Label no_canonicalization, done;
+
+  // Calculate the effective address of the slot in the array to store the
+  // double value.
+  if (key_is_constant) {
+    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+    if (constant_key & 0xF0000000) {
+      Abort("array index constant value too big.");
+    }
+  } else {
+    key = ToRegister(instr->key());
+  }
+  int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
+  bool key_is_tagged = instr->hydrogen()->key()->representation().IsTagged();
+  int dst_offset = instr->additional_index() << element_size_shift;
+  if (key_is_constant) {
+    __ Add(scratch, elements,
+           (constant_key << element_size_shift) +
+           FixedDoubleArray::kHeaderSize - kHeapObjectTag,
+           r0);
+  } else {
+    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_tagged);
+    __ add(scratch, elements, scratch);
+    __ addi(scratch, scratch,
+            Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+  }
+
+  if (instr->NeedsCanonicalization()) {
+    // Check for NaN. All NaNs must be canonicalized.
+    __ fcmpu(value, value);
+    // Only load canonical NaN if the comparison above set unordered.
+    __ bordered(&no_canonicalization);
+
+    uint64_t nan_int64 = BitCast<uint64_t>(
+        FixedDoubleArray::canonical_not_the_hole_nan_as_double());
+    __ mov(r0, Operand(static_cast<intptr_t>(nan_int64)));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    __ stw(r0, MemOperand(scratch, dst_offset));
+#else
+    __ stw(r0, MemOperand(scratch, dst_offset + 4));
+#endif
+    __ mov(r0, Operand(static_cast<intptr_t>(nan_int64 >> 32)));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    __ stw(r0, MemOperand(scratch, dst_offset + 4));
+#else
+    __ stw(r0, MemOperand(scratch, dst_offset));
+#endif
+    __ b(&done);
+  }
+
+  __ bind(&no_canonicalization);
+  __ stfd(value, MemOperand(scratch, dst_offset));
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoStoreKeyedSpecializedArrayElement(
+    LStoreKeyedSpecializedArrayElement* instr) {
+  Register external_pointer = ToRegister(instr->external_pointer());
+  Register key = no_reg;
+  ElementsKind elements_kind = instr->elements_kind();
+  bool key_is_constant = instr->key()->IsConstantOperand();
+  int constant_key = 0;
+  if (key_is_constant) {
+    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
+    if (constant_key & 0xF0000000) {
+      Abort("array index constant value too big.");
+    }
+  } else {
+    key = ToRegister(instr->key());
+  }
+  int element_size_shift = ElementsKindToShiftSize(elements_kind);
+  bool key_is_tagged = instr->hydrogen()->key()->representation().IsTagged();
+  int additional_offset = instr->additional_index() << element_size_shift;
+
+  if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
+      elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+    DwVfpRegister value(ToDoubleRegister(instr->value()));
+    if (key_is_constant) {
+      __ Add(scratch0(), external_pointer,
+             constant_key << element_size_shift,
+             r0);
+    } else {
+      __ IndexToArrayOffset(r0, key, element_size_shift, key_is_tagged);
+      __ add(scratch0(), external_pointer, r0);
+    }
+    if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+      __ frsp(double_scratch0(), value);
+      __ stfs(double_scratch0(), MemOperand(scratch0(), additional_offset));
+    } else {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
+      __ stfd(value, MemOperand(scratch0(), additional_offset));
+    }
+  } else {
+    Register value(ToRegister(instr->value()));
+    MemOperand mem_operand = PrepareKeyedOperand(
+      key, external_pointer, key_is_constant, key_is_tagged, constant_key,
+      element_size_shift, instr->additional_index(), additional_offset);
+    switch (elements_kind) {
+      case EXTERNAL_PIXEL_ELEMENTS:
+      case EXTERNAL_BYTE_ELEMENTS:
+      case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+        if (key_is_constant) {
+          __ StoreByte(value, mem_operand, r0);
+        } else {
+          __ stbx(value, mem_operand);
+        }
+        break;
+      case EXTERNAL_SHORT_ELEMENTS:
+      case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+        if (key_is_constant) {
+          __ StoreHalfWord(value, mem_operand, r0);
+        } else {
+          __ sthx(value, mem_operand);
+        }
+        break;
+      case EXTERNAL_INT_ELEMENTS:
+      case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+        if (key_is_constant) {
+          __ StoreWord(value, mem_operand, r0);
+        } else {
+          __ stwx(value, mem_operand);
+        }
+        break;
+      case EXTERNAL_FLOAT_ELEMENTS:
+      case EXTERNAL_DOUBLE_ELEMENTS:
+      case FAST_DOUBLE_ELEMENTS:
+      case FAST_ELEMENTS:
+      case FAST_SMI_ELEMENTS:
+      case FAST_HOLEY_DOUBLE_ELEMENTS:
+      case FAST_HOLEY_ELEMENTS:
+      case FAST_HOLEY_SMI_ELEMENTS:
+      case DICTIONARY_ELEMENTS:
+      case NON_STRICT_ARGUMENTS_ELEMENTS:
+        UNREACHABLE();
+        break;
+    }
+  }
+}
+
+
+void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
+  ASSERT(ToRegister(instr->object()).is(r5));
+  ASSERT(ToRegister(instr->key()).is(r4));
+  ASSERT(ToRegister(instr->value()).is(r3));
+
+  Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+      ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
+      : isolate()->builtins()->KeyedStoreIC_Initialize();
+  CallCode(ic, RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
+  Register object_reg = ToRegister(instr->object());
+  Register new_map_reg = ToRegister(instr->new_map_temp());
+  Register scratch = scratch0();
+
+  Handle<Map> from_map = instr->original_map();
+  Handle<Map> to_map = instr->transitioned_map();
+  ElementsKind from_kind = from_map->elements_kind();
+  ElementsKind to_kind = to_map->elements_kind();
+
+  Label not_applicable;
+  __ LoadP(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+  __ Cmpi(scratch, Operand(from_map), r0);
+  __ bne(&not_applicable);
+  __ mov(new_map_reg, Operand(to_map));
+
+  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+    __ StoreP(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset),
+              r0);
+    // Write barrier.
+    __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
+                        scratch, kLRHasBeenSaved, kDontSaveFPRegs);
+  } else if (IsFastSmiElementsKind(from_kind) &&
+             IsFastDoubleElementsKind(to_kind)) {
+    Register fixed_object_reg = ToRegister(instr->temp());
+    ASSERT(fixed_object_reg.is(r5));
+    ASSERT(new_map_reg.is(r6));
+    __ mr(fixed_object_reg, object_reg);
+    CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
+             RelocInfo::CODE_TARGET, instr);
+  } else if (IsFastDoubleElementsKind(from_kind) &&
+             IsFastObjectElementsKind(to_kind)) {
+    Register fixed_object_reg = ToRegister(instr->temp());
+    ASSERT(fixed_object_reg.is(r5));
+    ASSERT(new_map_reg.is(r6));
+    __ mr(fixed_object_reg, object_reg);
+    CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
+             RelocInfo::CODE_TARGET, instr);
+  } else {
+    UNREACHABLE();
+  }
+  __ bind(&not_applicable);
+}
+
+
+void LCodeGen::DoStringAdd(LStringAdd* instr) {
+  __ push(ToRegister(instr->left()));
+  __ push(ToRegister(instr->right()));
+  StringAddStub stub(NO_STRING_CHECK_IN_STUB);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
+  class DeferredStringCharCodeAt: public LDeferredCode {
+   public:
+    DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LStringCharCodeAt* instr_;
+  };
+
+  DeferredStringCharCodeAt* deferred =
+      new(zone()) DeferredStringCharCodeAt(this, instr);
+
+  StringCharLoadGenerator::Generate(masm(),
+                                    ToRegister(instr->string()),
+                                    ToRegister(instr->index()),
+                                    ToRegister(instr->result()),
+                                    deferred->entry());
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
+  Register string = ToRegister(instr->string());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ li(result, Operand::Zero());
+
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  __ push(string);
+  // Push the index as a smi. This is safe because of the checks in
+  // DoStringCharCodeAt above.
+  if (instr->index()->IsConstantOperand()) {
+    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    __ LoadSmiLiteral(scratch, Smi::FromInt(const_index));
+    __ push(scratch);
+  } else {
+    Register index = ToRegister(instr->index());
+    __ SmiTag(index);
+    __ push(index);
+  }
+  CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr);
+  __ AssertSmi(r3);
+  __ SmiUntag(r3);
+  __ StoreToSafepointRegisterSlot(r3, result);
+}
+
+
+void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
+  class DeferredStringCharFromCode: public LDeferredCode {
+   public:
+    DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LStringCharFromCode* instr_;
+  };
+
+  DeferredStringCharFromCode* deferred =
+      new(zone()) DeferredStringCharFromCode(this, instr);
+
+  ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+  ASSERT(!char_code.is(result));
+
+  __ cmpli(char_code, Operand(String::kMaxAsciiCharCode));
+  __ bgt(deferred->entry());
+  __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
+  __ ShiftLeftImm(r0, char_code, Operand(kPointerSizeLog2));
+  __ add(result, result, r0);
+  __ LoadP(result, FieldMemOperand(result, FixedArray::kHeaderSize));
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ cmp(result, ip);
+  __ beq(deferred->entry());
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
+  Register char_code = ToRegister(instr->char_code());
+  Register result = ToRegister(instr->result());
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ li(result, Operand::Zero());
+
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  __ SmiTag(char_code);
+  __ push(char_code);
+  CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
+  __ StoreToSafepointRegisterSlot(r3, result);
+}
+
+
+void LCodeGen::DoStringLength(LStringLength* instr) {
+  Register string = ToRegister(instr->string());
+  Register result = ToRegister(instr->result());
+  __ LoadP(result, FieldMemOperand(string, String::kLengthOffset));
+}
+
+
+void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister() || input->IsStackSlot());
+  LOperand* output = instr->result();
+  ASSERT(output->IsDoubleRegister());
+  if (input->IsStackSlot()) {
+    Register scratch = scratch0();
+    __ LoadP(scratch, ToMemOperand(input));
+    FloatingPointHelper::ConvertIntToDouble(masm(), scratch,
+       ToDoubleRegister(output));
+  } else {
+    FloatingPointHelper::ConvertIntToDouble(masm(), ToRegister(input),
+       ToDoubleRegister(output));
+  }
+}
+
+
+void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
+  LOperand* input = instr->value();
+  LOperand* output = instr->result();
+  FloatingPointHelper::ConvertUnsignedIntToDouble(masm(), ToRegister(input),
+       ToDoubleRegister(output));
+}
+
+
+void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
+  class DeferredNumberTagI: public LDeferredCode {
+   public:
+    DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() {
+      codegen()->DoDeferredNumberTagI(instr_,
+                                      instr_->value(),
+                                      SIGNED_INT32);
+    }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LNumberTagI* instr_;
+  };
+
+  Register src = ToRegister(instr->value());
+  Register dst = ToRegister(instr->result());
+
+  DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr);
+#if V8_TARGET_ARCH_PPC64
+  __ SmiTag(dst, src);
+#else
+  __ SmiTagCheckOverflow(dst, src, r0);
+  __ BranchOnOverflow(deferred->entry());
+#endif
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
+  class DeferredNumberTagU: public LDeferredCode {
+   public:
+    DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() {
+      codegen()->DoDeferredNumberTagI(instr_,
+                                      instr_->value(),
+                                      UNSIGNED_INT32);
+    }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LNumberTagU* instr_;
+  };
+
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister() && input->Equals(instr->result()));
+  Register reg = ToRegister(input);
+
+  DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
+  __ Cmpli(reg, Operand(Smi::kMaxValue), r0);
+  __ bgt(deferred->entry());
+  __ SmiTag(reg, reg);
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoDeferredNumberTagI(LInstruction* instr,
+                                    LOperand* value,
+                                    IntegerSignedness signedness) {
+  Label slow;
+  Register src = ToRegister(value);
+  Register dst = ToRegister(instr->result());
+  DoubleRegister dbl_scratch = double_scratch0();
+
+  // Preserve the value of all registers.
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+
+  Label done;
+  if (signedness == SIGNED_INT32) {
+    // There was overflow, so bits 30 and 31 of the original integer
+    // disagree. Try to allocate a heap number in new space and store
+    // the value in there. If that fails, call the runtime system.
+    if (dst.is(src)) {
+      __ SmiUntag(src, dst);
+      __ xoris(src, src, Operand(HeapNumber::kSignMask >> 16));
+    }
+    FloatingPointHelper::ConvertIntToDouble(masm(), src, dbl_scratch);
+  } else {
+    FloatingPointHelper::ConvertUnsignedIntToDouble(masm(), src, dbl_scratch);
+  }
+
+  if (FLAG_inline_new) {
+    __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r8, r6, r7, r9, &slow);
+    __ Move(dst, r8);
+    __ b(&done);
+  }
+
+  // Slow case: Call the runtime system to do the number allocation.
+  __ bind(&slow);
+
+  // TODO(3095996): Put a valid pointer value in the stack slot where the result
+  // register is stored, as this register is in the pointer map, but contains an
+  // integer value.
+  __ li(ip, Operand::Zero());
+  __ StoreToSafepointRegisterSlot(ip, dst);
+  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
+  __ Move(dst, r3);
+
+  // Done. Put the value in dbl_scratch into the value of the allocated heap
+  // number.
+  __ bind(&done);
+  __ stfd(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
+  __ StoreToSafepointRegisterSlot(dst, dst);
+}
+
+
+void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
+  class DeferredNumberTagD: public LDeferredCode {
+   public:
+    DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LNumberTagD* instr_;
+  };
+
+  DoubleRegister input_reg = ToDoubleRegister(instr->value());
+  Register scratch = scratch0();
+  Register reg = ToRegister(instr->result());
+  Register temp1 = ToRegister(instr->temp());
+  Register temp2 = ToRegister(instr->temp2());
+
+  DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
+  if (FLAG_inline_new) {
+    __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
+  } else {
+    __ b(deferred->entry());
+  }
+  __ bind(deferred->exit());
+  __ stfd(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
+}
+
+
+void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  Register reg = ToRegister(instr->result());
+  __ li(reg, Operand::Zero());
+
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
+  __ StoreToSafepointRegisterSlot(r3, reg);
+}
+
+
+void LCodeGen::DoSmiTag(LSmiTag* instr) {
+  ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
+  __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value()));
+}
+
+
+void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
+  Register scratch = scratch0();
+  Register input = ToRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  if (instr->needs_check()) {
+    STATIC_ASSERT(kHeapObjectTag == 1);
+    // If the input is a HeapObject, value of scratch won't be zero.
+    __ andi(scratch, input, Operand(kHeapObjectTag));
+    __ SmiUntag(result, input);
+    DeoptimizeIf(ne, instr->environment(), cr0);
+  } else {
+    __ SmiUntag(result, input);
+  }
+}
+
+
+void LCodeGen::EmitNumberUntagD(Register input_reg,
+                                DoubleRegister result_reg,
+                                bool deoptimize_on_undefined,
+                                bool deoptimize_on_minus_zero,
+                                LEnvironment* env) {
+  Register scratch = scratch0();
+  ASSERT(!result_reg.is(double_scratch0()));
+
+  Label load_smi, heap_number, done;
+
+  // Smi check.
+  __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
+
+  // Heap number map check.
+  __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+  __ cmp(scratch, ip);
+  if (deoptimize_on_undefined) {
+    DeoptimizeIf(ne, env);
+  } else {
+    Label heap_number;
+    __ beq(&heap_number);
+
+    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+    __ cmp(input_reg, ip);
+    DeoptimizeIf(ne, env);
+
+    // Convert undefined to NaN.
+    __ LoadRoot(ip, Heap::kNanValueRootIndex);
+    __ lfd(result_reg, FieldMemOperand(ip, HeapNumber::kValueOffset));
+    __ b(&done);
+
+    __ bind(&heap_number);
+  }
+  // Heap number to double register conversion.
+  __ lfd(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
+  if (deoptimize_on_minus_zero) {
+    __ subi(sp, sp, Operand(8));
+    __ stfd(result_reg, MemOperand(sp));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+    __ lwz(ip, MemOperand(sp, 0));
+    __ lwz(scratch, MemOperand(sp, 4));
+#else
+    __ lwz(ip, MemOperand(sp, 4));
+    __ lwz(scratch, MemOperand(sp, 0));
+#endif
+    __ addi(sp, sp, Operand(8));
+
+    __ cmpi(ip, Operand::Zero());
+    __ bne(&done);
+    __ Cmpi(scratch, Operand(HeapNumber::kSignMask), r0);
+    DeoptimizeIf(eq, env);
+  }
+  __ b(&done);
+
+  // Smi to double register conversion
+  __ bind(&load_smi);
+  // scratch: untagged value of input_reg
+  FloatingPointHelper::ConvertIntToDouble(masm(), scratch, result_reg);
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
+  Register input_reg = ToRegister(instr->value());
+  Register scratch1 = scratch0();
+  Register scratch2 = ToRegister(instr->temp());
+  DwVfpRegister double_scratch = double_scratch0();
+  DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3());
+
+  ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
+  ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
+
+  Label done;
+
+  // Heap number map check.
+  __ LoadP(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+  __ cmp(scratch1, ip);
+
+  if (instr->truncating()) {
+    Register scratch3 = ToRegister(instr->temp2());
+    ASSERT(!scratch3.is(input_reg) &&
+           !scratch3.is(scratch1) &&
+           !scratch3.is(scratch2));
+    // Performs a truncating conversion of a floating point number as used by
+    // the JS bitwise operations.
+    Label heap_number;
+    __ beq(&heap_number);
+    // Check for undefined. Undefined is converted to zero for truncating
+    // conversions.
+    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+    __ cmp(input_reg, ip);
+    DeoptimizeIf(ne, instr->environment());
+    __ li(input_reg, Operand::Zero());
+    __ b(&done);
+
+    __ bind(&heap_number);
+    __ lfd(double_scratch2,
+           FieldMemOperand(input_reg, HeapNumber::kValueOffset));
+
+    __ EmitECMATruncate(input_reg,
+                        double_scratch2,
+                        double_scratch,
+                        scratch1,
+                        scratch2,
+                        scratch3);
+
+  } else {
+    // Deoptimize if we don't have a heap number.
+    DeoptimizeIf(ne, instr->environment());
+
+    __ lfd(double_scratch,
+           FieldMemOperand(input_reg, HeapNumber::kValueOffset));
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      // preserve heap number pointer in scratch2 for minus zero check below
+      __ mr(scratch2, input_reg);
+    }
+    __ EmitVFPTruncate(kRoundToZero,
+                       input_reg,
+                       double_scratch,
+                       scratch1,
+                       double_scratch2,
+                       kCheckForInexactConversion);
+    DeoptimizeIf(ne, instr->environment());
+
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      __ cmpi(input_reg, Operand::Zero());
+      __ bne(&done);
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+      __ lwz(scratch1, FieldMemOperand(scratch2, HeapNumber::kValueOffset + 4));
+#else
+      __ lwz(scratch1, FieldMemOperand(scratch2, HeapNumber::kValueOffset));
+#endif
+      __ TestSignBit32(scratch1, r0);
+      DeoptimizeIf(ne, instr->environment(), cr0);
+    }
+  }
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
+  class DeferredTaggedToI: public LDeferredCode {
+   public:
+    DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LTaggedToI* instr_;
+  };
+
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister());
+  ASSERT(input->Equals(instr->result()));
+
+  Register input_reg = ToRegister(input);
+
+  DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr);
+
+  // Branch to deferred code if the input is a HeapObject.
+  __ JumpIfNotSmi(input_reg, deferred->entry());
+
+  __ SmiUntag(input_reg);
+  __ bind(deferred->exit());
+}
+
+
+void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister());
+  LOperand* result = instr->result();
+  ASSERT(result->IsDoubleRegister());
+
+  Register input_reg = ToRegister(input);
+  DoubleRegister result_reg = ToDoubleRegister(result);
+
+  EmitNumberUntagD(input_reg, result_reg,
+                   instr->hydrogen()->deoptimize_on_undefined(),
+                   instr->hydrogen()->deoptimize_on_minus_zero(),
+                   instr->environment());
+}
+
+
+void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
+  Register result_reg = ToRegister(instr->result());
+  Register scratch1 = scratch0();
+  Register scratch2 = ToRegister(instr->temp());
+  DwVfpRegister double_input = ToDoubleRegister(instr->value());
+
+  Label done;
+
+  if (instr->truncating()) {
+    Register scratch3 = ToRegister(instr->temp2());
+    DwVfpRegister double_scratch = double_scratch0();
+    __ EmitECMATruncate(result_reg,
+                        double_input,
+                        double_scratch,
+                        scratch1,
+                        scratch2,
+                        scratch3);
+  } else {
+    DwVfpRegister double_scratch = double_scratch0();
+    __ EmitVFPTruncate(kRoundToMinusInf,
+                       result_reg,
+                       double_input,
+                       scratch1,
+                       double_scratch,
+                       kCheckForInexactConversion);
+
+    // Deoptimize if we had a vfp invalid exception,
+    // including inexact operation.
+    DeoptimizeIf(ne, instr->environment());
+  }
+    __ bind(&done);
+}
+
+
+void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
+  LOperand* input = instr->value();
+  __ TestIfSmi(ToRegister(input), r0);
+  DeoptimizeIf(ne, instr->environment(), cr0);
+}
+
+
+void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
+  LOperand* input = instr->value();
+  __ TestIfSmi(ToRegister(input), r0);
+  DeoptimizeIf(eq, instr->environment(), cr0);
+}
+
+
+void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
+  Register input = ToRegister(instr->value());
+  Register scratch = scratch0();
+
+  __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
+  __ lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+
+  if (instr->hydrogen()->is_interval_check()) {
+    InstanceType first;
+    InstanceType last;
+    instr->hydrogen()->GetCheckInterval(&first, &last);
+
+    __ cmpli(scratch, Operand(first));
+
+    // If there is only one type in the interval check for equality.
+    if (first == last) {
+      DeoptimizeIf(ne, instr->environment());
+    } else {
+      DeoptimizeIf(lt, instr->environment());
+      // Omit check for the last type.
+      if (last != LAST_TYPE) {
+        __ cmpli(scratch, Operand(last));
+        DeoptimizeIf(gt, instr->environment());
+      }
+    }
+  } else {
+    uint8_t mask;
+    uint8_t tag;
+    instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
+
+    if (IsPowerOf2(mask)) {
+      ASSERT(tag == 0 || IsPowerOf2(tag));
+      __ andi(r0, scratch, Operand(mask));
+      DeoptimizeIf(tag == 0 ? ne : eq, instr->environment(), cr0);
+    } else {
+      __ andi(scratch, scratch, Operand(mask));
+      __ cmpi(scratch, Operand(tag));
+      DeoptimizeIf(ne, instr->environment());
+    }
+  }
+}
+
+
+void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
+  Register reg = ToRegister(instr->value());
+  Handle<JSFunction> target = instr->hydrogen()->target();
+  if (isolate()->heap()->InNewSpace(*target)) {
+    Register reg = ToRegister(instr->value());
+    Handle<JSGlobalPropertyCell> cell =
+        isolate()->factory()->NewJSGlobalPropertyCell(target);
+    __ mov(ip, Operand(Handle<Object>(cell)));
+    __ LoadP(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
+    __ cmp(reg, ip);
+  } else {
+    __ Cmpi(reg, Operand(target), r0);
+  }
+  DeoptimizeIf(ne, instr->environment());
+}
+
+
+void LCodeGen::DoCheckMapCommon(Register reg,
+                                Register scratch,
+                                Handle<Map> map,
+                                CompareMapMode mode,
+                                LEnvironment* env) {
+  Label success;
+  __ CompareMap(reg, scratch, map, &success, mode);
+  DeoptimizeIf(ne, env);
+  __ bind(&success);
+}
+
+
+void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
+  Register scratch = scratch0();
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister());
+  Register reg = ToRegister(input);
+
+  Label success;
+  SmallMapList* map_set = instr->hydrogen()->map_set();
+  for (int i = 0; i < map_set->length() - 1; i++) {
+    Handle<Map> map = map_set->at(i);
+    __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP);
+    __ beq(&success);
+  }
+  Handle<Map> map = map_set->last();
+  DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment());
+  __ bind(&success);
+}
+
+
+void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
+  DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
+  Register result_reg = ToRegister(instr->result());
+  DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
+  __ ClampDoubleToUint8(result_reg, value_reg, temp_reg, double_scratch0());
+}
+
+
+void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
+  Register unclamped_reg = ToRegister(instr->unclamped());
+  Register result_reg = ToRegister(instr->result());
+  __ ClampUint8(result_reg, unclamped_reg);
+}
+
+
+void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
+  Register scratch = scratch0();
+  Register input_reg = ToRegister(instr->unclamped());
+  Register result_reg = ToRegister(instr->result());
+  DoubleRegister temp_reg1 = ToDoubleRegister(instr->temp1());
+  DoubleRegister temp_reg2 = ToDoubleRegister(instr->temp2());
+  Label is_smi, done, heap_number;
+
+  // Both smi and heap number cases are handled.
+  __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi);
+
+  // Check for heap number
+  __ LoadP(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+  __ Cmpi(scratch, Operand(factory()->heap_number_map()), r0);
+  __ beq(&heap_number);
+
+  // Check for undefined. Undefined is converted to zero for clamping
+  // conversions.
+  __ Cmpi(input_reg, Operand(factory()->undefined_value()), r0);
+  DeoptimizeIf(ne, instr->environment());
+  __ li(result_reg, Operand::Zero());
+  __ b(&done);
+
+  // Heap number
+  __ bind(&heap_number);
+  __ lfd(double_scratch0(), FieldMemOperand(input_reg,
+                                            HeapNumber::kValueOffset));
+  __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg1, temp_reg2);
+  __ b(&done);
+
+  // smi
+  __ bind(&is_smi);
+  __ ClampUint8(result_reg, result_reg);
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
+  Register temp1 = ToRegister(instr->temp());
+  Register temp2 = ToRegister(instr->temp2());
+
+  Handle<JSObject> holder = instr->holder();
+  Handle<JSObject> current_prototype = instr->prototype();
+
+  // Load prototype object.
+  __ LoadHeapObject(temp1, current_prototype);
+
+  // Check prototype maps up to the holder.
+  while (!current_prototype.is_identical_to(holder)) {
+    DoCheckMapCommon(temp1, temp2,
+                     Handle<Map>(current_prototype->map()),
+                     ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
+    current_prototype =
+        Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
+    // Load next prototype object.
+    __ LoadHeapObject(temp1, current_prototype);
+  }
+
+  // Check the holder map.
+  DoCheckMapCommon(temp1, temp2,
+                   Handle<Map>(current_prototype->map()),
+                   ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
+  DeoptimizeIf(ne, instr->environment());
+}
+
+
+void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
+  class DeferredAllocateObject: public LDeferredCode {
+   public:
+    DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LAllocateObject* instr_;
+  };
+
+  DeferredAllocateObject* deferred =
+      new(zone()) DeferredAllocateObject(this, instr);
+
+  Register result = ToRegister(instr->result());
+  Register scratch = ToRegister(instr->temp());
+  Register scratch2 = ToRegister(instr->temp2());
+  Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+  Handle<Map> initial_map(constructor->initial_map());
+  int instance_size = initial_map->instance_size();
+  ASSERT(initial_map->pre_allocated_property_fields() +
+         initial_map->unused_property_fields() -
+         initial_map->inobject_properties() == 0);
+
+  // Allocate memory for the object.  The initial map might change when
+  // the constructor's prototype changes, but instance size and property
+  // counts remain unchanged (if slack tracking finished).
+  ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
+  __ AllocateInNewSpace(instance_size,
+                        result,
+                        scratch,
+                        scratch2,
+                        deferred->entry(),
+                        TAG_OBJECT);
+
+  __ bind(deferred->exit());
+  if (FLAG_debug_code) {
+    Label is_in_new_space;
+    __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+    __ Abort("Allocated object is not in new-space");
+    __ bind(&is_in_new_space);
+  }
+
+  // Load the initial map.
+  Register map = scratch;
+  __ LoadHeapObject(map, constructor);
+  __ LoadP(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // Initialize map and fields of the newly allocated object.
+  ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
+  __ StoreP(map, FieldMemOperand(result, JSObject::kMapOffset), r0);
+  __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
+  __ StoreP(scratch, FieldMemOperand(result, JSObject::kElementsOffset), r0);
+  __ StoreP(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset), r0);
+  if (initial_map->inobject_properties() != 0) {
+    __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+    for (int i = 0; i < initial_map->inobject_properties(); i++) {
+      int property_offset = JSObject::kHeaderSize + i * kPointerSize;
+      __ StoreP(scratch, FieldMemOperand(result, property_offset), r0);
+    }
+  }
+}
+
+
+void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
+  Register result = ToRegister(instr->result());
+  Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+  Handle<Map> initial_map(constructor->initial_map());
+  int instance_size = initial_map->instance_size();
+
+  // TODO(3095996): Get rid of this. For now, we need to make the
+  // result register contain a valid pointer because it is already
+  // contained in the register pointer map.
+  __ li(result, Operand::Zero());
+
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  __ LoadSmiLiteral(r3, Smi::FromInt(instance_size));
+  __ push(r3);
+  CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
+  __ StoreToSafepointRegisterSlot(r3, result);
+}
+
+
+void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
+  Handle<FixedArray> literals(instr->environment()->closure()->literals());
+  ElementsKind boilerplate_elements_kind =
+      instr->hydrogen()->boilerplate_elements_kind();
+
+  // Deopt if the array literal boilerplate ElementsKind is of a type different
+  // than the expected one. The check isn't necessary if the boilerplate has
+  // already been converted to TERMINAL_FAST_ELEMENTS_KIND.
+  if (CanTransitionToMoreGeneralFastElementsKind(
+          boilerplate_elements_kind, true)) {
+    __ LoadHeapObject(r4, instr->hydrogen()->boilerplate_object());
+    // Load map into r5.
+    __ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+    // Load the map's "bit field 2".
+    __ lbz(r5, FieldMemOperand(r5, Map::kBitField2Offset));
+    // Retrieve elements_kind from bit field 2.
+    __ ExtractBitMask(r5, r5, Map::kElementsKindMask);
+    __ Cmpi(r5, Operand(boilerplate_elements_kind), r0);
+    DeoptimizeIf(ne, instr->environment());
+  }
+
+  // Set up the parameters to the stub/runtime call.
+  __ LoadHeapObject(r6, literals);
+  __ LoadSmiLiteral(r5, Smi::FromInt(instr->hydrogen()->literal_index()));
+  // Boilerplate already exists, constant elements are never accessed.
+  // Pass an empty fixed array.
+  __ mov(r4, Operand(isolate()->factory()->empty_fixed_array()));
+  __ Push(r6, r5, r4);
+
+  // Pick the right runtime function or stub to call.
+  int length = instr->hydrogen()->length();
+  if (instr->hydrogen()->IsCopyOnWrite()) {
+    ASSERT(instr->hydrogen()->depth() == 1);
+    FastCloneShallowArrayStub::Mode mode =
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
+    FastCloneShallowArrayStub stub(mode, length);
+    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  } else if (instr->hydrogen()->depth() > 1) {
+    CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
+    CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
+  } else {
+    FastCloneShallowArrayStub::Mode mode =
+        boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS
+            ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
+            : FastCloneShallowArrayStub::CLONE_ELEMENTS;
+    FastCloneShallowArrayStub stub(mode, length);
+    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  }
+}
+
+
+void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
+                            Register result,
+                            Register source,
+                            int* offset) {
+  ASSERT(!source.is(r5));
+  ASSERT(!result.is(r5));
+
+  // Only elements backing stores for non-COW arrays need to be copied.
+  Handle<FixedArrayBase> elements(object->elements());
+  bool has_elements = elements->length() > 0 &&
+      elements->map() != isolate()->heap()->fixed_cow_array_map();
+
+  // Increase the offset so that subsequent objects end up right after
+  // this object and its backing store.
+  int object_offset = *offset;
+  int object_size = object->map()->instance_size();
+  int elements_offset = *offset + object_size;
+  int elements_size = has_elements ? elements->Size() : 0;
+  *offset += object_size + elements_size;
+
+  // Copy object header.
+  ASSERT(object->properties()->length() == 0);
+  int inobject_properties = object->map()->inobject_properties();
+  int header_size = object_size - inobject_properties * kPointerSize;
+  for (int i = 0; i < header_size; i += kPointerSize) {
+    if (has_elements && i == JSObject::kElementsOffset) {
+      __ Add(r5, result, elements_offset, r0);
+    } else {
+      __ LoadP(r5, FieldMemOperand(source, i));
+    }
+    __ StoreP(r5, FieldMemOperand(result, object_offset + i), r0);
+  }
+
+  // Copy in-object properties.
+  for (int i = 0; i < inobject_properties; i++) {
+    int total_offset = object_offset + object->GetInObjectPropertyOffset(i);
+    Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i));
+    if (value->IsJSObject()) {
+      Handle<JSObject> value_object = Handle<JSObject>::cast(value);
+      __ Add(r5, result, *offset, r0);
+      __ StoreP(r5, FieldMemOperand(result, total_offset), r0);
+      __ LoadHeapObject(source, value_object);
+      EmitDeepCopy(value_object, result, source, offset);
+    } else if (value->IsHeapObject()) {
+      __ LoadHeapObject(r5, Handle<HeapObject>::cast(value));
+      __ StoreP(r5, FieldMemOperand(result, total_offset), r0);
+    } else {
+      __ mov(r5, Operand(value));
+      __ StoreP(r5, FieldMemOperand(result, total_offset), r0);
+    }
+  }
+
+  if (has_elements) {
+    // Copy elements backing store header.
+    __ LoadHeapObject(source, elements);
+    for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) {
+      __ LoadP(r5, FieldMemOperand(source, i));
+      __ StoreP(r5, FieldMemOperand(result, elements_offset + i), r0);
+    }
+
+    // Copy elements backing store content.
+    int elements_length = has_elements ? elements->length() : 0;
+    if (elements->IsFixedDoubleArray()) {
+      Handle<FixedDoubleArray> double_array =
+          Handle<FixedDoubleArray>::cast(elements);
+      for (int i = 0; i < elements_length; i++) {
+        int64_t value = double_array->get_representation(i);
+        int32_t value_low = static_cast<int32_t>(value & 0xFFFFFFFF);
+        int32_t value_high = static_cast<int32_t>(value >> 32);
+        int total_offset =
+            elements_offset + FixedDoubleArray::OffsetOfElementAt(i);
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+        __ mov(r5, Operand(value_low));
+        __ stw(r5, FieldMemOperand(result, total_offset));
+        __ mov(r5, Operand(value_high));
+        __ stw(r5, FieldMemOperand(result, total_offset + 4));
+#else
+        __ mov(r5, Operand(value_high));
+        __ stw(r5, FieldMemOperand(result, total_offset));
+        __ mov(r5, Operand(value_low));
+        __ stw(r5, FieldMemOperand(result, total_offset + 4));
+#endif
+      }
+    } else if (elements->IsFixedArray()) {
+      Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
+      for (int i = 0; i < elements_length; i++) {
+        int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
+        Handle<Object> value(fast_elements->get(i));
+        if (value->IsJSObject()) {
+          Handle<JSObject> value_object = Handle<JSObject>::cast(value);
+          __ Add(r5, result, *offset, r0);
+          __ StoreP(r5, FieldMemOperand(result, total_offset), r0);
+          __ LoadHeapObject(source, value_object);
+          EmitDeepCopy(value_object, result, source, offset);
+        } else if (value->IsHeapObject()) {
+          __ LoadHeapObject(r5, Handle<HeapObject>::cast(value));
+          __ StoreP(r5, FieldMemOperand(result, total_offset), r0);
+        } else {
+          __ mov(r5, Operand(value));
+          __ StoreP(r5, FieldMemOperand(result, total_offset), r0);
+        }
+      }
+    } else {
+      UNREACHABLE();
+    }
+  }
+}
+
+
+void LCodeGen::DoFastLiteral(LFastLiteral* instr) {
+  int size = instr->hydrogen()->total_size();
+  ElementsKind boilerplate_elements_kind =
+      instr->hydrogen()->boilerplate()->GetElementsKind();
+
+  // Deopt if the array literal boilerplate ElementsKind is of a type different
+  // than the expected one. The check isn't necessary if the boilerplate has
+  // already been converted to TERMINAL_FAST_ELEMENTS_KIND.
+  if (CanTransitionToMoreGeneralFastElementsKind(
+          boilerplate_elements_kind, true)) {
+    __ LoadHeapObject(r4, instr->hydrogen()->boilerplate());
+    // Load map into r5.
+    __ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+    // Load the map's "bit field 2".
+    __ lbz(r5, FieldMemOperand(r5, Map::kBitField2Offset));
+    // Retrieve elements_kind from bit field 2.
+    __ ExtractBitMask(r5, r5, Map::kElementsKindMask);
+    __ Cmpi(r5, Operand(boilerplate_elements_kind), r0);
+    DeoptimizeIf(ne, instr->environment());
+  }
+
+  // Allocate all objects that are part of the literal in one big
+  // allocation. This avoids multiple limit checks.
+  Label allocated, runtime_allocate;
+  __ AllocateInNewSpace(size, r3, r5, r6, &runtime_allocate, TAG_OBJECT);
+  __ b(&allocated);
+
+  __ bind(&runtime_allocate);
+  __ LoadSmiLiteral(r3, Smi::FromInt(size));
+  __ push(r3);
+  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
+
+  __ bind(&allocated);
+  int offset = 0;
+  __ LoadHeapObject(r4, instr->hydrogen()->boilerplate());
+  EmitDeepCopy(instr->hydrogen()->boilerplate(), r3, r4, &offset);
+  ASSERT_EQ(size, offset);
+}
+
+
+void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
+  Handle<FixedArray> literals(instr->environment()->closure()->literals());
+  Handle<FixedArray> constant_properties =
+      instr->hydrogen()->constant_properties();
+
+  // Set up the parameters to the stub/runtime call.
+  __ LoadHeapObject(r7, literals);
+  __ LoadSmiLiteral(r6, Smi::FromInt(instr->hydrogen()->literal_index()));
+  __ mov(r5, Operand(constant_properties));
+  int flags = instr->hydrogen()->fast_elements()
+      ? ObjectLiteral::kFastElements
+      : ObjectLiteral::kNoFlags;
+  __ LoadSmiLiteral(r4, Smi::FromInt(flags));
+  __ Push(r7, r6, r5, r4);
+
+  // Pick the right runtime function or stub to call.
+  int properties_count = constant_properties->length() / 2;
+  if (instr->hydrogen()->depth() > 1) {
+    CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
+  } else if (flags != ObjectLiteral::kFastElements ||
+      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
+    CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
+  } else {
+    FastCloneShallowObjectStub stub(properties_count);
+    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  }
+}
+
+
+void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
+  ASSERT(ToRegister(instr->value()).is(r3));
+  __ push(r3);
+  CallRuntime(Runtime::kToFastProperties, 1, instr);
+}
+
+
+void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
+  Label materialized;
+  // Registers will be used as follows:
+  // r10 = literals array.
+  // r4 = regexp literal.
+  // r3 = regexp literal clone.
+  // r5 and r7-r9 are used as temporaries.
+  int literal_offset =
+      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
+  __ LoadHeapObject(r10, instr->hydrogen()->literals());
+  __ LoadP(r4, FieldMemOperand(r10, literal_offset));
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ cmp(r4, ip);
+  __ bne(&materialized);
+
+  // Create regexp literal using runtime function
+  // Result will be in r3.
+  __ LoadSmiLiteral(r9, Smi::FromInt(instr->hydrogen()->literal_index()));
+  __ mov(r8, Operand(instr->hydrogen()->pattern()));
+  __ mov(r7, Operand(instr->hydrogen()->flags()));
+  __ Push(r10, r9, r8, r7);
+  CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
+  __ mr(r4, r3);
+
+  __ bind(&materialized);
+  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
+  Label allocated, runtime_allocate;
+
+  __ AllocateInNewSpace(size, r3, r5, r6, &runtime_allocate, TAG_OBJECT);
+  __ b(&allocated);
+
+  __ bind(&runtime_allocate);
+  __ LoadSmiLiteral(r3, Smi::FromInt(size));
+  __ Push(r4, r3);
+  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
+  __ pop(r4);
+
+  __ bind(&allocated);
+  // Copy the content into the newly allocated memory.
+  // (Unroll copy loop once for better throughput).
+  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
+    __ LoadP(r6, FieldMemOperand(r4, i));
+    __ LoadP(r5, FieldMemOperand(r4, i + kPointerSize));
+    __ StoreP(r6, FieldMemOperand(r3, i), r0);
+    __ StoreP(r5, FieldMemOperand(r3, i + kPointerSize), r0);
+  }
+  if ((size % (2 * kPointerSize)) != 0) {
+    __ LoadP(r6, FieldMemOperand(r4, size - kPointerSize));
+    __ StoreP(r6, FieldMemOperand(r3, size - kPointerSize), r0);
+  }
+}
+
+
+void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
+  // Use the fast case closure allocation code that allocates in new
+  // space for nested functions that don't need literals cloning.
+  Handle<SharedFunctionInfo> shared_info = instr->shared_info();
+  bool pretenure = instr->hydrogen()->pretenure();
+  if (!pretenure && shared_info->num_literals() == 0) {
+    FastNewClosureStub stub(shared_info->language_mode());
+    __ mov(r4, Operand(shared_info));
+    __ push(r4);
+    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+  } else {
+    __ mov(r5, Operand(shared_info));
+    __ mov(r4, Operand(pretenure
+                       ? factory()->true_value()
+                       : factory()->false_value()));
+    __ Push(cp, r5, r4);
+    CallRuntime(Runtime::kNewClosure, 3, instr);
+  }
+}
+
+
+void LCodeGen::DoTypeof(LTypeof* instr) {
+  Register input = ToRegister(instr->value());
+  __ push(input);
+  CallRuntime(Runtime::kTypeof, 1, instr);
+}
+
+
+void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
+  Register input = ToRegister(instr->value());
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+  Label* true_label = chunk_->GetAssemblyLabel(true_block);
+  Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+  Condition final_branch_condition = EmitTypeofIs(true_label,
+                                                  false_label,
+                                                  input,
+                                                  instr->type_literal());
+  if (final_branch_condition != kNoCondition) {
+    EmitBranch(true_block, false_block, final_branch_condition);
+  }
+}
+
+
+Condition LCodeGen::EmitTypeofIs(Label* true_label,
+                                 Label* false_label,
+                                 Register input,
+                                 Handle<String> type_name) {
+  Condition final_branch_condition = kNoCondition;
+  Register scratch = scratch0();
+  if (type_name->Equals(heap()->number_symbol())) {
+    __ JumpIfSmi(input, true_label);
+    __ LoadP(input, FieldMemOperand(input, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
+    __ cmp(input, ip);
+    final_branch_condition = eq;
+
+  } else if (type_name->Equals(heap()->string_symbol())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
+    __ bge(false_label);
+    __ lbz(ip, FieldMemOperand(input, Map::kBitFieldOffset));
+    __ ExtractBit(r0, ip, Map::kIsUndetectable);
+    __ cmpi(r0, Operand::Zero());
+    final_branch_condition = eq;
+
+  } else if (type_name->Equals(heap()->boolean_symbol())) {
+    __ CompareRoot(input, Heap::kTrueValueRootIndex);
+    __ beq(true_label);
+    __ CompareRoot(input, Heap::kFalseValueRootIndex);
+    final_branch_condition = eq;
+
+  } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
+    __ CompareRoot(input, Heap::kNullValueRootIndex);
+    final_branch_condition = eq;
+
+  } else if (type_name->Equals(heap()->undefined_symbol())) {
+    __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
+    __ beq(true_label);
+    __ JumpIfSmi(input, false_label);
+    // Check for undetectable objects => true.
+    __ LoadP(input, FieldMemOperand(input, HeapObject::kMapOffset));
+    __ lbz(ip, FieldMemOperand(input, Map::kBitFieldOffset));
+    __ ExtractBit(r0, ip, Map::kIsUndetectable);
+    __ cmpi(r0, Operand::Zero());
+    final_branch_condition = ne;
+
+  } else if (type_name->Equals(heap()->function_symbol())) {
+    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE);
+    __ beq(true_label);
+    __ cmpi(input, Operand(JS_FUNCTION_PROXY_TYPE));
+    final_branch_condition = eq;
+
+  } else if (type_name->Equals(heap()->object_symbol())) {
+    __ JumpIfSmi(input, false_label);
+    if (!FLAG_harmony_typeof) {
+      __ CompareRoot(input, Heap::kNullValueRootIndex);
+      __ beq(true_label);
+    }
+    __ CompareObjectType(input, input, scratch,
+                         FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
+    __ blt(false_label);
+    __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
+    __ bgt(false_label);
+    // Check for undetectable objects => false.
+    __ lbz(ip, FieldMemOperand(input, Map::kBitFieldOffset));
+    __ ExtractBit(r0, ip, Map::kIsUndetectable);
+    __ cmpi(r0, Operand::Zero());
+    final_branch_condition = eq;
+
+  } else {
+    __ b(false_label);
+  }
+
+  return final_branch_condition;
+}
+
+
+void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
+  Register temp1 = ToRegister(instr->temp());
+  int true_block = chunk_->LookupDestination(instr->true_block_id());
+  int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+  EmitIsConstructCall(temp1, scratch0());
+  EmitBranch(true_block, false_block, eq);
+}
+
+
+void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
+  ASSERT(!temp1.is(temp2));
+  // Get the frame pointer for the calling frame.
+  __ LoadP(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+
+  // Skip the arguments adaptor frame if it exists.
+  Label check_frame_marker;
+  __ LoadP(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
+  __ CmpSmiLiteral(temp2, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+  __ bne(&check_frame_marker);
+  __ LoadP(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
+
+  // Check the marker in the calling frame.
+  __ bind(&check_frame_marker);
+  __ LoadP(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
+  __ CmpSmiLiteral(temp1, Smi::FromInt(StackFrame::CONSTRUCT), r0);
+}
+
+
+void LCodeGen::EnsureSpaceForLazyDeopt() {
+  // Ensure that we have enough space after the previous lazy-bailout
+  // instruction for patching the code here.
+  int current_pc = masm()->pc_offset();
+  int patch_size = Deoptimizer::patch_size();
+  if (current_pc < last_lazy_deopt_pc_ + patch_size) {
+    int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc;
+    ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
+    while (padding_size > 0) {
+      __ nop();
+      padding_size -= Assembler::kInstrSize;
+    }
+  }
+  last_lazy_deopt_pc_ = masm()->pc_offset();
+}
+
+
+void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
+  EnsureSpaceForLazyDeopt();
+  ASSERT(instr->HasEnvironment());
+  LEnvironment* env = instr->environment();
+  RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
+}
+
+
+void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
+  DeoptimizeIf(al, instr->environment());
+}
+
+
+void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
+  Register object = ToRegister(instr->object());
+  Register key = ToRegister(instr->key());
+  Register strict = scratch0();
+  __ LoadSmiLiteral(strict, Smi::FromInt(strict_mode_flag()));
+  __ Push(object, key, strict);
+  ASSERT(instr->HasPointerMap());
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+  SafepointGenerator safepoint_generator(
+      this, pointers, Safepoint::kLazyDeopt);
+  __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
+}
+
+
+void LCodeGen::DoIn(LIn* instr) {
+  Register obj = ToRegister(instr->object());
+  Register key = ToRegister(instr->key());
+  __ Push(key, obj);
+  ASSERT(instr->HasPointerMap());
+  LPointerMap* pointers = instr->pointer_map();
+  RecordPosition(pointers->position());
+  SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
+  __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
+}
+
+
+void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
+  PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+  __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
+  RecordSafepointWithLazyDeopt(
+      instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+  ASSERT(instr->HasEnvironment());
+  LEnvironment* env = instr->environment();
+  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
+}
+
+
+void LCodeGen::DoStackCheck(LStackCheck* instr) {
+  class DeferredStackCheck: public LDeferredCode {
+   public:
+    DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
+        : LDeferredCode(codegen), instr_(instr) { }
+    virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
+    virtual LInstruction* instr() { return instr_; }
+   private:
+    LStackCheck* instr_;
+  };
+
+  ASSERT(instr->HasEnvironment());
+  LEnvironment* env = instr->environment();
+  // There is no LLazyBailout instruction for stack-checks. We have to
+  // prepare for lazy deoptimization explicitly here.
+  if (instr->hydrogen()->is_function_entry()) {
+    // Perform stack overflow check.
+    Label done;
+    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
+    __ cmpl(sp, ip);
+    __ bge(&done);
+    StackCheckStub stub;
+    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+    EnsureSpaceForLazyDeopt();
+    __ bind(&done);
+    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+    safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
+  } else {
+    ASSERT(instr->hydrogen()->is_backwards_branch());
+    // Perform stack overflow check if this goto needs it before jumping.
+    DeferredStackCheck* deferred_stack_check =
+        new(zone()) DeferredStackCheck(this, instr);
+    __ LoadRoot(ip, Heap::kStackLimitRootIndex);
+    __ cmpl(sp, ip);
+    __ blt(deferred_stack_check->entry());
+    EnsureSpaceForLazyDeopt();
+    __ bind(instr->done_label());
+    deferred_stack_check->SetExit(instr->done_label());
+    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+    // Don't record a deoptimization index for the safepoint here.
+    // This will be done explicitly when emitting call and the safepoint in
+    // the deferred code.
+  }
+}
+
+
+void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
+  // This is a pseudo-instruction that ensures that the environment here is
+  // properly registered for deoptimization and records the assembler's PC
+  // offset.
+  LEnvironment* environment = instr->environment();
+  environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
+                                   instr->SpilledDoubleRegisterArray());
+
+  // If the environment were already registered, we would have no way of
+  // backpatching it with the spill slot operands.
+  ASSERT(!environment->HasBeenRegistered());
+  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
+  ASSERT(osr_pc_offset_ == -1);
+  osr_pc_offset_ = masm()->pc_offset();
+}
+
+
+void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
+  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+  __ cmp(r3, ip);
+  DeoptimizeIf(eq, instr->environment());
+
+  Register null_value = r8;
+  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
+  __ cmp(r3, null_value);
+  DeoptimizeIf(eq, instr->environment());
+
+  __ TestIfSmi(r3, r0);
+  DeoptimizeIf(eq, instr->environment(), cr0);
+
+  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
+  __ CompareObjectType(r3, r4, r4, LAST_JS_PROXY_TYPE);
+  DeoptimizeIf(le, instr->environment());
+
+  Label use_cache, call_runtime;
+  __ CheckEnumCache(null_value, &call_runtime);
+
+  __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ b(&use_cache);
+
+  // Get the set of properties to enumerate.
+  __ bind(&call_runtime);
+  __ push(r3);
+  CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
+
+  __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kMetaMapRootIndex);
+  __ cmp(r4, ip);
+  DeoptimizeIf(ne, instr->environment());
+  __ bind(&use_cache);
+}
+
+
+void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
+  Register map = ToRegister(instr->map());
+  Register result = ToRegister(instr->result());
+  Label load_cache, done;
+  __ EnumLength(result, map);
+  __ CmpSmiLiteral(result, Smi::FromInt(0), r0);
+  __ bne(&load_cache);
+  __ mov(result, Operand(isolate()->factory()->empty_fixed_array()));
+  __ b(&done);
+
+  __ bind(&load_cache);
+  __ LoadInstanceDescriptors(map, result);
+  __ LoadP(result,
+           FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
+  __ LoadP(result,
+           FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
+  __ cmpi(result, Operand::Zero());
+  DeoptimizeIf(eq, instr->environment());
+
+  __ bind(&done);
+}
+
+
+void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
+  Register object = ToRegister(instr->value());
+  Register map = ToRegister(instr->map());
+  __ LoadP(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
+  __ cmp(map, scratch0());
+  DeoptimizeIf(ne, instr->environment());
+}
+
+
+void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
+  Register object = ToRegister(instr->object());
+  Register index = ToRegister(instr->index());
+  Register result = ToRegister(instr->result());
+  Register scratch = scratch0();
+
+  Label out_of_object, done;
+  __ cmpi(index, Operand::Zero());
+  __ blt(&out_of_object);
+
+  __ SmiToPtrArrayOffset(r0, index);
+  __ add(scratch, object, r0);
+  __ LoadP(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
+
+  __ b(&done);
+
+  __ bind(&out_of_object);
+  __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+  // Index is equal to negated out of object property index plus 1.
+  __ SmiToPtrArrayOffset(r0, index);
+  __ sub(scratch, result, r0);
+  __ LoadP(result, FieldMemOperand(scratch,
+                                   FixedArray::kHeaderSize - kPointerSize));
+  __ bind(&done);
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/src/ppc/lithium-codegen-ppc.h b/src/ppc/lithium-codegen-ppc.h
new file mode 100644
index 0000000..9ea4f44
--- /dev/null
+++ b/src/ppc/lithium-codegen-ppc.h
@@ -0,0 +1,479 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_LITHIUM_CODEGEN_PPC_H_
+#define V8_PPC_LITHIUM_CODEGEN_PPC_H_
+
+#include "ppc/lithium-ppc.h"
+#include "ppc/lithium-gap-resolver-ppc.h"
+#include "deoptimizer.h"
+#include "safepoint-table.h"
+#include "scopes.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class LDeferredCode;
+class SafepointGenerator;
+
+class LCodeGen BASE_EMBEDDED {
+ public:
+  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
+      : zone_(info->zone()),
+        chunk_(static_cast<LPlatformChunk*>(chunk)),
+        masm_(assembler),
+        info_(info),
+        current_block_(-1),
+        current_instruction_(-1),
+        instructions_(chunk->instructions()),
+        deoptimizations_(4, info->zone()),
+        deopt_jump_table_(4, info->zone()),
+        deoptimization_literals_(8, info->zone()),
+        inlined_function_count_(0),
+        scope_(info->scope()),
+        status_(UNUSED),
+        translations_(info->zone()),
+        deferred_(8, info->zone()),
+        osr_pc_offset_(-1),
+        last_lazy_deopt_pc_(0),
+        safepoints_(info->zone()),
+        resolver_(this),
+        expected_safepoint_kind_(Safepoint::kSimple) {
+    PopulateDeoptimizationLiteralsWithInlinedFunctions();
+  }
+
+
+  // Simple accessors.
+  MacroAssembler* masm() const { return masm_; }
+  CompilationInfo* info() const { return info_; }
+  Isolate* isolate() const { return info_->isolate(); }
+  Factory* factory() const { return isolate()->factory(); }
+  Heap* heap() const { return isolate()->heap(); }
+  Zone* zone() const { return zone_; }
+
+  // Support for converting LOperands to assembler types.
+  // LOperand must be a register.
+  Register ToRegister(LOperand* op) const;
+
+  // LOperand is loaded into scratch, unless already a register.
+  Register EmitLoadRegister(LOperand* op, Register scratch);
+
+  // LOperand must be a double register.
+  DoubleRegister ToDoubleRegister(LOperand* op) const;
+
+  /*
+  // LOperand is loaded into dbl_scratch, unless already a double register.
+  DoubleRegister EmitLoadDoubleRegister(LOperand* op,
+                                        SwVfpRegister flt_scratch,
+                                        DoubleRegister dbl_scratch);
+  */
+
+  int ToInteger32(LConstantOperand* op) const;
+  double ToDouble(LConstantOperand* op) const;
+  Operand ToOperand(LOperand* op);
+  MemOperand ToMemOperand(LOperand* op) const;
+  // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
+  MemOperand ToHighMemOperand(LOperand* op) const;
+
+  bool IsInteger32(LConstantOperand* op) const;
+  Handle<Object> ToHandle(LConstantOperand* op) const;
+
+  // Try to generate code for the entire chunk, but it may fail if the
+  // chunk contains constructs we cannot handle. Returns true if the
+  // code generation attempt succeeded.
+  bool GenerateCode();
+
+  // Finish the code by setting stack height, safepoint, and bailout
+  // information on it.
+  void FinishCode(Handle<Code> code);
+
+  // Deferred code support.
+  void DoDeferredNumberTagD(LNumberTagD* instr);
+
+  enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
+  void DoDeferredNumberTagI(LInstruction* instr,
+                            LOperand* value,
+                            IntegerSignedness signedness);
+
+  void DoDeferredTaggedToI(LTaggedToI* instr);
+  void DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr);
+  void DoDeferredStackCheck(LStackCheck* instr);
+  void DoDeferredRandom(LRandom* instr);
+  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
+  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
+  void DoDeferredAllocateObject(LAllocateObject* instr);
+  void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+                                       Label* map_check);
+
+  void DoCheckMapCommon(Register reg, Register scratch, Handle<Map> map,
+                        CompareMapMode mode, LEnvironment* env);
+
+  // Parallel move support.
+  void DoParallelMove(LParallelMove* move);
+  void DoGap(LGap* instr);
+
+  MemOperand PrepareKeyedOperand(Register key,
+                                 Register base,
+                                 bool key_is_constant,
+                                 bool key_is_tagged,
+                                 int constant_key,
+                                 int element_size_shift,
+                                 int additional_index,
+                                 int additional_offset);
+
+  // Emit frame translation commands for an environment.
+  void WriteTranslation(LEnvironment* environment,
+                        Translation* translation,
+                        int* arguments_index,
+                        int* arguments_count);
+
+  // Declare methods that deal with the individual node types.
+#define DECLARE_DO(type) void Do##type(L##type* node);
+  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
+#undef DECLARE_DO
+
+ private:
+  enum Status {
+    UNUSED,
+    GENERATING,
+    DONE,
+    ABORTED
+  };
+
+  bool is_unused() const { return status_ == UNUSED; }
+  bool is_generating() const { return status_ == GENERATING; }
+  bool is_done() const { return status_ == DONE; }
+  bool is_aborted() const { return status_ == ABORTED; }
+
+  StrictModeFlag strict_mode_flag() const {
+    return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
+  }
+
+  LPlatformChunk* chunk() const { return chunk_; }
+  Scope* scope() const { return scope_; }
+  HGraph* graph() const { return chunk_->graph(); }
+
+  Register scratch0() { return r11; }
+  DwVfpRegister double_scratch0() { return kScratchDoubleReg; }
+
+  int GetNextEmittedBlock(int block);
+  LInstruction* GetNextInstruction();
+
+  void EmitClassOfTest(Label* if_true,
+                       Label* if_false,
+                       Handle<String> class_name,
+                       Register input,
+                       Register temporary,
+                       Register temporary2);
+
+  int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
+  int GetParameterCount() const { return scope()->num_parameters(); }
+
+  void Abort(const char* reason);
+  void Comment(const char* format, ...);
+
+  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
+
+  // Code generation passes.  Returns true if code generation should
+  // continue.
+  bool GeneratePrologue();
+  bool GenerateBody();
+  bool GenerateDeferredCode();
+  bool GenerateDeoptJumpTable();
+  bool GenerateSafepointTable();
+
+  enum SafepointMode {
+    RECORD_SIMPLE_SAFEPOINT,
+    RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
+  };
+
+  void CallCode(Handle<Code> code,
+                RelocInfo::Mode mode,
+                LInstruction* instr);
+
+  void CallCodeGeneric(Handle<Code> code,
+                       RelocInfo::Mode mode,
+                       LInstruction* instr,
+                       SafepointMode safepoint_mode);
+
+  void CallRuntime(const Runtime::Function* function,
+                   int num_arguments,
+                   LInstruction* instr);
+
+  void CallRuntime(Runtime::FunctionId id,
+                   int num_arguments,
+                   LInstruction* instr) {
+    const Runtime::Function* function = Runtime::FunctionForId(id);
+    CallRuntime(function, num_arguments, instr);
+  }
+
+  void CallRuntimeFromDeferred(Runtime::FunctionId id,
+                               int argc,
+                               LInstruction* instr);
+
+  enum R4State {
+    R4_UNINITIALIZED,
+    R4_CONTAINS_TARGET
+  };
+
+  // Generate a direct call to a known function.  Expects the function
+  // to be in r4.
+  void CallKnownFunction(Handle<JSFunction> function,
+                         int arity,
+                         LInstruction* instr,
+                         CallKind call_kind,
+                         R4State r4_state);
+
+  void LoadHeapObject(Register result, Handle<HeapObject> object);
+
+  void RecordSafepointWithLazyDeopt(LInstruction* instr,
+                                    SafepointMode safepoint_mode);
+
+  void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
+                                            Safepoint::DeoptMode mode);
+  void DeoptimizeIf(Condition cc, LEnvironment* environment,
+                    CRegister cr = cr7);
+
+  void AddToTranslation(Translation* translation,
+                        LOperand* op,
+                        bool is_tagged,
+                        bool is_uint32,
+                        int arguments_index,
+                        int arguments_count);
+  void PopulateDeoptimizationData(Handle<Code> code);
+  int DefineDeoptimizationLiteral(Handle<Object> literal);
+
+  void PopulateDeoptimizationLiteralsWithInlinedFunctions();
+
+  Register ToRegister(int index) const;
+  DoubleRegister ToDoubleRegister(int index) const;
+
+  // Specific math operations - used from DoUnaryMathOperation.
+  void EmitIntegerMathAbs(LUnaryMathOperation* instr);
+  void DoMathAbs(LUnaryMathOperation* instr);
+  void DoMathFloor(LUnaryMathOperation* instr);
+  void DoMathRound(LUnaryMathOperation* instr);
+  void DoMathSqrt(LUnaryMathOperation* instr);
+  void DoMathPowHalf(LUnaryMathOperation* instr);
+  void DoMathLog(LUnaryMathOperation* instr);
+  void DoMathTan(LUnaryMathOperation* instr);
+  void DoMathCos(LUnaryMathOperation* instr);
+  void DoMathSin(LUnaryMathOperation* instr);
+
+  // Support for recording safepoint and position information.
+  void RecordSafepoint(LPointerMap* pointers,
+                       Safepoint::Kind kind,
+                       int arguments,
+                       Safepoint::DeoptMode mode);
+  void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
+  void RecordSafepoint(Safepoint::DeoptMode mode);
+  void RecordSafepointWithRegisters(LPointerMap* pointers,
+                                    int arguments,
+                                    Safepoint::DeoptMode mode);
+  void RecordPosition(int position);
+
+  static Condition TokenToCondition(Token::Value op);
+  void EmitGoto(int block);
+  void EmitBranch(int left_block, int right_block, Condition cc,
+                  CRegister cr = cr7);
+  void EmitNumberUntagD(Register input,
+                        DoubleRegister result,
+                        bool deoptimize_on_undefined,
+                        bool deoptimize_on_minus_zero,
+                        LEnvironment* env);
+
+  void DeoptIfTaggedButNotSmi(LEnvironment* environment,
+                              HValue* value,
+                              LOperand* operand);
+
+  // Emits optimized code for typeof x == "y".  Modifies input register.
+  // Returns the condition on which a final split to
+  // true and false label should be made, to optimize fallthrough.
+  Condition EmitTypeofIs(Label* true_label,
+                         Label* false_label,
+                         Register input,
+                         Handle<String> type_name);
+
+  // Emits optimized code for %_IsObject(x).  Preserves input register.
+  // Returns the condition on which a final split to
+  // true and false label should be made, to optimize fallthrough.
+  Condition EmitIsObject(Register input,
+                         Register temp1,
+                         Label* is_not_object,
+                         Label* is_object);
+
+  // Emits optimized code for %_IsString(x).  Preserves input register.
+  // Returns the condition on which a final split to
+  // true and false label should be made, to optimize fallthrough.
+  Condition EmitIsString(Register input,
+                         Register temp1,
+                         Label* is_not_string);
+
+  // Emits optimized code for %_IsConstructCall().
+  // Caller should branch on equal condition.
+  void EmitIsConstructCall(Register temp1, Register temp2);
+
+  void EmitLoadFieldOrConstantFunction(Register result,
+                                       Register object,
+                                       Handle<Map> type,
+                                       Handle<String> name,
+                                       LEnvironment* env);
+
+  // Emits optimized code to deep-copy the contents of statically known
+  // object graphs (e.g. object literal boilerplate).
+  void EmitDeepCopy(Handle<JSObject> object,
+                    Register result,
+                    Register source,
+                    int* offset);
+
+  // Emit optimized code for integer division.
+  // Inputs are signed.
+  // All registers are clobbered.
+  // If 'remainder' is no_reg, it is not computed.
+  void EmitSignedIntegerDivisionByConstant(Register result,
+                                           Register dividend,
+                                           int32_t divisor,
+                                           Register remainder,
+                                           Register scratch,
+                                           LEnvironment* environment);
+
+  struct JumpTableEntry {
+    explicit inline JumpTableEntry(Address entry)
+        : label(),
+          address(entry) { }
+    Label label;
+    Address address;
+  };
+
+  void EnsureSpaceForLazyDeopt();
+
+  Zone* zone_;
+  LPlatformChunk* const chunk_;
+  MacroAssembler* const masm_;
+  CompilationInfo* const info_;
+
+  int current_block_;
+  int current_instruction_;
+  const ZoneList<LInstruction*>* instructions_;
+  ZoneList<LEnvironment*> deoptimizations_;
+  ZoneList<JumpTableEntry> deopt_jump_table_;
+  ZoneList<Handle<Object> > deoptimization_literals_;
+  int inlined_function_count_;
+  Scope* const scope_;
+  Status status_;
+  TranslationBuffer translations_;
+  ZoneList<LDeferredCode*> deferred_;
+  int osr_pc_offset_;
+  int last_lazy_deopt_pc_;
+
+  // Builder that keeps track of safepoints in the code. The table
+  // itself is emitted at the end of the generated code.
+  SafepointTableBuilder safepoints_;
+
+  // Compiler from a set of parallel moves to a sequential list of moves.
+  LGapResolver resolver_;
+
+  Safepoint::Kind expected_safepoint_kind_;
+
+  class PushSafepointRegistersScope BASE_EMBEDDED {
+   public:
+    PushSafepointRegistersScope(LCodeGen* codegen,
+                                Safepoint::Kind kind)
+        : codegen_(codegen) {
+      ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
+      codegen_->expected_safepoint_kind_ = kind;
+
+      switch (codegen_->expected_safepoint_kind_) {
+        case Safepoint::kWithRegisters:
+          codegen_->masm_->PushSafepointRegisters();
+          break;
+        default:
+          UNREACHABLE();
+      }
+    }
+
+    ~PushSafepointRegistersScope() {
+      Safepoint::Kind kind = codegen_->expected_safepoint_kind_;
+      ASSERT((kind & Safepoint::kWithRegisters) != 0);
+      switch (kind) {
+        case Safepoint::kWithRegisters:
+          codegen_->masm_->PopSafepointRegisters();
+          break;
+        default:
+          UNREACHABLE();
+      }
+      codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
+    }
+
+   private:
+    LCodeGen* codegen_;
+  };
+
+  friend class LDeferredCode;
+  friend class LEnvironment;
+  friend class SafepointGenerator;
+  DISALLOW_COPY_AND_ASSIGN(LCodeGen);
+};
+
+
+class LDeferredCode: public ZoneObject {
+ public:
+  explicit LDeferredCode(LCodeGen* codegen)
+      : codegen_(codegen),
+        external_exit_(NULL),
+        instruction_index_(codegen->current_instruction_) {
+    codegen->AddDeferredCode(this);
+  }
+
+  virtual ~LDeferredCode() { }
+  virtual void Generate() = 0;
+  virtual LInstruction* instr() = 0;
+
+  void SetExit(Label* exit) { external_exit_ = exit; }
+  Label* entry() { return &entry_; }
+  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
+  int instruction_index() const { return instruction_index_; }
+
+ protected:
+  LCodeGen* codegen() const { return codegen_; }
+  MacroAssembler* masm() const { return codegen_->masm(); }
+
+ private:
+  LCodeGen* codegen_;
+  Label entry_;
+  Label exit_;
+  Label* external_exit_;
+  int instruction_index_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_LITHIUM_CODEGEN_PPC_H_
diff --git a/src/ppc/lithium-gap-resolver-ppc.cc b/src/ppc/lithium-gap-resolver-ppc.cc
new file mode 100644
index 0000000..7c4d900
--- /dev/null
+++ b/src/ppc/lithium-gap-resolver-ppc.cc
@@ -0,0 +1,311 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "ppc/lithium-gap-resolver-ppc.h"
+#include "ppc/lithium-codegen-ppc.h"
+
+namespace v8 {
+namespace internal {
+
+static const Register kSavedValueRegister = { 11 };
+
+LGapResolver::LGapResolver(LCodeGen* owner)
+    : cgen_(owner), moves_(32, owner->zone()), root_index_(0), in_cycle_(false),
+      saved_destination_(NULL) { }
+
+
+void LGapResolver::Resolve(LParallelMove* parallel_move) {
+  ASSERT(moves_.is_empty());
+  // Build up a worklist of moves.
+  BuildInitialMoveList(parallel_move);
+
+  for (int i = 0; i < moves_.length(); ++i) {
+    LMoveOperands move = moves_[i];
+    // Skip constants to perform them last.  They don't block other moves
+    // and skipping such moves with register destinations keeps those
+    // registers free for the whole algorithm.
+    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
+      root_index_ = i;  // Any cycle is found when by reaching this move again.
+      PerformMove(i);
+      if (in_cycle_) {
+        RestoreValue();
+      }
+    }
+  }
+
+  // Perform the moves with constant sources.
+  for (int i = 0; i < moves_.length(); ++i) {
+    if (!moves_[i].IsEliminated()) {
+      ASSERT(moves_[i].source()->IsConstantOperand());
+      EmitMove(i);
+    }
+  }
+
+  moves_.Rewind(0);
+}
+
+
+void LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
+  // Perform a linear sweep of the moves to add them to the initial list of
+  // moves to perform, ignoring any move that is redundant (the source is
+  // the same as the destination, the destination is ignored and
+  // unallocated, or the move was already eliminated).
+  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
+  for (int i = 0; i < moves->length(); ++i) {
+    LMoveOperands move = moves->at(i);
+    if (!move.IsRedundant()) moves_.Add(move, cgen_->zone());
+  }
+  Verify();
+}
+
+
+void LGapResolver::PerformMove(int index) {
+  // Each call to this function performs a move and deletes it from the move
+  // graph.  We first recursively perform any move blocking this one.  We
+  // mark a move as "pending" on entry to PerformMove in order to detect
+  // cycles in the move graph.
+
+  // We can only find a cycle, when doing a depth-first traversal of moves,
+  // be encountering the starting move again. So by spilling the source of
+  // the starting move, we break the cycle.  All moves are then unblocked,
+  // and the starting move is completed by writing the spilled value to
+  // its destination.  All other moves from the spilled source have been
+  // completed prior to breaking the cycle.
+  // An additional complication is that moves to MemOperands with large
+  // offsets (more than 1K or 4K) require us to spill this spilled value to
+  // the stack, to free up the register.
+  ASSERT(!moves_[index].IsPending());
+  ASSERT(!moves_[index].IsRedundant());
+
+  // Clear this move's destination to indicate a pending move.  The actual
+  // destination is saved in a stack allocated local.  Multiple moves can
+  // be pending because this function is recursive.
+  ASSERT(moves_[index].source() != NULL);  // Or else it will look eliminated.
+  LOperand* destination = moves_[index].destination();
+  moves_[index].set_destination(NULL);
+
+  // Perform a depth-first traversal of the move graph to resolve
+  // dependencies.  Any unperformed, unpending move with a source the same
+  // as this one's destination blocks this one so recursively perform all
+  // such moves.
+  for (int i = 0; i < moves_.length(); ++i) {
+    LMoveOperands other_move = moves_[i];
+    if (other_move.Blocks(destination) && !other_move.IsPending()) {
+      PerformMove(i);
+      // If there is a blocking, pending move it must be moves_[root_index_]
+      // and all other moves with the same source as moves_[root_index_] are
+      // sucessfully executed (because they are cycle-free) by this loop.
+    }
+  }
+
+  // We are about to resolve this move and don't need it marked as
+  // pending, so restore its destination.
+  moves_[index].set_destination(destination);
+
+  // The move may be blocked on a pending move, which must be the starting move.
+  // In this case, we have a cycle, and we save the source of this move to
+  // a scratch register to break it.
+  LMoveOperands other_move = moves_[root_index_];
+  if (other_move.Blocks(destination)) {
+    ASSERT(other_move.IsPending());
+    BreakCycle(index);
+    return;
+  }
+
+  // This move is no longer blocked.
+  EmitMove(index);
+}
+
+
+void LGapResolver::Verify() {
+#ifdef ENABLE_SLOW_ASSERTS
+  // No operand should be the destination for more than one move.
+  for (int i = 0; i < moves_.length(); ++i) {
+    LOperand* destination = moves_[i].destination();
+    for (int j = i + 1; j < moves_.length(); ++j) {
+      SLOW_ASSERT(!destination->Equals(moves_[j].destination()));
+    }
+  }
+#endif
+}
+
+#define __ ACCESS_MASM(cgen_->masm())
+
+void LGapResolver::BreakCycle(int index) {
+  // We save in a register the value that should end up in the source of
+  // moves_[root_index].  After performing all moves in the tree rooted
+  // in that move, we save the value to that source.
+  ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
+  ASSERT(!in_cycle_);
+  in_cycle_ = true;
+  LOperand* source = moves_[index].source();
+  saved_destination_ = moves_[index].destination();
+  if (source->IsRegister()) {
+    __ mr(kSavedValueRegister, cgen_->ToRegister(source));
+  } else if (source->IsStackSlot()) {
+    __ LoadP(kSavedValueRegister, cgen_->ToMemOperand(source));
+  } else if (source->IsDoubleRegister()) {
+    __ fmr(kScratchDoubleReg, cgen_->ToDoubleRegister(source));
+  } else if (source->IsDoubleStackSlot()) {
+    __ lfd(kScratchDoubleReg, cgen_->ToMemOperand(source));
+  } else {
+    UNREACHABLE();
+  }
+  // This move will be done by restoring the saved value to the destination.
+  moves_[index].Eliminate();
+}
+
+
+void LGapResolver::RestoreValue() {
+  ASSERT(in_cycle_);
+  ASSERT(saved_destination_ != NULL);
+
+  // Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister.
+  if (saved_destination_->IsRegister()) {
+    __ mr(cgen_->ToRegister(saved_destination_), kSavedValueRegister);
+  } else if (saved_destination_->IsStackSlot()) {
+    __ StoreP(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
+  } else if (saved_destination_->IsDoubleRegister()) {
+    __ fmr(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg);
+  } else if (saved_destination_->IsDoubleStackSlot()) {
+    __ stfd(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_));
+  } else {
+    UNREACHABLE();
+  }
+
+  in_cycle_ = false;
+  saved_destination_ = NULL;
+}
+
+
+void LGapResolver::EmitMove(int index) {
+  LOperand* source = moves_[index].source();
+  LOperand* destination = moves_[index].destination();
+
+  // Dispatch on the source and destination operand kinds.  Not all
+  // combinations are possible.
+
+  if (source->IsRegister()) {
+    Register source_register = cgen_->ToRegister(source);
+    if (destination->IsRegister()) {
+      __ mr(cgen_->ToRegister(destination), source_register);
+    } else {
+      ASSERT(destination->IsStackSlot());
+      __ StoreP(source_register, cgen_->ToMemOperand(destination));
+    }
+
+  } else if (source->IsStackSlot()) {
+    MemOperand source_operand = cgen_->ToMemOperand(source);
+    if (destination->IsRegister()) {
+      __ LoadP(cgen_->ToRegister(destination), source_operand);
+    } else {
+      ASSERT(destination->IsStackSlot());
+      MemOperand destination_operand = cgen_->ToMemOperand(destination);
+      if (in_cycle_) {
+        __ LoadP(ip, source_operand);
+        __ StoreP(ip, destination_operand);
+      } else {
+        __ LoadP(kSavedValueRegister, source_operand);
+        __ StoreP(kSavedValueRegister, destination_operand);
+      }
+    }
+
+  } else if (source->IsConstantOperand()) {
+    LConstantOperand* constant_source = LConstantOperand::cast(source);
+    if (destination->IsRegister()) {
+      Register dst = cgen_->ToRegister(destination);
+      if (cgen_->IsInteger32(constant_source)) {
+        __ LoadIntLiteral(dst, cgen_->ToInteger32(constant_source));
+      } else {
+        __ LoadObject(dst, cgen_->ToHandle(constant_source));
+      }
+    } else {
+      ASSERT(destination->IsStackSlot());
+      ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
+      if (cgen_->IsInteger32(constant_source)) {
+        __ LoadIntLiteral(kSavedValueRegister,
+                          cgen_->ToInteger32(constant_source));
+      } else {
+        __ LoadObject(kSavedValueRegister,
+                      cgen_->ToHandle(constant_source));
+      }
+      __ StoreP(kSavedValueRegister, cgen_->ToMemOperand(destination));
+    }
+
+  } else if (source->IsDoubleRegister()) {
+    DoubleRegister source_register = cgen_->ToDoubleRegister(source);
+    if (destination->IsDoubleRegister()) {
+      __ fmr(cgen_->ToDoubleRegister(destination), source_register);
+    } else {
+      ASSERT(destination->IsDoubleStackSlot());
+      __ stfd(source_register, cgen_->ToMemOperand(destination));
+    }
+
+  } else if (source->IsDoubleStackSlot()) {
+    MemOperand source_operand = cgen_->ToMemOperand(source);
+    if (destination->IsDoubleRegister()) {
+      __ lfd(cgen_->ToDoubleRegister(destination), source_operand);
+    } else {
+      ASSERT(destination->IsDoubleStackSlot());
+      MemOperand destination_operand = cgen_->ToMemOperand(destination);
+      if (in_cycle_) {
+        // kSavedDoubleValueRegister was used to break the cycle,
+        // but kSavedValueRegister is free.
+#if V8_TARGET_ARCH_PPC64
+        __ ld(kSavedValueRegister, source_operand);
+        __ std(kSavedValueRegister, destination_operand);
+#else
+        MemOperand source_high_operand =
+            cgen_->ToHighMemOperand(source);
+        MemOperand destination_high_operand =
+            cgen_->ToHighMemOperand(destination);
+        __ lwz(kSavedValueRegister, source_operand);
+        __ stw(kSavedValueRegister, destination_operand);
+        __ lwz(kSavedValueRegister, source_high_operand);
+        __ stw(kSavedValueRegister, destination_high_operand);
+#endif
+      } else {
+        __ lfd(kScratchDoubleReg, source_operand);
+        __ stfd(kScratchDoubleReg, destination_operand);
+      }
+    }
+  } else {
+    UNREACHABLE();
+  }
+
+  moves_[index].Eliminate();
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
diff --git a/src/ppc/lithium-gap-resolver-ppc.h b/src/ppc/lithium-gap-resolver-ppc.h
new file mode 100644
index 0000000..3eab3de
--- /dev/null
+++ b/src/ppc/lithium-gap-resolver-ppc.h
@@ -0,0 +1,86 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_LITHIUM_GAP_RESOLVER_PPC_H_
+#define V8_PPC_LITHIUM_GAP_RESOLVER_PPC_H_
+
+#include "v8.h"
+
+#include "lithium.h"
+
+namespace v8 {
+namespace internal {
+
+class LCodeGen;
+class LGapResolver;
+
+class LGapResolver BASE_EMBEDDED {
+ public:
+  explicit LGapResolver(LCodeGen* owner);
+
+  // Resolve a set of parallel moves, emitting assembler instructions.
+  void Resolve(LParallelMove* parallel_move);
+
+ private:
+  // Build the initial list of moves.
+  void BuildInitialMoveList(LParallelMove* parallel_move);
+
+  // Perform the move at the moves_ index in question (possibly requiring
+  // other moves to satisfy dependencies).
+  void PerformMove(int index);
+
+  // If a cycle is found in the series of moves, save the blocking value to
+  // a scratch register.  The cycle must be found by hitting the root of the
+  // depth-first search.
+  void BreakCycle(int index);
+
+  // After a cycle has been resolved, restore the value from the scratch
+  // register to its proper destination.
+  void RestoreValue();
+
+  // Emit a move and remove it from the move graph.
+  void EmitMove(int index);
+
+  // Verify the move list before performing moves.
+  void Verify();
+
+  LCodeGen* cgen_;
+
+  // List of moves not yet resolved.
+  ZoneList<LMoveOperands> moves_;
+
+  int root_index_;
+  bool in_cycle_;
+  LOperand* saved_destination_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_LITHIUM_GAP_RESOLVER_PPC_H_
diff --git a/src/ppc/lithium-ppc.cc b/src/ppc/lithium-ppc.cc
new file mode 100644
index 0000000..dfdb6e5
--- /dev/null
+++ b/src/ppc/lithium-ppc.cc
@@ -0,0 +1,2323 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "lithium-allocator-inl.h"
+#include "ppc/lithium-ppc.h"
+#include "ppc/lithium-codegen-ppc.h"
+
+namespace v8 {
+namespace internal {
+
+#define DEFINE_COMPILE(type)                            \
+  void L##type::CompileToNative(LCodeGen* generator) {  \
+    generator->Do##type(this);                          \
+  }
+LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
+#undef DEFINE_COMPILE
+
+LOsrEntry::LOsrEntry() {
+  for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
+    register_spills_[i] = NULL;
+  }
+  for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
+    double_register_spills_[i] = NULL;
+  }
+}
+
+
+void LOsrEntry::MarkSpilledRegister(int allocation_index,
+                                    LOperand* spill_operand) {
+  ASSERT(spill_operand->IsStackSlot());
+  ASSERT(register_spills_[allocation_index] == NULL);
+  register_spills_[allocation_index] = spill_operand;
+}
+
+
+#ifdef DEBUG
+void LInstruction::VerifyCall() {
+  // Call instructions can use only fixed registers as temporaries and
+  // outputs because all registers are blocked by the calling convention.
+  // Inputs operands must use a fixed register or use-at-start policy or
+  // a non-register policy.
+  ASSERT(Output() == NULL ||
+         LUnallocated::cast(Output())->HasFixedPolicy() ||
+         !LUnallocated::cast(Output())->HasRegisterPolicy());
+  for (UseIterator it(this); !it.Done(); it.Advance()) {
+    LUnallocated* operand = LUnallocated::cast(it.Current());
+    ASSERT(operand->HasFixedPolicy() ||
+           operand->IsUsedAtStart());
+  }
+  for (TempIterator it(this); !it.Done(); it.Advance()) {
+    LUnallocated* operand = LUnallocated::cast(it.Current());
+    ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
+  }
+}
+#endif
+
+
+void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
+                                          LOperand* spill_operand) {
+  ASSERT(spill_operand->IsDoubleStackSlot());
+  ASSERT(double_register_spills_[allocation_index] == NULL);
+  double_register_spills_[allocation_index] = spill_operand;
+}
+
+
+void LInstruction::PrintTo(StringStream* stream) {
+  stream->Add("%s ", this->Mnemonic());
+
+  PrintOutputOperandTo(stream);
+
+  PrintDataTo(stream);
+
+  if (HasEnvironment()) {
+    stream->Add(" ");
+    environment()->PrintTo(stream);
+  }
+
+  if (HasPointerMap()) {
+    stream->Add(" ");
+    pointer_map()->PrintTo(stream);
+  }
+}
+
+
+void LInstruction::PrintDataTo(StringStream* stream) {
+  stream->Add("= ");
+  for (int i = 0; i < InputCount(); i++) {
+    if (i > 0) stream->Add(" ");
+    InputAt(i)->PrintTo(stream);
+  }
+}
+
+
+void LInstruction::PrintOutputOperandTo(StringStream* stream) {
+  if (HasResult()) result()->PrintTo(stream);
+}
+
+
+void LLabel::PrintDataTo(StringStream* stream) {
+  LGap::PrintDataTo(stream);
+  LLabel* rep = replacement();
+  if (rep != NULL) {
+    stream->Add(" Dead block replaced with B%d", rep->block_id());
+  }
+}
+
+
+bool LGap::IsRedundant() const {
+  for (int i = 0; i < 4; i++) {
+    if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
+void LGap::PrintDataTo(StringStream* stream) {
+  for (int i = 0; i < 4; i++) {
+    stream->Add("(");
+    if (parallel_moves_[i] != NULL) {
+      parallel_moves_[i]->PrintDataTo(stream);
+    }
+    stream->Add(") ");
+  }
+}
+
+
+const char* LArithmeticD::Mnemonic() const {
+  switch (op()) {
+    case Token::ADD: return "add-d";
+    case Token::SUB: return "sub-d";
+    case Token::MUL: return "mul-d";
+    case Token::DIV: return "div-d";
+    case Token::MOD: return "mod-d";
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+}
+
+
+const char* LArithmeticT::Mnemonic() const {
+  switch (op()) {
+    case Token::ADD: return "add-t";
+    case Token::SUB: return "sub-t";
+    case Token::MUL: return "mul-t";
+    case Token::MOD: return "mod-t";
+    case Token::DIV: return "div-t";
+    case Token::BIT_AND: return "bit-and-t";
+    case Token::BIT_OR: return "bit-or-t";
+    case Token::BIT_XOR: return "bit-xor-t";
+    case Token::SHL: return "shl-t";
+    case Token::SAR: return "sar-t";
+    case Token::SHR: return "shr-t";
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+}
+
+
+void LGoto::PrintDataTo(StringStream* stream) {
+  stream->Add("B%d", block_id());
+}
+
+
+void LBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
+  value()->PrintTo(stream);
+}
+
+
+void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if ");
+  left()->PrintTo(stream);
+  stream->Add(" %s ", Token::String(op()));
+  right()->PrintTo(stream);
+  stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LIsNilAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if ");
+  value()->PrintTo(stream);
+  stream->Add(kind() == kStrictEquality ? " === " : " == ");
+  stream->Add(nil() == kNullValue ? "null" : "undefined");
+  stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if is_object(");
+  value()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if is_string(");
+  value()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if is_smi(");
+  value()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if is_undetectable(");
+  value()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if string_compare(");
+  left()->PrintTo(stream);
+  right()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if has_instance_type(");
+  value()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if has_cached_array_index(");
+  value()->PrintTo(stream);
+  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
+}
+
+
+void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if class_of_test(");
+  value()->PrintTo(stream);
+  stream->Add(", \"%o\") then B%d else B%d",
+              *hydrogen()->class_name(),
+              true_block_id(),
+              false_block_id());
+}
+
+
+void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
+  stream->Add("if typeof ");
+  value()->PrintTo(stream);
+  stream->Add(" == \"%s\" then B%d else B%d",
+              *hydrogen()->type_literal()->ToCString(),
+              true_block_id(), false_block_id());
+}
+
+
+void LCallConstantFunction::PrintDataTo(StringStream* stream) {
+  stream->Add("#%d / ", arity());
+}
+
+
+void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
+  stream->Add("/%s ", hydrogen()->OpName());
+  value()->PrintTo(stream);
+}
+
+
+void LLoadContextSlot::PrintDataTo(StringStream* stream) {
+  context()->PrintTo(stream);
+  stream->Add("[%d]", slot_index());
+}
+
+
+void LStoreContextSlot::PrintDataTo(StringStream* stream) {
+  context()->PrintTo(stream);
+  stream->Add("[%d] <- ", slot_index());
+  value()->PrintTo(stream);
+}
+
+
+void LInvokeFunction::PrintDataTo(StringStream* stream) {
+  stream->Add("= ");
+  function()->PrintTo(stream);
+  stream->Add(" #%d / ", arity());
+}
+
+
+void LCallKeyed::PrintDataTo(StringStream* stream) {
+  stream->Add("[r5] #%d / ", arity());
+}
+
+
+void LCallNamed::PrintDataTo(StringStream* stream) {
+  SmartArrayPointer<char> name_string = name()->ToCString();
+  stream->Add("%s #%d / ", *name_string, arity());
+}
+
+
+void LCallGlobal::PrintDataTo(StringStream* stream) {
+  SmartArrayPointer<char> name_string = name()->ToCString();
+  stream->Add("%s #%d / ", *name_string, arity());
+}
+
+
+void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
+  stream->Add("#%d / ", arity());
+}
+
+
+void LCallNew::PrintDataTo(StringStream* stream) {
+  stream->Add("= ");
+  constructor()->PrintTo(stream);
+  stream->Add(" #%d / ", arity());
+}
+
+
+void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
+  arguments()->PrintTo(stream);
+  stream->Add(" length ");
+  length()->PrintTo(stream);
+  stream->Add(" index ");
+  index()->PrintTo(stream);
+}
+
+
+void LStoreNamedField::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add(".");
+  stream->Add(*String::cast(*name())->ToCString());
+  stream->Add(" <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add(".");
+  stream->Add(*String::cast(*name())->ToCString());
+  stream->Add(" <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add("[");
+  key()->PrintTo(stream);
+  stream->Add("] <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
+  elements()->PrintTo(stream);
+  stream->Add("[");
+  key()->PrintTo(stream);
+  stream->Add("] <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add("[");
+  key()->PrintTo(stream);
+  stream->Add("] <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add(" %p -> %p", *original_map(), *transitioned_map());
+}
+
+
+int LPlatformChunk::GetNextSpillIndex(bool is_double) {
+  // Skip a slot if for a double-width slot.
+  if (is_double) spill_slot_count_++;
+  return spill_slot_count_++;
+}
+
+
+LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double)  {
+  int index = GetNextSpillIndex(is_double);
+  if (is_double) {
+    return LDoubleStackSlot::Create(index, zone());
+  } else {
+    return LStackSlot::Create(index, zone());
+  }
+}
+
+
+LPlatformChunk* LChunkBuilder::Build() {
+  ASSERT(is_unused());
+  chunk_ = new(zone()) LPlatformChunk(info(), graph());
+  HPhase phase("L_Building chunk", chunk_);
+  status_ = BUILDING;
+  const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
+  for (int i = 0; i < blocks->length(); i++) {
+    HBasicBlock* next = NULL;
+    if (i < blocks->length() - 1) next = blocks->at(i + 1);
+    DoBasicBlock(blocks->at(i), next);
+    if (is_aborted()) return NULL;
+  }
+  status_ = DONE;
+  return chunk_;
+}
+
+
+void LChunkBuilder::Abort(const char* reason) {
+  info()->set_bailout_reason(reason);
+  status_ = ABORTED;
+}
+
+
+LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
+  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+                                  Register::ToAllocationIndex(reg));
+}
+
+
+LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
+  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+                                  DoubleRegister::ToAllocationIndex(reg));
+}
+
+
+LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
+  return Use(value, ToUnallocated(fixed_register));
+}
+
+
+LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
+  return Use(value, ToUnallocated(reg));
+}
+
+
+LOperand* LChunkBuilder::UseRegister(HValue* value) {
+  return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+}
+
+
+LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
+  return Use(value,
+             new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
+                                      LUnallocated::USED_AT_START));
+}
+
+
+LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
+  return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
+}
+
+
+LOperand* LChunkBuilder::Use(HValue* value) {
+  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
+}
+
+
+LOperand* LChunkBuilder::UseAtStart(HValue* value) {
+  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
+                                             LUnallocated::USED_AT_START));
+}
+
+
+LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
+  return value->IsConstant()
+      ? chunk_->DefineConstantOperand(HConstant::cast(value))
+      : Use(value);
+}
+
+
+LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
+  return value->IsConstant()
+      ? chunk_->DefineConstantOperand(HConstant::cast(value))
+      : UseAtStart(value);
+}
+
+
+LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
+  return value->IsConstant()
+      ? chunk_->DefineConstantOperand(HConstant::cast(value))
+      : UseRegister(value);
+}
+
+
+LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
+  return value->IsConstant()
+      ? chunk_->DefineConstantOperand(HConstant::cast(value))
+      : UseRegisterAtStart(value);
+}
+
+
+LOperand* LChunkBuilder::UseAny(HValue* value) {
+  return value->IsConstant()
+      ? chunk_->DefineConstantOperand(HConstant::cast(value))
+      :  Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
+}
+
+
+LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
+  if (value->EmitAtUses()) {
+    HInstruction* instr = HInstruction::cast(value);
+    VisitInstruction(instr);
+  }
+  operand->set_virtual_register(value->id());
+  return operand;
+}
+
+
+template<int I, int T>
+LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
+                                    LUnallocated* result) {
+  result->set_virtual_register(current_instruction_->id());
+  instr->set_result(result);
+  return instr;
+}
+
+
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineAsRegister(
+    LTemplateInstruction<1, I, T>* instr) {
+  return Define(instr,
+                new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+}
+
+
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineAsSpilled(
+    LTemplateInstruction<1, I, T>* instr, int index) {
+  return Define(instr,
+                new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
+}
+
+
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineSameAsFirst(
+    LTemplateInstruction<1, I, T>* instr) {
+  return Define(instr,
+                new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
+}
+
+
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineFixed(
+    LTemplateInstruction<1, I, T>* instr, Register reg) {
+  return Define(instr, ToUnallocated(reg));
+}
+
+
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineFixedDouble(
+    LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
+  return Define(instr, ToUnallocated(reg));
+}
+
+
+LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
+  HEnvironment* hydrogen_env = current_block_->last_environment();
+  int argument_index_accumulator = 0;
+  instr->set_environment(CreateEnvironment(hydrogen_env,
+                                           &argument_index_accumulator));
+  return instr;
+}
+
+
+LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
+                                        HInstruction* hinstr,
+                                        CanDeoptimize can_deoptimize) {
+#ifdef DEBUG
+  instr->VerifyCall();
+#endif
+  instr->MarkAsCall();
+  instr = AssignPointerMap(instr);
+
+  if (hinstr->HasObservableSideEffects()) {
+    ASSERT(hinstr->next()->IsSimulate());
+    HSimulate* sim = HSimulate::cast(hinstr->next());
+    ASSERT(instruction_pending_deoptimization_environment_ == NULL);
+    ASSERT(pending_deoptimization_ast_id_.IsNone());
+    instruction_pending_deoptimization_environment_ = instr;
+    pending_deoptimization_ast_id_ = sim->ast_id();
+  }
+
+  // If instruction does not have side-effects lazy deoptimization
+  // after the call will try to deoptimize to the point before the call.
+  // Thus we still need to attach environment to this call even if
+  // call sequence can not deoptimize eagerly.
+  bool needs_environment =
+      (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
+      !hinstr->HasObservableSideEffects();
+  if (needs_environment && !instr->HasEnvironment()) {
+    instr = AssignEnvironment(instr);
+  }
+
+  return instr;
+}
+
+
+LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
+  ASSERT(!instr->HasPointerMap());
+  instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
+  return instr;
+}
+
+
+LUnallocated* LChunkBuilder::TempRegister() {
+  LUnallocated* operand =
+      new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
+  operand->set_virtual_register(allocator_->GetVirtualRegister());
+  if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
+  return operand;
+}
+
+
+LOperand* LChunkBuilder::FixedTemp(Register reg) {
+  LUnallocated* operand = ToUnallocated(reg);
+  ASSERT(operand->HasFixedPolicy());
+  return operand;
+}
+
+
+LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
+  LUnallocated* operand = ToUnallocated(reg);
+  ASSERT(operand->HasFixedPolicy());
+  return operand;
+}
+
+
+LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
+  return new(zone()) LLabel(instr->block());
+}
+
+
+LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
+  return AssignEnvironment(new(zone()) LDeoptimize);
+}
+
+
+LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
+  return AssignEnvironment(new(zone()) LDeoptimize);
+}
+
+
+LInstruction* LChunkBuilder::DoShift(Token::Value op,
+                                     HBitwiseBinaryOperation* instr) {
+  if (instr->representation().IsTagged()) {
+    ASSERT(instr->left()->representation().IsTagged());
+    ASSERT(instr->right()->representation().IsTagged());
+
+    LOperand* left = UseFixed(instr->left(), r4);
+    LOperand* right = UseFixed(instr->right(), r3);
+    LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
+    return MarkAsCall(DefineFixed(result, r3), instr);
+  }
+
+  ASSERT(instr->representation().IsInteger32());
+  ASSERT(instr->left()->representation().IsInteger32());
+  ASSERT(instr->right()->representation().IsInteger32());
+  LOperand* left = UseRegisterAtStart(instr->left());
+
+  HValue* right_value = instr->right();
+  LOperand* right = NULL;
+  int constant_value = 0;
+  if (right_value->IsConstant()) {
+    HConstant* constant = HConstant::cast(right_value);
+    right = chunk_->DefineConstantOperand(constant);
+    constant_value = constant->Integer32Value() & 0x1f;
+  } else {
+    right = UseRegisterAtStart(right_value);
+  }
+
+  // Shift operations can only deoptimize if we do a logical shift
+  // by 0 and the result cannot be truncated to int32.
+  bool does_deopt = false;
+  if (op == Token::SHR && constant_value == 0) {
+    if (FLAG_opt_safe_uint32_operations) {
+      does_deopt = !instr->CheckFlag(HInstruction::kUint32);
+    } else {
+      for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
+        if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
+          does_deopt = true;
+          break;
+        }
+      }
+    }
+  }
+
+  LInstruction* result =
+      DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
+  return does_deopt ? AssignEnvironment(result) : result;
+}
+
+
+LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
+                                           HArithmeticBinaryOperation* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->left()->representation().IsDouble());
+  ASSERT(instr->right()->representation().IsDouble());
+  ASSERT(op != Token::MOD);
+  LOperand* left = UseRegisterAtStart(instr->left());
+  LOperand* right = UseRegisterAtStart(instr->right());
+  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
+  return DefineAsRegister(result);
+}
+
+
+LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
+                                           HArithmeticBinaryOperation* instr) {
+  ASSERT(op == Token::ADD ||
+         op == Token::DIV ||
+         op == Token::MOD ||
+         op == Token::MUL ||
+         op == Token::SUB);
+  HValue* left = instr->left();
+  HValue* right = instr->right();
+  ASSERT(left->representation().IsTagged());
+  ASSERT(right->representation().IsTagged());
+  LOperand* left_operand = UseFixed(left, r4);
+  LOperand* right_operand = UseFixed(right, r3);
+  LArithmeticT* result =
+      new(zone()) LArithmeticT(op, left_operand, right_operand);
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
+  ASSERT(is_building());
+  current_block_ = block;
+  next_block_ = next_block;
+  if (block->IsStartBlock()) {
+    block->UpdateEnvironment(graph_->start_environment());
+    argument_count_ = 0;
+  } else if (block->predecessors()->length() == 1) {
+    // We have a single predecessor => copy environment and outgoing
+    // argument count from the predecessor.
+    ASSERT(block->phis()->length() == 0);
+    HBasicBlock* pred = block->predecessors()->at(0);
+    HEnvironment* last_environment = pred->last_environment();
+    ASSERT(last_environment != NULL);
+    // Only copy the environment, if it is later used again.
+    if (pred->end()->SecondSuccessor() == NULL) {
+      ASSERT(pred->end()->FirstSuccessor() == block);
+    } else {
+      if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
+          pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
+        last_environment = last_environment->Copy();
+      }
+    }
+    block->UpdateEnvironment(last_environment);
+    ASSERT(pred->argument_count() >= 0);
+    argument_count_ = pred->argument_count();
+  } else {
+    // We are at a state join => process phis.
+    HBasicBlock* pred = block->predecessors()->at(0);
+    // No need to copy the environment, it cannot be used later.
+    HEnvironment* last_environment = pred->last_environment();
+    for (int i = 0; i < block->phis()->length(); ++i) {
+      HPhi* phi = block->phis()->at(i);
+      last_environment->SetValueAt(phi->merged_index(), phi);
+    }
+    for (int i = 0; i < block->deleted_phis()->length(); ++i) {
+      last_environment->SetValueAt(block->deleted_phis()->at(i),
+                                   graph_->GetConstantUndefined());
+    }
+    block->UpdateEnvironment(last_environment);
+    // Pick up the outgoing argument count of one of the predecessors.
+    argument_count_ = pred->argument_count();
+  }
+  HInstruction* current = block->first();
+  int start = chunk_->instructions()->length();
+  while (current != NULL && !is_aborted()) {
+    // Code for constants in registers is generated lazily.
+    if (!current->EmitAtUses()) {
+      VisitInstruction(current);
+    }
+    current = current->next();
+  }
+  int end = chunk_->instructions()->length() - 1;
+  if (end >= start) {
+    block->set_first_instruction_index(start);
+    block->set_last_instruction_index(end);
+  }
+  block->set_argument_count(argument_count_);
+  next_block_ = NULL;
+  current_block_ = NULL;
+}
+
+
+void LChunkBuilder::VisitInstruction(HInstruction* current) {
+  HInstruction* old_current = current_instruction_;
+  current_instruction_ = current;
+  if (current->has_position()) position_ = current->position();
+  LInstruction* instr = current->CompileToLithium(this);
+
+  if (instr != NULL) {
+    if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
+      instr = AssignPointerMap(instr);
+    }
+    if (FLAG_stress_environments && !instr->HasEnvironment()) {
+      instr = AssignEnvironment(instr);
+    }
+    instr->set_hydrogen_value(current);
+    chunk_->AddInstruction(instr, current_block_);
+  }
+  current_instruction_ = old_current;
+}
+
+
+LEnvironment* LChunkBuilder::CreateEnvironment(
+    HEnvironment* hydrogen_env,
+    int* argument_index_accumulator) {
+  if (hydrogen_env == NULL) return NULL;
+
+  LEnvironment* outer =
+      CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
+  BailoutId ast_id = hydrogen_env->ast_id();
+  ASSERT(!ast_id.IsNone() ||
+         hydrogen_env->frame_type() != JS_FUNCTION);
+  int value_count = hydrogen_env->length();
+  LEnvironment* result = new(zone()) LEnvironment(
+      hydrogen_env->closure(),
+      hydrogen_env->frame_type(),
+      ast_id,
+      hydrogen_env->parameter_count(),
+      argument_count_,
+      value_count,
+      outer,
+      hydrogen_env->entry(),
+      zone());
+  int argument_index = *argument_index_accumulator;
+  for (int i = 0; i < value_count; ++i) {
+    if (hydrogen_env->is_special_index(i)) continue;
+
+    HValue* value = hydrogen_env->values()->at(i);
+    LOperand* op = NULL;
+    if (value->IsArgumentsObject()) {
+      op = NULL;
+    } else if (value->IsPushArgument()) {
+      op = new(zone()) LArgument(argument_index++);
+    } else {
+      op = UseAny(value);
+    }
+    result->AddValue(op,
+                     value->representation(),
+                     value->CheckFlag(HInstruction::kUint32));
+  }
+
+  if (hydrogen_env->frame_type() == JS_FUNCTION) {
+    *argument_index_accumulator = argument_index;
+  }
+
+  return result;
+}
+
+
+LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
+  return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
+}
+
+
+LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
+  HValue* value = instr->value();
+  if (value->EmitAtUses()) {
+    HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
+        ? instr->FirstSuccessor()
+        : instr->SecondSuccessor();
+    return new(zone()) LGoto(successor->block_id());
+  }
+
+  LBranch* result = new(zone()) LBranch(UseRegister(value));
+  // Tagged values that are not known smis or booleans require a
+  // deoptimization environment.
+  Representation rep = value->representation();
+  HType type = value->type();
+  if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
+    return AssignEnvironment(result);
+  }
+  return result;
+}
+
+
+
+LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LOperand* temp = TempRegister();
+  return new(zone()) LCmpMapAndBranch(value, temp);
+}
+
+
+LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
+  LOperand* value = UseRegister(instr->value());
+  return DefineAsRegister(new(zone()) LArgumentsLength(value));
+}
+
+
+LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
+  return DefineAsRegister(new(zone()) LArgumentsElements);
+}
+
+
+LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
+  LInstanceOf* result =
+      new(zone()) LInstanceOf(UseFixed(instr->left(), r3),
+                      UseFixed(instr->right(), r4));
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
+    HInstanceOfKnownGlobal* instr) {
+  LInstanceOfKnownGlobal* result =
+      new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), r3),
+                                         FixedTemp(r7));
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
+  LOperand* receiver = UseRegisterAtStart(instr->receiver());
+  LOperand* function = UseRegisterAtStart(instr->function());
+  LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
+  return AssignEnvironment(DefineSameAsFirst(result));
+}
+
+
+LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
+  LOperand* function = UseFixed(instr->function(), r4);
+  LOperand* receiver = UseFixed(instr->receiver(), r3);
+  LOperand* length = UseFixed(instr->length(), r5);
+  LOperand* elements = UseFixed(instr->elements(), r6);
+  LApplyArguments* result = new(zone()) LApplyArguments(function,
+                                                receiver,
+                                                length,
+                                                elements);
+  return MarkAsCall(DefineFixed(result, r3), instr, CAN_DEOPTIMIZE_EAGERLY);
+}
+
+
+LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
+  ++argument_count_;
+  LOperand* argument = Use(instr->argument());
+  return new(zone()) LPushArgument(argument);
+}
+
+
+LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
+  return instr->HasNoUses()
+      ? NULL
+      : DefineAsRegister(new(zone()) LThisFunction);
+}
+
+
+LInstruction* LChunkBuilder::DoContext(HContext* instr) {
+  return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
+}
+
+
+LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+  LOperand* context = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LOuterContext(context));
+}
+
+
+LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
+  return MarkAsCall(new(zone()) LDeclareGlobals, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
+  LOperand* context = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LGlobalObject(context));
+}
+
+
+LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
+  LOperand* global_object = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
+}
+
+
+LInstruction* LChunkBuilder::DoCallConstantFunction(
+    HCallConstantFunction* instr) {
+  argument_count_ -= instr->argument_count();
+  return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
+  LOperand* function = UseFixed(instr->function(), r4);
+  argument_count_ -= instr->argument_count();
+  LInvokeFunction* result = new(zone()) LInvokeFunction(function);
+  return MarkAsCall(DefineFixed(result, r3), instr, CANNOT_DEOPTIMIZE_EAGERLY);
+}
+
+
+LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
+  BuiltinFunctionId op = instr->op();
+  if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) {
+    LOperand* input = UseFixedDouble(instr->value(), d2);
+    LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, NULL);
+    return MarkAsCall(DefineFixedDouble(result, d2), instr);
+  } else if (op == kMathPowHalf) {
+    LOperand* input = UseFixedDouble(instr->value(), d2);
+    LOperand* temp = FixedTemp(d3);
+    LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
+    return DefineFixedDouble(result, d2);
+  } else {
+    LOperand* input = UseRegisterAtStart(instr->value());
+
+    LOperand* temp = (op == kMathRound) ? FixedTemp(d3) : NULL;
+    LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
+    switch (op) {
+      case kMathAbs:
+        return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+      case kMathFloor:
+        return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+      case kMathSqrt:
+        return DefineAsRegister(result);
+      case kMathRound:
+        return AssignEnvironment(DefineAsRegister(result));
+      default:
+        UNREACHABLE();
+        return NULL;
+    }
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
+  ASSERT(instr->key()->representation().IsTagged());
+  argument_count_ -= instr->argument_count();
+  LOperand* key = UseFixed(instr->key(), r5);
+  return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
+  argument_count_ -= instr->argument_count();
+  return MarkAsCall(DefineFixed(new(zone()) LCallNamed, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
+  argument_count_ -= instr->argument_count();
+  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
+  argument_count_ -= instr->argument_count();
+  return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
+  LOperand* constructor = UseFixed(instr->constructor(), r4);
+  argument_count_ -= instr->argument_count();
+  LCallNew* result = new(zone()) LCallNew(constructor);
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
+  LOperand* function = UseFixed(instr->function(), r4);
+  argument_count_ -= instr->argument_count();
+  return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), r3),
+                    instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
+  argument_count_ -= instr->argument_count();
+  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoShr(HShr* instr) {
+  return DoShift(Token::SHR, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoSar(HSar* instr) {
+  return DoShift(Token::SAR, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoShl(HShl* instr) {
+  return DoShift(Token::SHL, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+
+    LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
+    LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
+    return DefineAsRegister(new(zone()) LBitI(left, right));
+  } else {
+    ASSERT(instr->representation().IsTagged());
+    ASSERT(instr->left()->representation().IsTagged());
+    ASSERT(instr->right()->representation().IsTagged());
+
+    LOperand* left = UseFixed(instr->left(), r4);
+    LOperand* right = UseFixed(instr->right(), r3);
+    LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
+    return MarkAsCall(DefineFixed(result, r3), instr);
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
+  ASSERT(instr->value()->representation().IsInteger32());
+  ASSERT(instr->representation().IsInteger32());
+  if (instr->HasNoUses()) return NULL;
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LBitNotI(value));
+}
+
+
+LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
+  if (instr->representation().IsDouble()) {
+    return DoArithmeticD(Token::DIV, instr);
+  } else if (instr->representation().IsInteger32()) {
+    // TODO(1042) The fixed register allocation
+    // is needed because we call TypeRecordingBinaryOpStub from
+    // the generated code, which requires registers r3
+    // and r4 to be used. We should remove that
+    // when we provide a native implementation.
+    LOperand* dividend = UseFixed(instr->left(), r3);
+    LOperand* divisor = UseFixed(instr->right(), r4);
+    return AssignEnvironment(AssignPointerMap(
+             DefineFixed(new(zone()) LDivI(dividend, divisor), r3)));
+  } else {
+    return DoArithmeticT(Token::DIV, instr);
+  }
+}
+
+
+bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) {
+  uint32_t divisor_abs = abs(divisor);
+  // Dividing by 0, 1, and powers of 2 is easy.
+  // Note that IsPowerOf2(0) returns true;
+  ASSERT(IsPowerOf2(0) == true);
+  if (IsPowerOf2(divisor_abs)) return true;
+
+  // We have magic numbers for a few specific divisors.
+  // Details and proofs can be found in:
+  // - Hacker's Delight, Henry S. Warren, Jr.
+  // - The PowerPC Compiler Writer’s Guide
+  // and probably many others.
+  //
+  // We handle
+  //   <divisor with magic numbers> * <power of 2>
+  // but not
+  //   <divisor with magic numbers> * <other divisor with magic numbers>
+  int32_t power_of_2_factor =
+    CompilerIntrinsics::CountTrailingZeros(divisor_abs);
+  DivMagicNumbers magic_numbers =
+    DivMagicNumberFor(divisor_abs >> power_of_2_factor);
+  if (magic_numbers.M != InvalidDivMagicNumber.M) return true;
+
+  return false;
+}
+
+
+HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
+  // A value with an integer representation does not need to be transformed.
+  if (dividend->representation().IsInteger32()) {
+    return dividend;
+  // A change from an integer32 can be replaced by the integer32 value.
+  } else if (dividend->IsChange() &&
+      HChange::cast(dividend)->from().IsInteger32()) {
+    return HChange::cast(dividend)->value();
+  }
+  return NULL;
+}
+
+
+HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
+  if (divisor->IsConstant() &&
+      HConstant::cast(divisor)->HasInteger32Value()) {
+    HConstant* constant_val = HConstant::cast(divisor);
+    return constant_val->CopyToRepresentation(Representation::Integer32(),
+                                              divisor->block()->zone());
+  }
+  return NULL;
+}
+
+LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
+  HValue* right = instr->right();
+  ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value());
+  LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right));
+  int32_t divisor_si = HConstant::cast(right)->Integer32Value();
+  if (divisor_si == 0) {
+    LOperand* dividend = UseRegister(instr->left());
+    return AssignEnvironment(DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)));
+  } else if (IsPowerOf2(abs(divisor_si))) {
+    LOperand* dividend = UseRegisterAtStart(instr->left());
+    LInstruction* result = DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, NULL));
+    return divisor_si < 0 ? AssignEnvironment(result) : result;
+  } else {
+    LOperand* dividend = UseRegisterAtStart(instr->left());
+    LOperand* temp = TempRegister();
+    LInstruction* result = DefineAsRegister(
+        new(zone()) LMathFloorOfDiv(dividend, divisor, temp));
+    return divisor_si < 0 ? AssignEnvironment(result) : result;
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoMod(HMod* instr) {
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+
+    LModI* mod;
+    if (instr->HasPowerOf2Divisor()) {
+      ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
+      LOperand* value = UseRegisterAtStart(instr->left());
+      mod = new(zone()) LModI(value, UseOrConstant(instr->right()));
+    } else {
+      LOperand* dividend = UseRegister(instr->left());
+      LOperand* divisor = UseRegister(instr->right());
+      mod = new(zone()) LModI(dividend,
+                              divisor,
+                              TempRegister(),
+                              FixedTemp(d10),
+                              FixedTemp(d11));
+    }
+
+    if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+        instr->CheckFlag(HValue::kCanBeDivByZero)) {
+      return AssignEnvironment(DefineAsRegister(mod));
+    } else {
+      return DefineAsRegister(mod);
+    }
+  } else if (instr->representation().IsTagged()) {
+    return DoArithmeticT(Token::MOD, instr);
+  } else {
+    ASSERT(instr->representation().IsDouble());
+    // We call a C function for double modulo. It can't trigger a GC.
+    // We need to use fixed result register for the call.
+    // TODO(fschneider): Allow any register as input registers.
+    LOperand* left = UseFixedDouble(instr->left(), d1);
+    LOperand* right = UseFixedDouble(instr->right(), d2);
+    LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
+    return MarkAsCall(DefineFixedDouble(result, d1), instr);
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoMul(HMul* instr) {
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+    LOperand* left;
+    LOperand* right = UseOrConstant(instr->MostConstantOperand());
+    LOperand* temp = NULL;
+    if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
+        (instr->CheckFlag(HValue::kCanOverflow) ||
+        !right->IsConstantOperand())) {
+      left = UseRegister(instr->LeastConstantOperand());
+      temp = TempRegister();
+    } else {
+      left = UseRegisterAtStart(instr->LeastConstantOperand());
+    }
+    LMulI* mul = new(zone()) LMulI(left, right, temp);
+    if (instr->CheckFlag(HValue::kCanOverflow) ||
+        instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      AssignEnvironment(mul);
+    }
+    return DefineAsRegister(mul);
+
+  } else if (instr->representation().IsDouble()) {
+    return DoArithmeticD(Token::MUL, instr);
+
+  } else {
+    return DoArithmeticT(Token::MUL, instr);
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoSub(HSub* instr) {
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+    LOperand* left = UseRegisterAtStart(instr->left());
+    LOperand* right = UseOrConstantAtStart(instr->right());
+    LSubI* sub = new(zone()) LSubI(left, right);
+    LInstruction* result = DefineAsRegister(sub);
+    if (instr->CheckFlag(HValue::kCanOverflow)) {
+      result = AssignEnvironment(result);
+    }
+    return result;
+  } else if (instr->representation().IsDouble()) {
+    return DoArithmeticD(Token::SUB, instr);
+  } else {
+    return DoArithmeticT(Token::SUB, instr);
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+    LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
+    LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
+    LAddI* add = new(zone()) LAddI(left, right);
+    LInstruction* result = DefineAsRegister(add);
+    if (instr->CheckFlag(HValue::kCanOverflow)) {
+      result = AssignEnvironment(result);
+    }
+    return result;
+  } else if (instr->representation().IsDouble()) {
+    return DoArithmeticD(Token::ADD, instr);
+  } else {
+    ASSERT(instr->representation().IsTagged());
+    return DoArithmeticT(Token::ADD, instr);
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
+  LOperand* left = NULL;
+  LOperand* right = NULL;
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+    left = UseRegisterAtStart(instr->LeastConstantOperand());
+    right = UseOrConstantAtStart(instr->MostConstantOperand());
+  } else {
+    ASSERT(instr->representation().IsDouble());
+    ASSERT(instr->left()->representation().IsDouble());
+    ASSERT(instr->right()->representation().IsDouble());
+    left = UseRegisterAtStart(instr->left());
+    right = UseRegisterAtStart(instr->right());
+  }
+  return DefineAsRegister(new(zone()) LMathMinMax(left, right));
+}
+
+
+LInstruction* LChunkBuilder::DoPower(HPower* instr) {
+  ASSERT(instr->representation().IsDouble());
+  // We call a C function for double power. It can't trigger a GC.
+  // We need to use fixed result register for the call.
+  Representation exponent_type = instr->right()->representation();
+  ASSERT(instr->left()->representation().IsDouble());
+  LOperand* left = UseFixedDouble(instr->left(), d1);
+  LOperand* right = exponent_type.IsDouble() ?
+      UseFixedDouble(instr->right(), d2) :
+      UseFixed(instr->right(), r5);
+  LPower* result = new(zone()) LPower(left, right);
+  return MarkAsCall(DefineFixedDouble(result, d3),
+                    instr,
+                    CAN_DEOPTIMIZE_EAGERLY);
+}
+
+
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+  LOperand* global_object = UseFixed(instr->global_object(), r3);
+  LRandom* result = new(zone()) LRandom(global_object);
+  return MarkAsCall(DefineFixedDouble(result, d7), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
+  ASSERT(instr->left()->representation().IsTagged());
+  ASSERT(instr->right()->representation().IsTagged());
+  LOperand* left = UseFixed(instr->left(), r4);
+  LOperand* right = UseFixed(instr->right(), r3);
+  LCmpT* result = new(zone()) LCmpT(left, right);
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoCompareIDAndBranch(
+    HCompareIDAndBranch* instr) {
+  Representation r = instr->GetInputRepresentation();
+  if (r.IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+    LOperand* left = UseRegisterOrConstantAtStart(instr->left());
+    LOperand* right = UseRegisterOrConstantAtStart(instr->right());
+    return new(zone()) LCmpIDAndBranch(left, right);
+  } else {
+    ASSERT(r.IsDouble());
+    ASSERT(instr->left()->representation().IsDouble());
+    ASSERT(instr->right()->representation().IsDouble());
+    LOperand* left = UseRegisterAtStart(instr->left());
+    LOperand* right = UseRegisterAtStart(instr->right());
+    return new(zone()) LCmpIDAndBranch(left, right);
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
+    HCompareObjectEqAndBranch* instr) {
+  LOperand* left = UseRegisterAtStart(instr->left());
+  LOperand* right = UseRegisterAtStart(instr->right());
+  return new(zone()) LCmpObjectEqAndBranch(left, right);
+}
+
+
+LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
+    HCompareConstantEqAndBranch* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return new(zone()) LCmpConstantEqAndBranch(value);
+}
+
+
+LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
+}
+
+
+LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LOperand* temp = TempRegister();
+  return new(zone()) LIsObjectAndBranch(value, temp);
+}
+
+
+LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LOperand* temp = TempRegister();
+  return new(zone()) LIsStringAndBranch(value, temp);
+}
+
+
+LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  return new(zone()) LIsSmiAndBranch(Use(instr->value()));
+}
+
+
+LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
+    HIsUndetectableAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
+}
+
+
+LInstruction* LChunkBuilder::DoStringCompareAndBranch(
+    HStringCompareAndBranch* instr) {
+  ASSERT(instr->left()->representation().IsTagged());
+  ASSERT(instr->right()->representation().IsTagged());
+  LOperand* left = UseFixed(instr->left(), r4);
+  LOperand* right = UseFixed(instr->right(), r3);
+  LStringCompareAndBranch* result =
+      new(zone()) LStringCompareAndBranch(left, right);
+  return MarkAsCall(result, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
+    HHasInstanceTypeAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return new(zone()) LHasInstanceTypeAndBranch(value);
+}
+
+
+LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
+    HGetCachedArrayIndex* instr)  {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegisterAtStart(instr->value());
+
+  return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
+}
+
+
+LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
+    HHasCachedArrayIndexAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  return new(zone()) LHasCachedArrayIndexAndBranch(
+      UseRegisterAtStart(instr->value()));
+}
+
+
+LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
+    HClassOfTestAndBranch* instr) {
+  ASSERT(instr->value()->representation().IsTagged());
+  LOperand* value = UseRegister(instr->value());
+  return new(zone()) LClassOfTestAndBranch(value, TempRegister());
+}
+
+
+LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
+  LOperand* array = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LJSArrayLength(array));
+}
+
+
+LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
+    HFixedArrayBaseLength* instr) {
+  LOperand* array = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
+}
+
+
+LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
+  LOperand* map = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LMapEnumLength(map));
+}
+
+
+LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
+  LOperand* object = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LElementsKind(object));
+}
+
+
+LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
+  LOperand* object = UseRegister(instr->value());
+  LValueOf* result = new(zone()) LValueOf(object, TempRegister());
+  return DefineAsRegister(result);
+}
+
+
+LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
+  LOperand* object = UseFixed(instr->value(), r3);
+  LDateField* result =
+      new(zone()) LDateField(object, FixedTemp(r4), instr->index());
+  return MarkAsCall(DefineFixed(result, r3), instr, CAN_DEOPTIMIZE_EAGERLY);
+}
+
+
+LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
+  LOperand* value = UseRegisterOrConstantAtStart(instr->index());
+  LOperand* length = UseRegister(instr->length());
+  return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
+}
+
+
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+  // The control instruction marking the end of a block that completed
+  // abruptly (e.g., threw an exception).  There is nothing specific to do.
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
+  LOperand* value = UseFixed(instr->value(), r3);
+  return MarkAsCall(new(zone()) LThrow(value), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
+  // All HForceRepresentation instructions should be eliminated in the
+  // representation change phase of Hydrogen.
+  UNREACHABLE();
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoChange(HChange* instr) {
+  Representation from = instr->from();
+  Representation to = instr->to();
+  if (from.IsTagged()) {
+    if (to.IsDouble()) {
+      LOperand* value = UseRegister(instr->value());
+      LNumberUntagD* res = new(zone()) LNumberUntagD(value);
+      return AssignEnvironment(DefineAsRegister(res));
+    } else {
+      ASSERT(to.IsInteger32());
+      LOperand* value = UseRegisterAtStart(instr->value());
+      LInstruction* res = NULL;
+      if (instr->value()->type().IsSmi()) {
+        res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
+      } else {
+        LOperand* temp1 = TempRegister();
+        LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
+                                                      : NULL;
+        LOperand* temp3 = FixedTemp(d11);
+        res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
+                                                       temp1,
+                                                       temp2,
+                                                       temp3));
+        res = AssignEnvironment(res);
+      }
+      return res;
+    }
+  } else if (from.IsDouble()) {
+    if (to.IsTagged()) {
+      LOperand* value = UseRegister(instr->value());
+      LOperand* temp1 = TempRegister();
+      LOperand* temp2 = TempRegister();
+
+      // Make sure that the temp and result_temp registers are
+      // different.
+      LUnallocated* result_temp = TempRegister();
+      LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
+      Define(result, result_temp);
+      return AssignPointerMap(result);
+    } else {
+      ASSERT(to.IsInteger32());
+      LOperand* value = UseRegister(instr->value());
+      LOperand* temp1 = TempRegister();
+      LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
+      LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
+      return AssignEnvironment(DefineAsRegister(res));
+    }
+  } else if (from.IsInteger32()) {
+    if (to.IsTagged()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegisterAtStart(val);
+      if (val->CheckFlag(HInstruction::kUint32)) {
+        LNumberTagU* result = new(zone()) LNumberTagU(value);
+        return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
+      } else if (val->HasRange() && val->range()->IsInSmiRange()) {
+        return DefineAsRegister(new(zone()) LSmiTag(value));
+      } else {
+        LNumberTagI* result = new(zone()) LNumberTagI(value);
+        return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+      }
+    } else {
+      ASSERT(to.IsDouble());
+      if (instr->value()->CheckFlag(HInstruction::kUint32)) {
+        return DefineAsRegister(
+            new(zone()) LUint32ToDouble(UseRegister(instr->value())));
+      } else {
+        return DefineAsRegister(
+            new(zone()) LInteger32ToDouble(Use(instr->value())));
+      }
+    }
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return AssignEnvironment(new(zone()) LCheckNonSmi(value));
+}
+
+
+LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LInstruction* result = new(zone()) LCheckInstanceType(value);
+  return AssignEnvironment(result);
+}
+
+
+LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
+  LOperand* temp1 = TempRegister();
+  LOperand* temp2 = TempRegister();
+  LInstruction* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
+  return AssignEnvironment(result);
+}
+
+
+LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return AssignEnvironment(new(zone()) LCheckSmi(value));
+}
+
+
+LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return AssignEnvironment(new(zone()) LCheckFunction(value));
+}
+
+
+LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LInstruction* result = new(zone()) LCheckMaps(value);
+  return AssignEnvironment(result);
+}
+
+
+LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
+  HValue* value = instr->value();
+  Representation input_rep = value->representation();
+  LOperand* reg = UseRegister(value);
+  if (input_rep.IsDouble()) {
+    return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(d11)));
+  } else if (input_rep.IsInteger32()) {
+    return DefineAsRegister(new(zone()) LClampIToUint8(reg));
+  } else {
+    ASSERT(input_rep.IsTagged());
+    // Register allocator doesn't (yet) support allocation of double
+    // temps. Reserve d1 explicitly.
+    LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d10),
+                                                        FixedTemp(d11));
+    return AssignEnvironment(DefineAsRegister(result));
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
+  return new(zone()) LReturn(UseFixed(instr->value(), r3));
+}
+
+
+LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
+  Representation r = instr->representation();
+  if (r.IsInteger32()) {
+    return DefineAsRegister(new(zone()) LConstantI);
+  } else if (r.IsDouble()) {
+    return DefineAsRegister(new(zone()) LConstantD);
+  } else if (r.IsTagged()) {
+    return DefineAsRegister(new(zone()) LConstantT);
+  } else {
+    UNREACHABLE();
+    return NULL;
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
+  LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
+  return instr->RequiresHoleCheck()
+      ? AssignEnvironment(DefineAsRegister(result))
+      : DefineAsRegister(result);
+}
+
+
+LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
+  LOperand* global_object = UseFixed(instr->global_object(), r3);
+  LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
+  LOperand* value = UseRegister(instr->value());
+  // Use a temp to check the value in the cell in the case where we perform
+  // a hole check.
+  return instr->RequiresHoleCheck()
+      ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
+      : new(zone()) LStoreGlobalCell(value, NULL);
+}
+
+
+LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
+  LOperand* global_object = UseFixed(instr->global_object(), r4);
+  LOperand* value = UseFixed(instr->value(), r3);
+  LStoreGlobalGeneric* result =
+      new(zone()) LStoreGlobalGeneric(global_object, value);
+  return MarkAsCall(result, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
+  LOperand* context = UseRegisterAtStart(instr->value());
+  LInstruction* result =
+      DefineAsRegister(new(zone()) LLoadContextSlot(context));
+  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
+}
+
+
+LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
+  LOperand* context;
+  LOperand* value;
+  if (instr->NeedsWriteBarrier()) {
+    context = UseTempRegister(instr->context());
+    value = UseTempRegister(instr->value());
+  } else {
+    context = UseRegister(instr->context());
+    value = UseRegister(instr->value());
+  }
+  LInstruction* result = new(zone()) LStoreContextSlot(context, value);
+  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
+}
+
+
+LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
+  return DefineAsRegister(
+      new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
+    HLoadNamedFieldPolymorphic* instr) {
+  ASSERT(instr->representation().IsTagged());
+  if (instr->need_generic()) {
+    LOperand* obj = UseFixed(instr->object(), r3);
+    LLoadNamedFieldPolymorphic* result =
+        new(zone()) LLoadNamedFieldPolymorphic(obj);
+    return MarkAsCall(DefineFixed(result, r3), instr);
+  } else {
+    LOperand* obj = UseRegisterAtStart(instr->object());
+    LLoadNamedFieldPolymorphic* result =
+        new(zone()) LLoadNamedFieldPolymorphic(obj);
+    return AssignEnvironment(DefineAsRegister(result));
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
+  LOperand* object = UseFixed(instr->object(), r3);
+  LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r3);
+  return MarkAsCall(result, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
+    HLoadFunctionPrototype* instr) {
+  return AssignEnvironment(DefineAsRegister(
+      new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LLoadElements(input));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
+    HLoadExternalArrayPointer* instr) {
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
+    HLoadKeyedFastElement* instr) {
+  ASSERT(instr->representation().IsTagged());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
+  LOperand* obj = UseRegisterAtStart(instr->object());
+  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+  LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
+  if (instr->RequiresHoleCheck()) AssignEnvironment(result);
+  return DefineAsRegister(result);
+}
+
+
+LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
+    HLoadKeyedFastDoubleElement* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
+  LOperand* elements = UseTempRegister(instr->elements());
+  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+  LLoadKeyedFastDoubleElement* result =
+      new(zone()) LLoadKeyedFastDoubleElement(elements, key);
+  return AssignEnvironment(DefineAsRegister(result));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
+    HLoadKeyedSpecializedArrayElement* instr) {
+  ElementsKind elements_kind = instr->elements_kind();
+  ASSERT(
+      (instr->representation().IsInteger32() &&
+       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+      (instr->representation().IsDouble() &&
+       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
+  LOperand* external_pointer = UseRegister(instr->external_pointer());
+  LOperand* key = UseRegisterOrConstant(instr->key());
+  LLoadKeyedSpecializedArrayElement* result =
+      new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
+  LInstruction* load_instr = DefineAsRegister(result);
+  // An unsigned int array load might overflow and cause a deopt, make sure it
+  // has an environment.
+  return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
+      AssignEnvironment(load_instr) : load_instr;
+}
+
+
+LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
+  LOperand* object = UseFixed(instr->object(), r4);
+  LOperand* key = UseFixed(instr->key(), r3);
+
+  LInstruction* result =
+      DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r3);
+  return MarkAsCall(result, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
+    HStoreKeyedFastElement* instr) {
+  bool needs_write_barrier = instr->NeedsWriteBarrier();
+  ASSERT(instr->value()->representation().IsTagged());
+  ASSERT(instr->object()->representation().IsTagged());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
+
+  LOperand* obj = UseTempRegister(instr->object());
+  LOperand* val = needs_write_barrier
+      ? UseTempRegister(instr->value())
+      : UseRegisterAtStart(instr->value());
+  LOperand* key = needs_write_barrier
+      ? UseTempRegister(instr->key())
+      : UseRegisterOrConstantAtStart(instr->key());
+  return new(zone()) LStoreKeyedFastElement(obj, key, val);
+}
+
+
+LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
+    HStoreKeyedFastDoubleElement* instr) {
+  ASSERT(instr->value()->representation().IsDouble());
+  ASSERT(instr->elements()->representation().IsTagged());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
+
+  LOperand* elements = UseRegisterAtStart(instr->elements());
+  LOperand* val = UseTempRegister(instr->value());
+  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
+
+  return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
+}
+
+
+LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
+    HStoreKeyedSpecializedArrayElement* instr) {
+  ElementsKind elements_kind = instr->elements_kind();
+  ASSERT(
+      (instr->value()->representation().IsInteger32() &&
+       (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
+       (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+      (instr->value()->representation().IsDouble() &&
+       ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
+       (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+  ASSERT(instr->external_pointer()->representation().IsExternal());
+  ASSERT(instr->key()->representation().IsInteger32() ||
+         instr->key()->representation().IsTagged());
+
+  LOperand* external_pointer = UseRegister(instr->external_pointer());
+  bool val_is_temp_register =
+      elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT_ELEMENTS;
+  LOperand* val = val_is_temp_register
+      ? UseTempRegister(instr->value())
+      : UseRegister(instr->value());
+  LOperand* key = UseRegisterOrConstant(instr->key());
+
+  return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
+                                                        key,
+                                                        val);
+}
+
+
+LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
+  LOperand* obj = UseFixed(instr->object(), r5);
+  LOperand* key = UseFixed(instr->key(), r4);
+  LOperand* val = UseFixed(instr->value(), r3);
+
+  ASSERT(instr->object()->representation().IsTagged());
+  ASSERT(instr->key()->representation().IsTagged());
+  ASSERT(instr->value()->representation().IsTagged());
+
+  return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoTransitionElementsKind(
+    HTransitionElementsKind* instr) {
+  ElementsKind from_kind = instr->original_map()->elements_kind();
+  ElementsKind to_kind = instr->transitioned_map()->elements_kind();
+  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+    LOperand* object = UseRegister(instr->object());
+    LOperand* new_map_reg = TempRegister();
+    LTransitionElementsKind* result =
+        new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
+    return DefineSameAsFirst(result);
+  } else {
+    LOperand* object = UseFixed(instr->object(), r3);
+    LOperand* fixed_object_reg = FixedTemp(r5);
+    LOperand* new_map_reg = FixedTemp(r6);
+    LTransitionElementsKind* result =
+        new(zone()) LTransitionElementsKind(object,
+                                            new_map_reg,
+                                            fixed_object_reg);
+    return MarkAsCall(DefineFixed(result, r3), instr);
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
+  bool needs_write_barrier = instr->NeedsWriteBarrier();
+  bool needs_write_barrier_for_map = !instr->transition().is_null() &&
+      instr->NeedsWriteBarrierForMap();
+
+  LOperand* obj;
+  if (needs_write_barrier) {
+    obj = instr->is_in_object()
+        ? UseRegister(instr->object())
+        : UseTempRegister(instr->object());
+  } else {
+    obj = needs_write_barrier_for_map
+        ? UseRegister(instr->object())
+        : UseRegisterAtStart(instr->object());
+  }
+
+  LOperand* val = needs_write_barrier
+      ? UseTempRegister(instr->value())
+      : UseRegister(instr->value());
+
+  // We need a temporary register for write barrier of the map field.
+  LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
+
+  return new(zone()) LStoreNamedField(obj, val, temp);
+}
+
+
+LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
+  LOperand* obj = UseFixed(instr->object(), r4);
+  LOperand* val = UseFixed(instr->value(), r3);
+
+  LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
+  return MarkAsCall(result, instr);
+}
+
+
+LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
+  LOperand* left = UseRegisterAtStart(instr->left());
+  LOperand* right = UseRegisterAtStart(instr->right());
+  return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), r3),
+                    instr);
+}
+
+
+LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
+  LOperand* string = UseTempRegister(instr->string());
+  LOperand* index = UseTempRegister(instr->index());
+  LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
+  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+}
+
+
+LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
+  LOperand* char_code = UseRegister(instr->value());
+  LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
+  return AssignPointerMap(DefineAsRegister(result));
+}
+
+
+LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
+  LOperand* string = UseRegisterAtStart(instr->value());
+  return DefineAsRegister(new(zone()) LStringLength(string));
+}
+
+
+LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
+  LAllocateObject* result =
+      new(zone()) LAllocateObject(TempRegister(), TempRegister());
+  return AssignPointerMap(DefineAsRegister(result));
+}
+
+
+LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
+  return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
+  return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
+  return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
+  return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
+  return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
+  LOperand* object = UseFixed(instr->object(), r3);
+  LOperand* key = UseFixed(instr->key(), r4);
+  LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
+  ASSERT(argument_count_ == 0);
+  allocator_->MarkAsOsrEntry();
+  current_block_->last_environment()->set_ast_id(instr->ast_id());
+  return AssignEnvironment(new(zone()) LOsrEntry);
+}
+
+
+LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
+  int spill_index = chunk()->GetParameterStackSlot(instr->index());
+  return DefineAsSpilled(new(zone()) LParameter, spill_index);
+}
+
+
+LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
+  int spill_index = chunk()->GetNextSpillIndex(false);  // Not double-width.
+  if (spill_index > LUnallocated::kMaxFixedIndex) {
+    Abort("Too many spill slots needed for OSR");
+    spill_index = 0;
+  }
+  return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
+}
+
+
+LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
+  argument_count_ -= instr->argument_count();
+  return MarkAsCall(DefineFixed(new(zone()) LCallStub, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
+  // There are no real uses of the arguments object.
+  // arguments.length and element access are supported directly on
+  // stack arguments, and any real arguments object use causes a bailout.
+  // So this value is never used.
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
+  LOperand* args = UseRegister(instr->arguments());
+  LOperand* length = UseTempRegister(instr->length());
+  LOperand* index = UseRegister(instr->index());
+  return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
+}
+
+
+LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
+  LOperand* object = UseFixed(instr->value(), r3);
+  LToFastProperties* result = new(zone()) LToFastProperties(object);
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
+  LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), r3));
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
+  return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
+}
+
+
+LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
+    HIsConstructCallAndBranch* instr) {
+  return new(zone()) LIsConstructCallAndBranch(TempRegister());
+}
+
+
+LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
+  HEnvironment* env = current_block_->last_environment();
+  ASSERT(env != NULL);
+
+  env->set_ast_id(instr->ast_id());
+
+  env->Drop(instr->pop_count());
+  for (int i = 0; i < instr->values()->length(); ++i) {
+    HValue* value = instr->values()->at(i);
+    if (instr->HasAssignedIndexAt(i)) {
+      env->Bind(instr->GetAssignedIndexAt(i), value);
+    } else {
+      env->Push(value);
+    }
+  }
+
+  // If there is an instruction pending deoptimization environment create a
+  // lazy bailout instruction to capture the environment.
+  if (pending_deoptimization_ast_id_ == instr->ast_id()) {
+    LInstruction* result = new(zone()) LLazyBailout;
+    result = AssignEnvironment(result);
+    // Store the lazy deopt environment with the instruction if needed. Right
+    // now it is only used for LInstanceOfKnownGlobal.
+    instruction_pending_deoptimization_environment_->
+        SetDeferredLazyDeoptimizationEnvironment(result->environment());
+    instruction_pending_deoptimization_environment_ = NULL;
+    pending_deoptimization_ast_id_ = BailoutId::None();
+    return result;
+  }
+
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
+  if (instr->is_function_entry()) {
+    return MarkAsCall(new(zone()) LStackCheck, instr);
+  } else {
+    ASSERT(instr->is_backwards_branch());
+    return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
+  }
+}
+
+
+LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
+  HEnvironment* outer = current_block_->last_environment();
+  HConstant* undefined = graph()->GetConstantUndefined();
+  HEnvironment* inner = outer->CopyForInlining(instr->closure(),
+                                               instr->arguments_count(),
+                                               instr->function(),
+                                               undefined,
+                                               instr->call_kind(),
+                                               instr->inlining_kind());
+  if (instr->arguments_var() != NULL) {
+    inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
+  }
+  inner->set_entry(instr);
+  current_block_->UpdateEnvironment(inner);
+  chunk_->AddInlinedClosure(instr->closure());
+  return NULL;
+}
+
+
+LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
+  LInstruction* pop = NULL;
+
+  HEnvironment* env = current_block_->last_environment();
+
+  if (env->entry()->arguments_pushed()) {
+    int argument_count = env->arguments_environment()->parameter_count();
+    pop = new(zone()) LDrop(argument_count);
+    argument_count_ -= argument_count;
+  }
+
+  HEnvironment* outer = current_block_->last_environment()->
+      DiscardInlined(false);
+  current_block_->UpdateEnvironment(outer);
+
+  return pop;
+}
+
+
+LInstruction* LChunkBuilder::DoIn(HIn* instr) {
+  LOperand* key = UseRegisterAtStart(instr->key());
+  LOperand* object = UseRegisterAtStart(instr->object());
+  LIn* result = new(zone()) LIn(key, object);
+  return MarkAsCall(DefineFixed(result, r3), instr);
+}
+
+
+LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
+  LOperand* object = UseFixed(instr->enumerable(), r3);
+  LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
+  return MarkAsCall(DefineFixed(result, r3), instr, CAN_DEOPTIMIZE_EAGERLY);
+}
+
+
+LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
+  LOperand* map = UseRegister(instr->map());
+  return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
+}
+
+
+LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LOperand* map = UseRegisterAtStart(instr->map());
+  return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
+  LOperand* object = UseRegister(instr->object());
+  LOperand* index = UseRegister(instr->index());
+  return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/ppc/lithium-ppc.h b/src/ppc/lithium-ppc.h
new file mode 100644
index 0000000..cd3752b
--- /dev/null
+++ b/src/ppc/lithium-ppc.h
@@ -0,0 +1,2620 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_LITHIUM_PPC_H_
+#define V8_PPC_LITHIUM_PPC_H_
+
+#include "hydrogen.h"
+#include "lithium-allocator.h"
+#include "lithium.h"
+#include "safepoint-table.h"
+#include "utils.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class LCodeGen;
+
+#define LITHIUM_ALL_INSTRUCTION_LIST(V)         \
+  V(ControlInstruction)                         \
+  V(Call)                                       \
+  LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
+
+
+#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)    \
+  V(AccessArgumentsAt)                          \
+  V(AddI)                                       \
+  V(AllocateObject)                             \
+  V(ApplyArguments)                             \
+  V(ArgumentsElements)                          \
+  V(ArgumentsLength)                            \
+  V(ArithmeticD)                                \
+  V(ArithmeticT)                                \
+  V(ArrayLiteral)                               \
+  V(BitI)                                       \
+  V(BitNotI)                                    \
+  V(BoundsCheck)                                \
+  V(Branch)                                     \
+  V(CallConstantFunction)                       \
+  V(CallFunction)                               \
+  V(CallGlobal)                                 \
+  V(CallKeyed)                                  \
+  V(CallKnownGlobal)                            \
+  V(CallNamed)                                  \
+  V(CallNew)                                    \
+  V(CallRuntime)                                \
+  V(CallStub)                                   \
+  V(CheckFunction)                              \
+  V(CheckInstanceType)                          \
+  V(CheckNonSmi)                                \
+  V(CheckMaps)                                  \
+  V(CheckPrototypeMaps)                         \
+  V(CheckSmi)                                   \
+  V(ClampDToUint8)                              \
+  V(ClampIToUint8)                              \
+  V(ClampTToUint8)                              \
+  V(ClassOfTestAndBranch)                       \
+  V(CmpConstantEqAndBranch)                     \
+  V(CmpIDAndBranch)                             \
+  V(CmpObjectEqAndBranch)                       \
+  V(CmpMapAndBranch)                            \
+  V(CmpT)                                       \
+  V(ConstantD)                                  \
+  V(ConstantI)                                  \
+  V(ConstantT)                                  \
+  V(Context)                                    \
+  V(DeclareGlobals)                             \
+  V(DeleteProperty)                             \
+  V(Deoptimize)                                 \
+  V(DivI)                                       \
+  V(DoubleToI)                                  \
+  V(ElementsKind)                               \
+  V(FastLiteral)                                \
+  V(FixedArrayBaseLength)                       \
+  V(FunctionLiteral)                            \
+  V(GetCachedArrayIndex)                        \
+  V(GlobalObject)                               \
+  V(GlobalReceiver)                             \
+  V(Goto)                                       \
+  V(HasCachedArrayIndexAndBranch)               \
+  V(HasInstanceTypeAndBranch)                   \
+  V(In)                                         \
+  V(InstanceOf)                                 \
+  V(InstanceOfKnownGlobal)                      \
+  V(InstructionGap)                             \
+  V(Integer32ToDouble)                          \
+  V(Uint32ToDouble)                             \
+  V(InvokeFunction)                             \
+  V(IsConstructCallAndBranch)                   \
+  V(IsNilAndBranch)                             \
+  V(IsObjectAndBranch)                          \
+  V(IsStringAndBranch)                          \
+  V(IsSmiAndBranch)                             \
+  V(IsUndetectableAndBranch)                    \
+  V(JSArrayLength)                              \
+  V(Label)                                      \
+  V(LazyBailout)                                \
+  V(LoadContextSlot)                            \
+  V(LoadElements)                               \
+  V(LoadExternalArrayPointer)                   \
+  V(LoadFunctionPrototype)                      \
+  V(LoadGlobalCell)                             \
+  V(LoadGlobalGeneric)                          \
+  V(LoadKeyedFastDoubleElement)                 \
+  V(LoadKeyedFastElement)                       \
+  V(LoadKeyedGeneric)                           \
+  V(LoadKeyedSpecializedArrayElement)           \
+  V(LoadNamedField)                             \
+  V(LoadNamedFieldPolymorphic)                  \
+  V(LoadNamedGeneric)                           \
+  V(MapEnumLength)                              \
+  V(MathFloorOfDiv)                             \
+  V(MathMinMax)                                 \
+  V(ModI)                                       \
+  V(MulI)                                       \
+  V(NumberTagD)                                 \
+  V(NumberTagI)                                 \
+  V(NumberTagU)                                 \
+  V(NumberUntagD)                               \
+  V(ObjectLiteral)                              \
+  V(OsrEntry)                                   \
+  V(OuterContext)                               \
+  V(Parameter)                                  \
+  V(Power)                                      \
+  V(PushArgument)                               \
+  V(Random)                                     \
+  V(RegExpLiteral)                              \
+  V(Return)                                     \
+  V(ShiftI)                                     \
+  V(SmiTag)                                     \
+  V(SmiUntag)                                   \
+  V(StackCheck)                                 \
+  V(StoreContextSlot)                           \
+  V(StoreGlobalCell)                            \
+  V(StoreGlobalGeneric)                         \
+  V(StoreKeyedFastDoubleElement)                \
+  V(StoreKeyedFastElement)                      \
+  V(StoreKeyedGeneric)                          \
+  V(StoreKeyedSpecializedArrayElement)          \
+  V(StoreNamedField)                            \
+  V(StoreNamedGeneric)                          \
+  V(StringAdd)                                  \
+  V(StringCharCodeAt)                           \
+  V(StringCharFromCode)                         \
+  V(StringCompareAndBranch)                     \
+  V(StringLength)                               \
+  V(SubI)                                       \
+  V(TaggedToI)                                  \
+  V(ThisFunction)                               \
+  V(Throw)                                      \
+  V(ToFastProperties)                           \
+  V(TransitionElementsKind)                     \
+  V(Typeof)                                     \
+  V(TypeofIsAndBranch)                          \
+  V(UnaryMathOperation)                         \
+  V(UnknownOSRValue)                            \
+  V(ValueOf)                                    \
+  V(ForInPrepareMap)                            \
+  V(ForInCacheArray)                            \
+  V(CheckMapValue)                              \
+  V(LoadFieldByIndex)                           \
+  V(DateField)                                  \
+  V(WrapReceiver)                               \
+  V(Drop)
+
+
+#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)              \
+  virtual Opcode opcode() const { return LInstruction::k##type; } \
+  virtual void CompileToNative(LCodeGen* generator);              \
+  virtual const char* Mnemonic() const { return mnemonic; }       \
+  static L##type* cast(LInstruction* instr) {                     \
+    ASSERT(instr->Is##type());                                    \
+    return reinterpret_cast<L##type*>(instr);                     \
+  }
+
+
+#define DECLARE_HYDROGEN_ACCESSOR(type)     \
+  H##type* hydrogen() const {               \
+    return H##type::cast(hydrogen_value()); \
+  }
+
+
+class LInstruction: public ZoneObject {
+ public:
+  LInstruction()
+      :  environment_(NULL),
+         hydrogen_value_(NULL),
+         is_call_(false) { }
+  virtual ~LInstruction() { }
+
+  virtual void CompileToNative(LCodeGen* generator) = 0;
+  virtual const char* Mnemonic() const = 0;
+  virtual void PrintTo(StringStream* stream);
+  virtual void PrintDataTo(StringStream* stream);
+  virtual void PrintOutputOperandTo(StringStream* stream);
+
+  enum Opcode {
+    // Declare a unique enum value for each instruction.
+#define DECLARE_OPCODE(type) k##type,
+    LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
+    kNumberOfInstructions
+#undef DECLARE_OPCODE
+  };
+
+  virtual Opcode opcode() const = 0;
+
+  // Declare non-virtual type testers for all leaf IR classes.
+#define DECLARE_PREDICATE(type) \
+  bool Is##type() const { return opcode() == k##type; }
+  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
+#undef DECLARE_PREDICATE
+
+  // Declare virtual predicates for instructions that don't have
+  // an opcode.
+  virtual bool IsGap() const { return false; }
+
+  virtual bool IsControl() const { return false; }
+
+  void set_environment(LEnvironment* env) { environment_ = env; }
+  LEnvironment* environment() const { return environment_; }
+  bool HasEnvironment() const { return environment_ != NULL; }
+
+  void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
+  LPointerMap* pointer_map() const { return pointer_map_.get(); }
+  bool HasPointerMap() const { return pointer_map_.is_set(); }
+
+  void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
+  HValue* hydrogen_value() const { return hydrogen_value_; }
+
+  virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
+
+  void MarkAsCall() { is_call_ = true; }
+
+  // Interface to the register allocator and iterators.
+  bool IsMarkedAsCall() const { return is_call_; }
+
+  virtual bool HasResult() const = 0;
+  virtual LOperand* result() = 0;
+
+  LOperand* FirstInput() { return InputAt(0); }
+  LOperand* Output() { return HasResult() ? result() : NULL; }
+
+#ifdef DEBUG
+  void VerifyCall();
+#endif
+
+ private:
+  // Iterator support.
+  friend class InputIterator;
+  virtual int InputCount() = 0;
+  virtual LOperand* InputAt(int i) = 0;
+
+  friend class TempIterator;
+  virtual int TempCount() = 0;
+  virtual LOperand* TempAt(int i) = 0;
+
+  LEnvironment* environment_;
+  SetOncePointer<LPointerMap> pointer_map_;
+  HValue* hydrogen_value_;
+  bool is_call_;
+};
+
+
+// R = number of result operands (0 or 1).
+// I = number of input operands.
+// T = number of temporary operands.
+template<int R, int I, int T>
+class LTemplateInstruction: public LInstruction {
+ public:
+  // Allow 0 or 1 output operands.
+  STATIC_ASSERT(R == 0 || R == 1);
+  virtual bool HasResult() const { return R != 0; }
+  void set_result(LOperand* operand) { results_[0] = operand; }
+  LOperand* result() { return results_[0]; }
+
+ protected:
+  EmbeddedContainer<LOperand*, R> results_;
+  EmbeddedContainer<LOperand*, I> inputs_;
+  EmbeddedContainer<LOperand*, T> temps_;
+
+ private:
+  virtual int InputCount() { return I; }
+  virtual LOperand* InputAt(int i) { return inputs_[i]; }
+
+  virtual int TempCount() { return T; }
+  virtual LOperand* TempAt(int i) { return temps_[i]; }
+};
+
+
+class LGap: public LTemplateInstruction<0, 0, 0> {
+ public:
+  explicit LGap(HBasicBlock* block)
+      : block_(block) {
+    parallel_moves_[BEFORE] = NULL;
+    parallel_moves_[START] = NULL;
+    parallel_moves_[END] = NULL;
+    parallel_moves_[AFTER] = NULL;
+  }
+
+  // Can't use the DECLARE-macro here because of sub-classes.
+  virtual bool IsGap() const { return true; }
+  virtual void PrintDataTo(StringStream* stream);
+  static LGap* cast(LInstruction* instr) {
+    ASSERT(instr->IsGap());
+    return reinterpret_cast<LGap*>(instr);
+  }
+
+  bool IsRedundant() const;
+
+  HBasicBlock* block() const { return block_; }
+
+  enum InnerPosition {
+    BEFORE,
+    START,
+    END,
+    AFTER,
+    FIRST_INNER_POSITION = BEFORE,
+    LAST_INNER_POSITION = AFTER
+  };
+
+  LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone)  {
+    if (parallel_moves_[pos] == NULL) {
+      parallel_moves_[pos] = new(zone) LParallelMove(zone);
+    }
+    return parallel_moves_[pos];
+  }
+
+  LParallelMove* GetParallelMove(InnerPosition pos)  {
+    return parallel_moves_[pos];
+  }
+
+ private:
+  LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
+  HBasicBlock* block_;
+};
+
+
+class LInstructionGap: public LGap {
+ public:
+  explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
+};
+
+
+class LGoto: public LTemplateInstruction<0, 0, 0> {
+ public:
+  explicit LGoto(int block_id) : block_id_(block_id) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
+  virtual void PrintDataTo(StringStream* stream);
+  virtual bool IsControl() const { return true; }
+
+  int block_id() const { return block_id_; }
+
+ private:
+  int block_id_;
+};
+
+
+class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
+ public:
+  LLazyBailout() : gap_instructions_size_(0) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
+
+  void set_gap_instructions_size(int gap_instructions_size) {
+    gap_instructions_size_ = gap_instructions_size;
+  }
+  int gap_instructions_size() { return gap_instructions_size_; }
+
+ private:
+  int gap_instructions_size_;
+};
+
+
+class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
+};
+
+
+class LLabel: public LGap {
+ public:
+  explicit LLabel(HBasicBlock* block)
+      : LGap(block), replacement_(NULL) { }
+
+  DECLARE_CONCRETE_INSTRUCTION(Label, "label")
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  int block_id() const { return block()->block_id(); }
+  bool is_loop_header() const { return block()->IsLoopHeader(); }
+  Label* label() { return &label_; }
+  LLabel* replacement() const { return replacement_; }
+  void set_replacement(LLabel* label) { replacement_ = label; }
+  bool HasReplacement() const { return replacement_ != NULL; }
+
+ private:
+  Label label_;
+  LLabel* replacement_;
+};
+
+
+class LParameter: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
+};
+
+
+class LCallStub: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
+  DECLARE_HYDROGEN_ACCESSOR(CallStub)
+
+  TranscendentalCache::Type transcendental_type() {
+    return hydrogen()->transcendental_type();
+  }
+};
+
+
+class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
+};
+
+
+template<int I, int T>
+class LControlInstruction: public LTemplateInstruction<0, I, T> {
+ public:
+  virtual bool IsControl() const { return true; }
+
+  int SuccessorCount() { return hydrogen()->SuccessorCount(); }
+  HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
+  int true_block_id() { return hydrogen()->SuccessorAt(0)->block_id(); }
+  int false_block_id() { return hydrogen()->SuccessorAt(1)->block_id(); }
+
+ private:
+  HControlInstruction* hydrogen() {
+    return HControlInstruction::cast(this->hydrogen_value());
+  }
+};
+
+
+class LWrapReceiver: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LWrapReceiver(LOperand* receiver, LOperand* function) {
+    inputs_[0] = receiver;
+    inputs_[1] = function;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
+
+  LOperand* receiver() { return inputs_[0]; }
+  LOperand* function() { return inputs_[1]; }
+};
+
+
+class LApplyArguments: public LTemplateInstruction<1, 4, 0> {
+ public:
+  LApplyArguments(LOperand* function,
+                  LOperand* receiver,
+                  LOperand* length,
+                  LOperand* elements) {
+    inputs_[0] = function;
+    inputs_[1] = receiver;
+    inputs_[2] = length;
+    inputs_[3] = elements;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
+
+  LOperand* function() { return inputs_[0]; }
+  LOperand* receiver() { return inputs_[1]; }
+  LOperand* length() { return inputs_[2]; }
+  LOperand* elements() { return inputs_[3]; }
+};
+
+
+class LAccessArgumentsAt: public LTemplateInstruction<1, 3, 0> {
+ public:
+  LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) {
+    inputs_[0] = arguments;
+    inputs_[1] = length;
+    inputs_[2] = index;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
+
+  LOperand* arguments() { return inputs_[0]; }
+  LOperand* length() { return inputs_[1]; }
+  LOperand* index() { return inputs_[2]; }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LArgumentsLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LArgumentsLength(LOperand* elements) {
+    inputs_[0] = elements;
+  }
+
+  LOperand* elements() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
+};
+
+
+class LArgumentsElements: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
+  DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
+};
+
+
+class LModI: public LTemplateInstruction<1, 2, 3> {
+ public:
+  // Used when the right hand is a constant power of 2.
+  LModI(LOperand* left,
+        LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = NULL;
+    temps_[1] = NULL;
+    temps_[2] = NULL;
+  }
+
+  // Used for the standard case.
+  LModI(LOperand* left,
+        LOperand* right,
+        LOperand* temp,
+        LOperand* temp2,
+        LOperand* temp3) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp;
+    temps_[1] = temp2;
+    temps_[2] = temp3;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+  LOperand* temp3() { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
+  DECLARE_HYDROGEN_ACCESSOR(Mod)
+};
+
+
+class LDivI: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LDivI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
+  DECLARE_HYDROGEN_ACCESSOR(Div)
+};
+
+
+class LMathFloorOfDiv: public LTemplateInstruction<1, 2, 1> {
+ public:
+  LMathFloorOfDiv(LOperand* left,
+                  LOperand* right,
+                  LOperand* temp = NULL) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv, "math-floor-of-div")
+  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
+};
+
+
+class LMulI: public LTemplateInstruction<1, 2, 1> {
+ public:
+  LMulI(LOperand* left, LOperand* right, LOperand* temp) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
+  DECLARE_HYDROGEN_ACCESSOR(Mul)
+};
+
+
+class LCmpIDAndBranch: public LControlInstruction<2, 0> {
+ public:
+  LCmpIDAndBranch(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareIDAndBranch)
+
+  Token::Value op() const { return hydrogen()->token(); }
+  bool is_double() const {
+    return hydrogen()->GetInputRepresentation().IsDouble();
+  }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LUnaryMathOperation: public LTemplateInstruction<1, 1, 1> {
+ public:
+  LUnaryMathOperation(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary-math-operation")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
+
+  virtual void PrintDataTo(StringStream* stream);
+  BuiltinFunctionId op() const { return hydrogen()->op(); }
+};
+
+
+class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> {
+ public:
+  LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch,
+                               "cmp-object-eq-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
+};
+
+
+class LCmpConstantEqAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LCmpConstantEqAndBranch(LOperand* left) {
+    inputs_[0] = left;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CmpConstantEqAndBranch,
+                               "cmp-constant-eq-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareConstantEqAndBranch)
+};
+
+
+class LIsNilAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LIsNilAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch, "is-nil-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsNilAndBranch)
+
+  EqualityKind kind() const { return hydrogen()->kind(); }
+  NilValue nil() const { return hydrogen()->nil(); }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LIsObjectAndBranch: public LControlInstruction<1, 1> {
+ public:
+  LIsObjectAndBranch(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LIsStringAndBranch: public LControlInstruction<1, 1> {
+ public:
+  LIsStringAndBranch(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LIsSmiAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LIsSmiAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LIsUndetectableAndBranch: public LControlInstruction<1, 1> {
+ public:
+  explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
+                               "is-undetectable-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LStringCompareAndBranch: public LControlInstruction<2, 0> {
+ public:
+  LStringCompareAndBranch(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
+                               "string-compare-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
+
+  Token::Value op() const { return hydrogen()->token(); }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LHasInstanceTypeAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
+                               "has-instance-type-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LGetCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LGetCachedArrayIndex(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
+  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
+};
+
+
+class LHasCachedArrayIndexAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LHasCachedArrayIndexAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
+                               "has-cached-array-index-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LClassOfTestAndBranch: public LControlInstruction<1, 1> {
+ public:
+  LClassOfTestAndBranch(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
+                               "class-of-test-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LCmpT: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LCmpT(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
+  DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
+
+  Token::Value op() const { return hydrogen()->token(); }
+};
+
+
+class LInstanceOf: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LInstanceOf(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
+};
+
+
+class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 1> {
+ public:
+  LInstanceOfKnownGlobal(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
+                               "instance-of-known-global")
+  DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
+
+  Handle<JSFunction> function() const { return hydrogen()->function(); }
+  LEnvironment* GetDeferredLazyDeoptimizationEnvironment() {
+    return lazy_deopt_env_;
+  }
+  virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) {
+    lazy_deopt_env_ = env;
+  }
+
+ private:
+  LEnvironment* lazy_deopt_env_;
+};
+
+
+class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
+ public:
+  LBoundsCheck(LOperand* index, LOperand* length) {
+    inputs_[0] = index;
+    inputs_[1] = length;
+  }
+
+  LOperand* index() { return inputs_[0]; }
+  LOperand* length() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
+  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
+};
+
+
+class LBitI: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LBitI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  Token::Value op() const { return hydrogen()->op(); }
+
+  DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
+  DECLARE_HYDROGEN_ACCESSOR(Bitwise)
+};
+
+
+class LShiftI: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
+      : op_(op), can_deopt_(can_deopt) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  Token::Value op() const { return op_; }
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+  bool can_deopt() const { return can_deopt_; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
+
+ private:
+  Token::Value op_;
+  bool can_deopt_;
+};
+
+
+class LSubI: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LSubI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
+  DECLARE_HYDROGEN_ACCESSOR(Sub)
+};
+
+
+class LConstantI: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  int32_t value() const { return hydrogen()->Integer32Value(); }
+};
+
+
+class LConstantD: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  double value() const { return hydrogen()->DoubleValue(); }
+};
+
+
+class LConstantT: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  Handle<Object> value() const { return hydrogen()->handle(); }
+};
+
+
+class LBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
+  DECLARE_HYDROGEN_ACCESSOR(Branch)
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 1> {
+ public:
+  LCmpMapAndBranch(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareMap)
+
+  virtual bool IsControl() const { return true; }
+
+  Handle<Map> map() const { return hydrogen()->map(); }
+  int true_block_id() const {
+    return hydrogen()->FirstSuccessor()->block_id();
+  }
+  int false_block_id() const {
+    return hydrogen()->SecondSuccessor()->block_id();
+  }
+};
+
+
+class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LJSArrayLength(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
+  DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
+};
+
+
+class LFixedArrayBaseLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LFixedArrayBaseLength(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength,
+                               "fixed-array-base-length")
+  DECLARE_HYDROGEN_ACCESSOR(FixedArrayBaseLength)
+};
+
+
+class LMapEnumLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMapEnumLength(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
+};
+
+
+class LElementsKind: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LElementsKind(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ElementsKind, "elements-kind")
+  DECLARE_HYDROGEN_ACCESSOR(ElementsKind)
+};
+
+
+class LValueOf: public LTemplateInstruction<1, 1, 1> {
+ public:
+  LValueOf(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of")
+  DECLARE_HYDROGEN_ACCESSOR(ValueOf)
+};
+
+
+class LDateField: public LTemplateInstruction<1, 1, 1> {
+ public:
+  LDateField(LOperand* date, LOperand* temp, Smi* index) : index_(index) {
+    inputs_[0] = date;
+    temps_[0] = temp;
+  }
+
+  LOperand* date() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+  Smi* index() const { return index_; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ValueOf, "date-field")
+  DECLARE_HYDROGEN_ACCESSOR(ValueOf)
+
+ private:
+  Smi* index_;
+};
+
+
+class LThrow: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LThrow(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
+};
+
+
+class LBitNotI: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LBitNotI(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
+};
+
+
+class LAddI: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LAddI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
+  DECLARE_HYDROGEN_ACCESSOR(Add)
+};
+
+
+class LMathMinMax: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LMathMinMax(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "min-max")
+  DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
+};
+
+
+class LPower: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LPower(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
+  DECLARE_HYDROGEN_ACCESSOR(Power)
+};
+
+
+class LRandom: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LRandom(LOperand* global_object) {
+    inputs_[0] = global_object;
+  }
+
+  LOperand* global_object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
+class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
+      : op_(op) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  Token::Value op() const { return op_; }
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  virtual Opcode opcode() const { return LInstruction::kArithmeticD; }
+  virtual void CompileToNative(LCodeGen* generator);
+  virtual const char* Mnemonic() const;
+
+ private:
+  Token::Value op_;
+};
+
+
+class LArithmeticT: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LArithmeticT(Token::Value op, LOperand* left, LOperand* right)
+      : op_(op) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+  Token::Value op() const { return op_; }
+
+  virtual Opcode opcode() const { return LInstruction::kArithmeticT; }
+  virtual void CompileToNative(LCodeGen* generator);
+  virtual const char* Mnemonic() const;
+
+ private:
+  Token::Value op_;
+};
+
+
+class LReturn: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LReturn(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Return, "return")
+};
+
+
+class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadNamedField(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
+  DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
+};
+
+
+class LLoadNamedFieldPolymorphic: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadNamedFieldPolymorphic(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field-polymorphic")
+  DECLARE_HYDROGEN_ACCESSOR(LoadNamedFieldPolymorphic)
+};
+
+
+class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadNamedGeneric(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
+  DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
+
+  Handle<Object> name() const { return hydrogen()->name(); }
+};
+
+
+class LLoadFunctionPrototype: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadFunctionPrototype(LOperand* function) {
+    inputs_[0] = function;
+  }
+
+  LOperand* function() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
+  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
+};
+
+
+class LLoadElements: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadElements(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
+};
+
+
+class LLoadExternalArrayPointer: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadExternalArrayPointer(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
+                               "load-external-array-pointer")
+};
+
+
+class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
+    inputs_[0] = elements;
+    inputs_[1] = key;
+  }
+
+  LOperand* elements() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
+
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
+};
+
+
+class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
+    inputs_[0] = elements;
+    inputs_[1] = key;
+  }
+
+  LOperand* elements() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
+                               "load-keyed-fast-double-element")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
+
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
+};
+
+
+class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LLoadKeyedSpecializedArrayElement(LOperand* external_pointer, LOperand* key) {
+    inputs_[0] = external_pointer;
+    inputs_[1] = key;
+  }
+
+  LOperand* external_pointer() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement,
+                               "load-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedSpecializedArrayElement)
+
+  ElementsKind elements_kind() const {
+    return hydrogen()->elements_kind();
+  }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
+};
+
+
+class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LLoadKeyedGeneric(LOperand* object, LOperand* key) {
+    inputs_[0] = object;
+    inputs_[1] = key;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
+};
+
+
+class LLoadGlobalCell: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
+  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
+};
+
+
+class LLoadGlobalGeneric: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadGlobalGeneric(LOperand* global_object) {
+    inputs_[0] = global_object;
+  }
+
+  LOperand* global_object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
+  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
+
+  Handle<Object> name() const { return hydrogen()->name(); }
+  bool for_typeof() const { return hydrogen()->for_typeof(); }
+};
+
+
+class LStoreGlobalCell: public LTemplateInstruction<0, 1, 1> {
+ public:
+  LStoreGlobalCell(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
+  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
+};
+
+
+class LStoreGlobalGeneric: public LTemplateInstruction<0, 2, 0> {
+ public:
+  explicit LStoreGlobalGeneric(LOperand* global_object,
+                               LOperand* value) {
+    inputs_[0] = global_object;
+    inputs_[1] = value;
+  }
+
+  LOperand* global_object() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
+  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
+
+  Handle<Object> name() const { return hydrogen()->name(); }
+  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+};
+
+
+class LLoadContextSlot: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LLoadContextSlot(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
+  DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
+
+  int slot_index() { return hydrogen()->slot_index(); }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LStoreContextSlot: public LTemplateInstruction<0, 2, 0> {
+ public:
+  LStoreContextSlot(LOperand* context, LOperand* value) {
+    inputs_[0] = context;
+    inputs_[1] = value;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
+  DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
+
+  int slot_index() { return hydrogen()->slot_index(); }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LPushArgument: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LPushArgument(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
+};
+
+
+class LDrop: public LTemplateInstruction<0, 0, 0> {
+ public:
+  explicit LDrop(int count) : count_(count) { }
+
+  int count() const { return count_; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
+
+ private:
+  int count_;
+};
+
+
+class LThisFunction: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
+  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
+};
+
+
+class LContext: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(Context, "context")
+};
+
+
+class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LOuterContext(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  LOperand* context() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context")
+};
+
+
+class LDeclareGlobals: public LTemplateInstruction<0, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
+  DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
+};
+
+
+class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LGlobalObject(LOperand* context) {
+    inputs_[0] = context;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+  LOperand* context() { return inputs_[0]; }
+};
+
+
+class LGlobalReceiver: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LGlobalReceiver(LOperand* global_object) {
+    inputs_[0] = global_object;
+  }
+
+  LOperand* global_object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
+};
+
+
+class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function")
+  DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  Handle<JSFunction> function() { return hydrogen()->function(); }
+  int arity() const { return hydrogen()->argument_count() - 1; }
+};
+
+
+class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LInvokeFunction(LOperand* function) {
+    inputs_[0] = function;
+  }
+
+  LOperand* function() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
+  DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  int arity() const { return hydrogen()->argument_count() - 1; }
+  Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
+};
+
+
+class LCallKeyed: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCallKeyed(LOperand* key) {
+    inputs_[0] = key;
+  }
+
+  LOperand* key() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
+  DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  int arity() const { return hydrogen()->argument_count() - 1; }
+};
+
+
+
+class LCallNamed: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named")
+  DECLARE_HYDROGEN_ACCESSOR(CallNamed)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  Handle<String> name() const { return hydrogen()->name(); }
+  int arity() const { return hydrogen()->argument_count() - 1; }
+};
+
+
+class LCallFunction: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCallFunction(LOperand* function) {
+    inputs_[0] = function;
+  }
+
+  LOperand* function() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
+  DECLARE_HYDROGEN_ACCESSOR(CallFunction)
+
+  int arity() const { return hydrogen()->argument_count() - 1; }
+};
+
+
+class LCallGlobal: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global")
+  DECLARE_HYDROGEN_ACCESSOR(CallGlobal)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  Handle<String> name() const {return hydrogen()->name(); }
+  int arity() const { return hydrogen()->argument_count() - 1; }
+};
+
+
+class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global")
+  DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  Handle<JSFunction> target() const { return hydrogen()->target();  }
+  int arity() const { return hydrogen()->argument_count() - 1;  }
+};
+
+
+class LCallNew: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCallNew(LOperand* constructor) {
+    inputs_[0] = constructor;
+  }
+
+  LOperand* constructor() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
+  DECLARE_HYDROGEN_ACCESSOR(CallNew)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  int arity() const { return hydrogen()->argument_count() - 1; }
+};
+
+
+class LCallRuntime: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
+  DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
+
+  const Runtime::Function* function() const { return hydrogen()->function(); }
+  int arity() const { return hydrogen()->argument_count(); }
+};
+
+
+class LInteger32ToDouble: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LInteger32ToDouble(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
+};
+
+
+class LUint32ToDouble: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LUint32ToDouble(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
+};
+
+
+class LNumberTagI: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LNumberTagI(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
+};
+
+
+class LNumberTagU: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LNumberTagU(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
+};
+
+
+class LNumberTagD: public LTemplateInstruction<1, 1, 2> {
+ public:
+  LNumberTagD(LOperand* value, LOperand* temp, LOperand* temp2) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+    temps_[1] = temp2;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
+};
+
+
+// Sometimes truncating conversion from a tagged value to an int32.
+class LDoubleToI: public LTemplateInstruction<1, 1, 2> {
+ public:
+  LDoubleToI(LOperand* value, LOperand* temp, LOperand* temp2) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+    temps_[1] = temp2;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
+
+  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
+};
+
+
+// Truncating conversion from a tagged value to an int32.
+class LTaggedToI: public LTemplateInstruction<1, 1, 3> {
+ public:
+  LTaggedToI(LOperand* value,
+             LOperand* temp,
+             LOperand* temp2,
+             LOperand* temp3) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+    temps_[1] = temp2;
+    temps_[2] = temp3;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+  LOperand* temp3() { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
+
+  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
+};
+
+
+class LSmiTag: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LSmiTag(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
+};
+
+
+class LNumberUntagD: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LNumberUntagD(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
+  DECLARE_HYDROGEN_ACCESSOR(Change)
+};
+
+
+class LSmiUntag: public LTemplateInstruction<1, 1, 0> {
+ public:
+  LSmiUntag(LOperand* value, bool needs_check)
+      : needs_check_(needs_check) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  bool needs_check() const { return needs_check_; }
+
+  DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
+
+ private:
+  bool needs_check_;
+};
+
+
+class LStoreNamedField: public LTemplateInstruction<0, 2, 1> {
+ public:
+  LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) {
+    inputs_[0] = object;
+    inputs_[1] = value;
+    temps_[0] = temp;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  Handle<Object> name() const { return hydrogen()->name(); }
+  bool is_in_object() { return hydrogen()->is_in_object(); }
+  int offset() { return hydrogen()->offset(); }
+  Handle<Map> transition() const { return hydrogen()->transition(); }
+};
+
+
+class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> {
+ public:
+  LStoreNamedGeneric(LOperand* object, LOperand* value) {
+    inputs_[0] = object;
+    inputs_[1] = value;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  Handle<Object> name() const { return hydrogen()->name(); }
+  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+};
+
+
+class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+  LStoreKeyedFastElement(LOperand* object, LOperand* key, LOperand* value) {
+    inputs_[0] = object;
+    inputs_[1] = key;
+    inputs_[2] = value;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement,
+                               "store-keyed-fast-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastElement)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
+};
+
+
+class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+  LStoreKeyedFastDoubleElement(LOperand* elements,
+                               LOperand* key,
+                               LOperand* value) {
+    inputs_[0] = elements;
+    inputs_[1] = key;
+    inputs_[2] = value;
+  }
+
+  LOperand* elements() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
+                               "store-keyed-fast-double-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
+
+  bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
+};
+
+
+class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
+ public:
+  LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* value) {
+    inputs_[0] = obj;
+    inputs_[1] = key;
+    inputs_[2] = value;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+};
+
+class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
+ public:
+  LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,
+                                     LOperand* key,
+                                     LOperand* value) {
+    inputs_[0] = external_pointer;
+    inputs_[1] = key;
+    inputs_[2] = value;
+  }
+
+  LOperand* external_pointer() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement,
+                               "store-keyed-specialized-array-element")
+  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedSpecializedArrayElement)
+
+  ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
+  uint32_t additional_index() const { return hydrogen()->index_offset(); }
+};
+
+
+class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
+ public:
+  LTransitionElementsKind(LOperand* object,
+                          LOperand* new_map_temp,
+                          LOperand* temp) {
+    inputs_[0] = object;
+    temps_[0] = new_map_temp;
+    temps_[1] = temp;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* new_map_temp() { return temps_[0]; }
+  LOperand* temp() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
+                               "transition-elements-kind")
+  DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  Handle<Map> original_map() { return hydrogen()->original_map(); }
+  Handle<Map> transitioned_map() { return hydrogen()->transitioned_map(); }
+};
+
+
+class LStringAdd: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LStringAdd(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
+  DECLARE_HYDROGEN_ACCESSOR(StringAdd)
+};
+
+
+
+class LStringCharCodeAt: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LStringCharCodeAt(LOperand* string, LOperand* index) {
+    inputs_[0] = string;
+    inputs_[1] = index;
+  }
+
+  LOperand* string() { return inputs_[0]; }
+  LOperand* index() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
+  DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
+};
+
+
+class LStringCharFromCode: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LStringCharFromCode(LOperand* char_code) {
+    inputs_[0] = char_code;
+  }
+
+  LOperand* char_code() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
+  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
+};
+
+
+class LStringLength: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LStringLength(LOperand* string) {
+    inputs_[0] = string;
+  }
+
+  LOperand* string() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
+  DECLARE_HYDROGEN_ACCESSOR(StringLength)
+};
+
+
+class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckFunction(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
+  DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
+};
+
+
+class LCheckInstanceType: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckInstanceType(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
+  DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
+};
+
+
+class LCheckMaps: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckMaps(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
+  DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
+};
+
+
+class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 2> {
+ public:
+  LCheckPrototypeMaps(LOperand* temp, LOperand* temp2)  {
+    temps_[0] = temp;
+    temps_[1] = temp2;
+  }
+
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
+  DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
+
+  Handle<JSObject> prototype() const { return hydrogen()->prototype(); }
+  Handle<JSObject> holder() const { return hydrogen()->holder(); }
+};
+
+
+class LCheckSmi: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
+};
+
+
+class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckNonSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
+};
+
+
+class LClampDToUint8: public LTemplateInstruction<1, 1, 1> {
+ public:
+  LClampDToUint8(LOperand* unclamped, LOperand* temp) {
+    inputs_[0] = unclamped;
+    temps_[0] = temp;
+  }
+
+  LOperand* unclamped() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
+};
+
+
+class LClampIToUint8: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LClampIToUint8(LOperand* unclamped) {
+    inputs_[0] = unclamped;
+  }
+
+  LOperand* unclamped() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
+};
+
+
+class LClampTToUint8: public LTemplateInstruction<1, 1, 2> {
+ public:
+  LClampTToUint8(LOperand* unclamped, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = unclamped;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* unclamped() { return inputs_[0]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
+};
+
+
+class LAllocateObject: public LTemplateInstruction<1, 0, 2> {
+ public:
+  LAllocateObject(LOperand* temp, LOperand* temp2) {
+    temps_[0] = temp;
+    temps_[1] = temp2;
+  }
+
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object")
+  DECLARE_HYDROGEN_ACCESSOR(AllocateObject)
+};
+
+
+class LFastLiteral: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(FastLiteral, "fast-literal")
+  DECLARE_HYDROGEN_ACCESSOR(FastLiteral)
+};
+
+
+class LArrayLiteral: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array-literal")
+  DECLARE_HYDROGEN_ACCESSOR(ArrayLiteral)
+};
+
+
+class LObjectLiteral: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object-literal")
+  DECLARE_HYDROGEN_ACCESSOR(ObjectLiteral)
+};
+
+
+class LRegExpLiteral: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
+  DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
+};
+
+
+class LFunctionLiteral: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
+  DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
+
+  Handle<SharedFunctionInfo> shared_info() { return hydrogen()->shared_info(); }
+};
+
+
+class LToFastProperties: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LToFastProperties(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
+  DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
+};
+
+
+class LTypeof: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LTypeof(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
+};
+
+
+class LTypeofIsAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LTypeofIsAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
+
+  Handle<String> type_literal() { return hydrogen()->type_literal(); }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LIsConstructCallAndBranch: public LControlInstruction<0, 1> {
+ public:
+  explicit LIsConstructCallAndBranch(LOperand* temp) {
+    temps_[0] = temp;
+  }
+
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
+                               "is-construct-call-and-branch")
+};
+
+
+class LDeleteProperty: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LDeleteProperty(LOperand* object, LOperand* key) {
+    inputs_[0] = object;
+    inputs_[1] = key;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete-property")
+};
+
+
+class LOsrEntry: public LTemplateInstruction<0, 0, 0> {
+ public:
+  LOsrEntry();
+
+  DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
+
+  LOperand** SpilledRegisterArray() { return register_spills_; }
+  LOperand** SpilledDoubleRegisterArray() { return double_register_spills_; }
+
+  void MarkSpilledRegister(int allocation_index, LOperand* spill_operand);
+  void MarkSpilledDoubleRegister(int allocation_index,
+                                 LOperand* spill_operand);
+
+ private:
+  // Arrays of spill slot operands for registers with an assigned spill
+  // slot, i.e., that must also be restored to the spill slot on OSR entry.
+  // NULL if the register has no assigned spill slot.  Indexed by allocation
+  // index.
+  LOperand* register_spills_[Register::kNumAllocatableRegisters];
+  LOperand* double_register_spills_[DoubleRegister::kNumAllocatableRegisters];
+};
+
+
+class LStackCheck: public LTemplateInstruction<0, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
+  DECLARE_HYDROGEN_ACCESSOR(StackCheck)
+
+  Label* done_label() { return &done_label_; }
+
+ private:
+  Label done_label_;
+};
+
+
+class LIn: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LIn(LOperand* key, LOperand* object) {
+    inputs_[0] = key;
+    inputs_[1] = object;
+  }
+
+  LOperand* key() { return inputs_[0]; }
+  LOperand* object() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(In, "in")
+};
+
+
+class LForInPrepareMap: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LForInPrepareMap(LOperand* object) {
+    inputs_[0] = object;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
+};
+
+
+class LForInCacheArray: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LForInCacheArray(LOperand* map) {
+    inputs_[0] = map;
+  }
+
+  LOperand* map() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
+
+  int idx() {
+    return HForInCacheArray::cast(this->hydrogen_value())->idx();
+  }
+};
+
+
+class LCheckMapValue: public LTemplateInstruction<0, 2, 0> {
+ public:
+  LCheckMapValue(LOperand* value, LOperand* map) {
+    inputs_[0] = value;
+    inputs_[1] = map;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* map() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
+};
+
+
+class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
+ public:
+  LLoadFieldByIndex(LOperand* object, LOperand* index) {
+    inputs_[0] = object;
+    inputs_[1] = index;
+  }
+
+  LOperand* object() { return inputs_[0]; }
+  LOperand* index() { return inputs_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
+};
+
+
+class LChunkBuilder;
+class LPlatformChunk: public LChunk {
+ public:
+  LPlatformChunk(CompilationInfo* info, HGraph* graph)
+      : LChunk(info, graph) { }
+
+  int GetNextSpillIndex(bool is_double);
+  LOperand* GetNextSpillSlot(bool is_double);
+};
+
+
+class LChunkBuilder BASE_EMBEDDED {
+ public:
+  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
+      : chunk_(NULL),
+        info_(info),
+        graph_(graph),
+        zone_(graph->zone()),
+        status_(UNUSED),
+        current_instruction_(NULL),
+        current_block_(NULL),
+        next_block_(NULL),
+        argument_count_(0),
+        allocator_(allocator),
+        position_(RelocInfo::kNoPosition),
+        instruction_pending_deoptimization_environment_(NULL),
+        pending_deoptimization_ast_id_(BailoutId::None()) { }
+
+  // Build the sequence for the graph.
+  LPlatformChunk* Build();
+
+  // Declare methods that deal with the individual node types.
+#define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
+  HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
+#undef DECLARE_DO
+
+  static bool HasMagicNumberForDivisor(int32_t divisor);
+  static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* val);
+  static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
+
+ private:
+  enum Status {
+    UNUSED,
+    BUILDING,
+    DONE,
+    ABORTED
+  };
+
+  LPlatformChunk* chunk() const { return chunk_; }
+  CompilationInfo* info() const { return info_; }
+  HGraph* graph() const { return graph_; }
+  Zone* zone() const { return zone_; }
+
+  bool is_unused() const { return status_ == UNUSED; }
+  bool is_building() const { return status_ == BUILDING; }
+  bool is_done() const { return status_ == DONE; }
+  bool is_aborted() const { return status_ == ABORTED; }
+
+  void Abort(const char* reason);
+
+  // Methods for getting operands for Use / Define / Temp.
+  LUnallocated* ToUnallocated(Register reg);
+  LUnallocated* ToUnallocated(DoubleRegister reg);
+
+  // Methods for setting up define-use relationships.
+  MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
+  MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
+  MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
+                                           DoubleRegister fixed_register);
+
+  // A value that is guaranteed to be allocated to a register.
+  // Operand created by UseRegister is guaranteed to be live until the end of
+  // instruction. This means that register allocator will not reuse it's
+  // register for any other operand inside instruction.
+  // Operand created by UseRegisterAtStart is guaranteed to be live only at
+  // instruction start. Register allocator is free to assign the same register
+  // to some other operand used inside instruction (i.e. temporary or
+  // output).
+  MUST_USE_RESULT LOperand* UseRegister(HValue* value);
+  MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
+
+  // An input operand in a register that may be trashed.
+  MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
+
+  // An input operand in a register or stack slot.
+  MUST_USE_RESULT LOperand* Use(HValue* value);
+  MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
+
+  // An input operand in a register, stack slot or a constant operand.
+  MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
+  MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
+
+  // An input operand in a register or a constant operand.
+  MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
+  MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
+
+  // An input operand in register, stack slot or a constant operand.
+  // Will not be moved to a register even if one is freely available.
+  MUST_USE_RESULT LOperand* UseAny(HValue* value);
+
+  // Temporary operand that must be in a register.
+  MUST_USE_RESULT LUnallocated* TempRegister();
+  MUST_USE_RESULT LOperand* FixedTemp(Register reg);
+  MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg);
+
+  // Methods for setting up define-use relationships.
+  // Return the same instruction that they are passed.
+  template<int I, int T>
+      LInstruction* Define(LTemplateInstruction<1, I, T>* instr,
+                           LUnallocated* result);
+  template<int I, int T>
+      LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr);
+  template<int I, int T>
+      LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr,
+                                    int index);
+  template<int I, int T>
+      LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr);
+  template<int I, int T>
+      LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr,
+                                Register reg);
+  template<int I, int T>
+      LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr,
+                                      DoubleRegister reg);
+  LInstruction* AssignEnvironment(LInstruction* instr);
+  LInstruction* AssignPointerMap(LInstruction* instr);
+
+  enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
+
+  // By default we assume that instruction sequences generated for calls
+  // cannot deoptimize eagerly and we do not attach environment to this
+  // instruction.
+  LInstruction* MarkAsCall(
+      LInstruction* instr,
+      HInstruction* hinstr,
+      CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
+
+  LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
+                                  int* argument_index_accumulator);
+
+  void VisitInstruction(HInstruction* current);
+
+  void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
+  LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
+  LInstruction* DoArithmeticD(Token::Value op,
+                              HArithmeticBinaryOperation* instr);
+  LInstruction* DoArithmeticT(Token::Value op,
+                              HArithmeticBinaryOperation* instr);
+
+  LPlatformChunk* chunk_;
+  CompilationInfo* info_;
+  HGraph* const graph_;
+  Zone* zone_;
+  Status status_;
+  HInstruction* current_instruction_;
+  HBasicBlock* current_block_;
+  HBasicBlock* next_block_;
+  int argument_count_;
+  LAllocator* allocator_;
+  int position_;
+  LInstruction* instruction_pending_deoptimization_environment_;
+  BailoutId pending_deoptimization_ast_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
+};
+
+#undef DECLARE_HYDROGEN_ACCESSOR
+#undef DECLARE_CONCRETE_INSTRUCTION
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_LITHIUM_PPC_H_
diff --git a/src/ppc/macro-assembler-ppc.cc b/src/ppc/macro-assembler-ppc.cc
new file mode 100644
index 0000000..b590a0c
--- /dev/null
+++ b/src/ppc/macro-assembler-ppc.cc
@@ -0,0 +1,4460 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <limits.h>  // For LONG_MIN, LONG_MAX.
+#include <assert.h>  // For assert
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "bootstrapper.h"
+#include "codegen.h"
+#include "debug.h"
+#include "runtime.h"
+
+namespace v8 {
+namespace internal {
+
+MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
+    : Assembler(arg_isolate, buffer, size),
+      generating_stub_(false),
+      allow_stub_calls_(true),
+      has_frame_(false) {
+  if (isolate() != NULL) {
+    code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
+                                  isolate());
+  }
+}
+
+
+void MacroAssembler::Jump(Register target, Condition cond) {
+  ASSERT(cond == al);
+  mtctr(target);
+  bcr();
+}
+
+
+void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
+                          Condition cond, CRegister cr) {
+  Label skip;
+
+  if (cond != al) b(NegateCondition(cond), &skip, cr);
+
+  ASSERT(rmode == RelocInfo::CODE_TARGET ||
+         rmode == RelocInfo::RUNTIME_ENTRY);
+
+  mov(r0, Operand(target, rmode));
+  mtctr(r0);
+  bcr();
+
+  bind(&skip);
+  //  mov(pc, Operand(target, rmode), LeaveCC, cond);
+}
+
+
+void MacroAssembler::Jump(Address target, RelocInfo::Mode rmode,
+                          Condition cond, CRegister cr) {
+  ASSERT(!RelocInfo::IsCodeTarget(rmode));
+  Jump(reinterpret_cast<intptr_t>(target), rmode, cond, cr);
+}
+
+
+void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
+                          Condition cond) {
+  ASSERT(RelocInfo::IsCodeTarget(rmode));
+  // 'code' is always generated ppc code, never THUMB code
+  Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
+}
+
+
+int MacroAssembler::CallSize(Register target, Condition cond) {
+  return 2 * kInstrSize;
+}
+
+
+void MacroAssembler::Call(Register target, Condition cond) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  Label start;
+  bind(&start);
+  ASSERT(cond == al);  // in prep of removal of condition
+
+  // Statement positions are expected to be recorded when the target
+  // address is loaded.
+  positions_recorder()->WriteRecordedPositions();
+
+  // branch via link register and set LK bit for return point
+  mtlr(target);
+  bclr(BA, SetLK);
+
+  ASSERT_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start));
+}
+
+
+int MacroAssembler::CallSize(
+    Address target, RelocInfo::Mode rmode, Condition cond) {
+  int size;
+  int movSize;
+
+#if 0  // Account for variable length Assembler::mov sequence.
+  intptr_t value = reinterpret_cast<intptr_t>(target);
+  if (is_int16(value) || (((value >> 16) << 16) == value)) {
+    movSize = 1;
+  } else {
+    movSize = 2;
+  }
+#else
+
+#if V8_TARGET_ARCH_PPC64
+  movSize = 5;
+#else
+  movSize = 2;
+#endif
+
+#endif
+
+  size = (2 + movSize) * kInstrSize;
+
+  return size;
+}
+
+
+int MacroAssembler::CallSizeNotPredictableCodeSize(
+    Address target, RelocInfo::Mode rmode, Condition cond) {
+  int size;
+  int movSize;
+
+#if 0  // Account for variable length Assembler::mov sequence.
+  intptr_t value = reinterpret_cast<intptr_t>(target);
+  if (is_int16(value) || (((value >> 16) << 16) == value)) {
+    movSize = 1;
+  } else {
+    movSize = 2;
+  }
+#else
+
+#if V8_TARGET_ARCH_PPC64
+  movSize = 5;
+#else
+  movSize = 2;
+#endif
+
+#endif
+
+  size = (2 + movSize) * kInstrSize;
+
+  return size;
+}
+
+
+void MacroAssembler::Call(Address target,
+                          RelocInfo::Mode rmode,
+                          Condition cond) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  ASSERT(cond == al);
+  Label start;
+  bind(&start);
+
+  // Statement positions are expected to be recorded when the target
+  // address is loaded.
+  positions_recorder()->WriteRecordedPositions();
+
+  // This can likely be optimized to make use of bc() with 24bit relative
+  //
+  // RecordRelocInfo(x.rmode_, x.imm_);
+  // bc( BA, .... offset, LKset);
+  //
+
+  mov(ip, Operand(reinterpret_cast<intptr_t>(target), rmode));
+  mtlr(ip);
+  bclr(BA, SetLK);
+
+#if V8_TARGET_ARCH_PPC64
+  ASSERT(kCallTargetAddressOffset == 7 * kInstrSize);
+#else
+  ASSERT(kCallTargetAddressOffset == 4 * kInstrSize);
+#endif
+  ASSERT_EQ(CallSize(target, rmode, cond), SizeOfCodeGeneratedSince(&start));
+}
+
+
+int MacroAssembler::CallSize(Handle<Code> code,
+                             RelocInfo::Mode rmode,
+                             TypeFeedbackId ast_id,
+                             Condition cond) {
+  return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond);
+}
+
+
+void MacroAssembler::Call(Handle<Code> code,
+                          RelocInfo::Mode rmode,
+                          TypeFeedbackId ast_id,
+                          Condition cond) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  Label start;
+  bind(&start);
+  ASSERT(RelocInfo::IsCodeTarget(rmode));
+  if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
+    SetRecordedAstId(ast_id);
+    rmode = RelocInfo::CODE_TARGET_WITH_ID;
+  }
+  Call(reinterpret_cast<Address>(code.location()), rmode, cond);
+  ASSERT_EQ(CallSize(code, rmode, ast_id, cond),
+            SizeOfCodeGeneratedSince(&start));
+}
+
+
+void MacroAssembler::Ret(Condition cond) {
+  ASSERT(cond == al);
+  blr();
+}
+
+
+void MacroAssembler::Drop(int count, Condition cond) {
+  ASSERT(cond == al);
+  if (count > 0) {
+    Add(sp, sp, count * kPointerSize, r0);
+  }
+}
+
+
+void MacroAssembler::Ret(int drop, Condition cond) {
+  Drop(drop, cond);
+  Ret(cond);
+}
+
+void MacroAssembler::Call(Label* target) {
+  b(target, SetLK);
+}
+
+
+void MacroAssembler::Push(Handle<Object> handle) {
+  mov(ip, Operand(handle));
+  push(ip);
+}
+
+
+void MacroAssembler::Move(Register dst, Handle<Object> value) {
+  mov(dst, Operand(value));
+}
+
+
+void MacroAssembler::Move(Register dst, Register src, Condition cond) {
+  ASSERT(cond == al);
+  if (!dst.is(src)) {
+    mr(dst, src);
+  }
+}
+
+
+void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) {
+  if (!dst.is(src)) {
+    fmr(dst, src);
+  }
+}
+
+
+void MacroAssembler::MultiPush(RegList regs) {
+  int16_t num_to_push = NumberOfBitsSet(regs);
+  int16_t stack_offset = num_to_push * kPointerSize;
+
+  subi(sp, sp, Operand(stack_offset));
+  for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
+    if ((regs & (1 << i)) != 0) {
+      stack_offset -= kPointerSize;
+      StoreP(ToRegister(i), MemOperand(sp, stack_offset));
+    }
+  }
+}
+
+void MacroAssembler::MultiPop(RegList regs) {
+  int16_t stack_offset = 0;
+
+  for (int16_t i = 0; i < kNumRegisters; i++) {
+    if ((regs & (1 << i)) != 0) {
+      LoadP(ToRegister(i), MemOperand(sp, stack_offset));
+      stack_offset += kPointerSize;
+    }
+  }
+  addi(sp, sp, Operand(stack_offset));
+}
+
+
+void MacroAssembler::LoadRoot(Register destination,
+                              Heap::RootListIndex index,
+                              Condition cond) {
+  ASSERT(cond == al);
+  LoadP(destination, MemOperand(kRootRegister,
+                                index << kPointerSizeLog2), r0);
+}
+
+
+void MacroAssembler::StoreRoot(Register source,
+                               Heap::RootListIndex index,
+                               Condition cond) {
+  ASSERT(cond == al);
+  StoreP(source, MemOperand(kRootRegister, index << kPointerSizeLog2), r0);
+}
+
+
+void MacroAssembler::LoadHeapObject(Register result,
+                                    Handle<HeapObject> object) {
+  if (isolate()->heap()->InNewSpace(*object)) {
+    Handle<JSGlobalPropertyCell> cell =
+        isolate()->factory()->NewJSGlobalPropertyCell(object);
+    mov(result, Operand(cell));
+    LoadP(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
+  } else {
+    mov(result, Operand(object));
+  }
+}
+
+
+void MacroAssembler::InNewSpace(Register object,
+                                Register scratch,
+                                Condition cond,
+                                Label* branch) {
+  // N.B. scratch may be same register as object
+  ASSERT(cond == eq || cond == ne);
+  mov(r0, Operand(ExternalReference::new_space_mask(isolate())));
+  and_(scratch, object, r0);
+  mov(r0, Operand(ExternalReference::new_space_start(isolate())));
+  cmp(scratch, r0);
+  b(cond, branch);
+}
+
+
+void MacroAssembler::RecordWriteField(
+    Register object,
+    int offset,
+    Register value,
+    Register dst,
+    LinkRegisterStatus lr_status,
+    SaveFPRegsMode save_fp,
+    RememberedSetAction remembered_set_action,
+    SmiCheck smi_check) {
+  // First, check if a write barrier is even needed. The tests below
+  // catch stores of Smis.
+  Label done;
+
+  // Skip barrier if writing a smi.
+  if (smi_check == INLINE_SMI_CHECK) {
+    JumpIfSmi(value, &done);
+  }
+
+  // Although the object register is tagged, the offset is relative to the start
+  // of the object, so so offset must be a multiple of kPointerSize.
+  ASSERT(IsAligned(offset, kPointerSize));
+
+  addi(dst, object, Operand(offset - kHeapObjectTag));
+  if (emit_debug_code()) {
+    Label ok;
+    andi(r0, dst, Operand((1 << kPointerSizeLog2) - 1));
+    beq(&ok, cr0);
+    stop("Unaligned cell in write barrier");
+    bind(&ok);
+  }
+
+  RecordWrite(object,
+              dst,
+              value,
+              lr_status,
+              save_fp,
+              remembered_set_action,
+              OMIT_SMI_CHECK);
+
+  bind(&done);
+
+  // Clobber clobbered input registers when running with the debug-code flag
+  // turned on to provoke errors.
+  if (emit_debug_code()) {
+    mov(value, Operand(BitCast<intptr_t>(kZapValue + 4)));
+    mov(dst, Operand(BitCast<intptr_t>(kZapValue + 8)));
+  }
+}
+
+
+// Will clobber 4 registers: object, address, scratch, ip.  The
+// register 'object' contains a heap object pointer.  The heap object
+// tag is shifted away.
+void MacroAssembler::RecordWrite(Register object,
+                                 Register address,
+                                 Register value,
+                                 LinkRegisterStatus lr_status,
+                                 SaveFPRegsMode fp_mode,
+                                 RememberedSetAction remembered_set_action,
+                                 SmiCheck smi_check) {
+  // The compiled code assumes that record write doesn't change the
+  // context register, so we check that none of the clobbered
+  // registers are cp.
+  ASSERT(!address.is(cp) && !value.is(cp));
+
+  if (emit_debug_code()) {
+    LoadP(ip, MemOperand(address));
+    cmp(ip, value);
+    Check(eq, "Wrong address or value passed to RecordWrite");
+  }
+
+  Label done;
+
+  if (smi_check == INLINE_SMI_CHECK) {
+    JumpIfSmi(value, &done);
+  }
+
+  CheckPageFlag(value,
+                value,  // Used as scratch.
+                MemoryChunk::kPointersToHereAreInterestingMask,
+                eq,
+                &done);
+  CheckPageFlag(object,
+                value,  // Used as scratch.
+                MemoryChunk::kPointersFromHereAreInterestingMask,
+                eq,
+                &done);
+
+  // Record the actual write.
+  if (lr_status == kLRHasNotBeenSaved) {
+    mflr(r0);
+    push(r0);
+  }
+  RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
+  CallStub(&stub);
+  if (lr_status == kLRHasNotBeenSaved) {
+    pop(r0);
+    mtlr(r0);
+  }
+
+  bind(&done);
+
+  // Clobber clobbered registers when running with the debug-code flag
+  // turned on to provoke errors.
+  if (emit_debug_code()) {
+    mov(address, Operand(BitCast<intptr_t>(kZapValue + 12)));
+    mov(value, Operand(BitCast<intptr_t>(kZapValue + 16)));
+  }
+}
+
+
+void MacroAssembler::RememberedSetHelper(Register object,  // For debug tests.
+                                         Register address,
+                                         Register scratch,
+                                         SaveFPRegsMode fp_mode,
+                                         RememberedSetFinalAction and_then) {
+  Label done;
+  if (emit_debug_code()) {
+    Label ok;
+    JumpIfNotInNewSpace(object, scratch, &ok);
+    stop("Remembered set pointer is in new space");
+    bind(&ok);
+  }
+  // Load store buffer top.
+  ExternalReference store_buffer =
+      ExternalReference::store_buffer_top(isolate());
+  mov(ip, Operand(store_buffer));
+  LoadP(scratch, MemOperand(ip));
+  // Store pointer to buffer and increment buffer top.
+  StoreP(address, MemOperand(scratch));
+  addi(scratch, scratch, Operand(kPointerSize));
+  // Write back new top of buffer.
+  StoreP(scratch, MemOperand(ip));
+  // Call stub on end of buffer.
+  // Check for end of buffer.
+  mov(r0, Operand(StoreBuffer::kStoreBufferOverflowBit));
+  and_(r0, scratch, r0, SetRC);
+
+  if (and_then == kFallThroughAtEnd) {
+    beq(&done, cr0);
+  } else {
+    ASSERT(and_then == kReturnAtEnd);
+    beq(&done, cr0);
+  }
+  mflr(r0);
+  push(r0);
+  StoreBufferOverflowStub store_buffer_overflow =
+      StoreBufferOverflowStub(fp_mode);
+  CallStub(&store_buffer_overflow);
+  pop(r0);
+  mtlr(r0);
+  bind(&done);
+  if (and_then == kReturnAtEnd) {
+    Ret();
+  }
+}
+
+
+// Push and pop all registers that can hold pointers.
+void MacroAssembler::PushSafepointRegisters() {
+  // Safepoints expect a block of kNumSafepointRegisters values on the
+  // stack, so adjust the stack for unsaved registers.
+  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
+  ASSERT(num_unsaved >= 0);
+  if (num_unsaved > 0) {
+    subi(sp, sp, Operand(num_unsaved * kPointerSize));
+  }
+  MultiPush(kSafepointSavedRegisters);
+}
+
+
+void MacroAssembler::PopSafepointRegisters() {
+  const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
+  MultiPop(kSafepointSavedRegisters);
+  if (num_unsaved > 0) {
+    addi(sp, sp, Operand(num_unsaved * kPointerSize));
+  }
+}
+
+
+void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) {
+  StoreP(src, SafepointRegisterSlot(dst));
+}
+
+
+void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
+  LoadP(dst, SafepointRegisterSlot(src));
+}
+
+
+int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
+  // The registers are pushed starting with the highest encoding,
+  // which means that lowest encodings are closest to the stack pointer.
+  RegList regs = kSafepointSavedRegisters;
+  int index = 0;
+
+  ASSERT(reg_code >= 0 && reg_code < kNumRegisters);
+
+  for (int16_t i = 0; i < reg_code; i++) {
+    if ((regs & (1 << i)) != 0) {
+      index++;
+    }
+  }
+
+  return index;
+}
+
+
+MemOperand MacroAssembler::SafepointRegisterSlot(Register reg) {
+  return MemOperand(sp, SafepointRegisterStackIndex(reg.code()) * kPointerSize);
+}
+
+
+MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
+  // General purpose registers are pushed last on the stack.
+  int doubles_size = DwVfpRegister::kNumAllocatableRegisters * kDoubleSize;
+  int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
+  return MemOperand(sp, doubles_size + register_offset);
+}
+
+void MacroAssembler::EnterFrame(StackFrame::Type type) {
+  mflr(r0);
+  push(r0);
+  push(fp);
+  push(cp);
+  LoadSmiLiteral(r0, Smi::FromInt(type));
+  push(r0);
+  mov(r0, Operand(CodeObject()));
+  push(r0);
+  addi(fp, sp, Operand(3 * kPointerSize));  // Adjust FP to point to saved FP
+}
+
+
+void MacroAssembler::LeaveFrame(StackFrame::Type type) {
+  // Drop the execution stack down to the frame pointer and restore
+  // the caller frame pointer and return address.
+  mr(sp, fp);
+  LoadP(fp, MemOperand(sp));
+  LoadP(r0, MemOperand(sp, kPointerSize));
+  mtlr(r0);
+  addi(sp, sp, Operand(2*kPointerSize));
+}
+
+// ExitFrame layout (probably wrongish.. needs updating)
+//
+//  SP -> previousSP
+//        LK reserved
+//        code
+//        sp_on_exit (for debug?)
+// oldSP->prev SP
+//        LK
+//        <parameters on stack>
+
+// Prior to calling EnterExitFrame, we've got a bunch of parameters
+// on the stack that we need to wrap a real frame around.. so first
+// we reserve a slot for LK and push the previous SP which is captured
+// in the fp register (r31)
+// Then - we buy a new frame
+
+void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
+  // Set up the frame structure on the stack.
+  ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement);
+  ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset);
+  ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset);
+  ASSERT(stack_space > 0);
+
+  // This is an opportunity to build a frame to wrap
+  // all of the pushes that have happened inside of V8
+  // since we were called from C code
+
+  // replicate ARM frame - TODO make this more closely follow PPC ABI
+  mflr(r0);
+  Push(r0, fp);
+  mr(fp, sp);
+  // Reserve room for saved entry sp and code object.
+  subi(sp, sp, Operand(2 * kPointerSize));
+
+  if (emit_debug_code()) {
+    li(r8, Operand::Zero());
+    StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
+  }
+  mov(r8, Operand(CodeObject()));
+  StoreP(r8, MemOperand(fp, ExitFrameConstants::kCodeOffset));
+
+  // Save the frame pointer and the context in top.
+  mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
+  StoreP(fp, MemOperand(r8));
+  mov(r8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
+  StoreP(cp, MemOperand(r8));
+
+  // Optionally save all volatile double registers.
+  if (save_doubles) {
+    const int kNumRegs = DwVfpRegister::kNumVolatileRegisters;
+    subi(sp, sp, Operand(kNumRegs * kDoubleSize));
+    for (int i = 0; i < kNumRegs; i++) {
+      DwVfpRegister reg = DwVfpRegister::from_code(i);
+      stfd(reg, MemOperand(sp, i * kDoubleSize));
+    }
+    // Note that d0 will be accessible at
+    //   fp - 2 * kPointerSize - kNumVolatileRegisters * kDoubleSize,
+    // since the sp slot and code slot were pushed after the fp.
+  }
+
+  // Allocate and align the frame preparing for calling the runtime
+  // function.
+  stack_space += kNumRequiredStackFrameSlots;
+  subi(sp, sp, Operand(stack_space * kPointerSize));
+  const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
+  if (frame_alignment > 0) {
+    ASSERT(frame_alignment == 8);
+    ClearRightImm(sp, sp, Operand(3));  // equivalent to &= -8
+  }
+
+  // Set the exit frame sp value to point just before the return address
+  // location.
+  addi(r8, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
+  StoreP(r8, MemOperand(fp, ExitFrameConstants::kSPOffset));
+}
+
+
+void MacroAssembler::InitializeNewString(Register string,
+                                         Register length,
+                                         Heap::RootListIndex map_index,
+                                         Register scratch1,
+                                         Register scratch2) {
+  SmiTag(scratch1, length);
+  LoadRoot(scratch2, map_index);
+  StoreP(scratch1, FieldMemOperand(string, String::kLengthOffset), r0);
+  li(scratch1, Operand(String::kEmptyHashField));
+  StoreP(scratch2, FieldMemOperand(string, HeapObject::kMapOffset), r0);
+  StoreP(scratch1, FieldMemOperand(string, String::kHashFieldSlot), r0);
+}
+
+
+int MacroAssembler::ActivationFrameAlignment() {
+#if !defined(USE_SIMULATOR)
+  // Running on the real platform. Use the alignment as mandated by the local
+  // environment.
+  // Note: This will break if we ever start generating snapshots on one PPC
+  // platform for another PPC platform with a different alignment.
+  return OS::ActivationFrameAlignment();
+#else  // Simulated
+  // If we are using the simulator then we should always align to the expected
+  // alignment. As the simulator is used to generate snapshots we do not know
+  // if the target platform will need alignment, so this is controlled from a
+  // flag.
+  return FLAG_sim_stack_alignment;
+#endif
+}
+
+
+void MacroAssembler::LeaveExitFrame(bool save_doubles,
+                                    Register argument_count) {
+  // Optionally restore all double registers.
+  if (save_doubles) {
+    // Calculate the stack location of the saved doubles and restore them.
+    const int kNumRegs = DwVfpRegister::kNumVolatileRegisters;
+    const int offset = (2 * kPointerSize + kNumRegs * kDoubleSize);
+    addi(r6, fp, Operand(-offset));
+    for (int i = 0; i < kNumRegs; i++) {
+      DwVfpRegister reg = DwVfpRegister::from_code(i);
+      lfd(reg, MemOperand(r6, i * kDoubleSize));
+    }
+  }
+
+  // Clear top frame.
+  li(r6, Operand(0, RelocInfo::NONE));
+  mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
+  StoreP(r6, MemOperand(ip));
+
+  // Restore current context from top and clear it in debug mode.
+  mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
+  LoadP(cp, MemOperand(ip));
+#ifdef DEBUG
+  StoreP(r6, MemOperand(ip));
+#endif
+
+  // Tear down the exit frame, pop the arguments, and return.
+  mr(sp, fp);
+  pop(fp);
+  pop(r0);
+  mtlr(r0);
+
+  if (argument_count.is_valid()) {
+    ShiftLeftImm(argument_count, argument_count, Operand(kPointerSizeLog2));
+    add(sp, sp, argument_count);
+  }
+}
+
+void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
+  fmr(dst, d1);
+}
+
+
+void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
+  // This macro takes the dst register to make the code more readable
+  // at the call sites. However, the dst register has to be r8 to
+  // follow the calling convention which requires the call type to be
+  // in r8.
+  ASSERT(dst.is(r8));
+  if (call_kind == CALL_AS_FUNCTION) {
+    LoadSmiLiteral(dst, Smi::FromInt(1));
+  } else {
+    LoadSmiLiteral(dst, Smi::FromInt(0));
+  }
+}
+
+
+void MacroAssembler::InvokePrologue(const ParameterCount& expected,
+                                    const ParameterCount& actual,
+                                    Handle<Code> code_constant,
+                                    Register code_reg,
+                                    Label* done,
+                                    bool* definitely_mismatches,
+                                    InvokeFlag flag,
+                                    const CallWrapper& call_wrapper,
+                                    CallKind call_kind) {
+  bool definitely_matches = false;
+  *definitely_mismatches = false;
+  Label regular_invoke;
+
+  // Check whether the expected and actual arguments count match. If not,
+  // setup registers according to contract with ArgumentsAdaptorTrampoline:
+  //  r3: actual arguments count
+  //  r4: function (passed through to callee)
+  //  r5: expected arguments count
+  //  r6: callee code entry
+
+  // The code below is made a lot easier because the calling code already sets
+  // up actual and expected registers according to the contract if values are
+  // passed in registers.
+
+  // roohack - remove these 3 checks temporarily
+  //  ASSERT(actual.is_immediate() || actual.reg().is(r3));
+  //  ASSERT(expected.is_immediate() || expected.reg().is(r5));
+  //  ASSERT((!code_constant.is_null() && code_reg.is(no_reg))
+  //          || code_reg.is(r6));
+
+  if (expected.is_immediate()) {
+    ASSERT(actual.is_immediate());
+    if (expected.immediate() == actual.immediate()) {
+      definitely_matches = true;
+    } else {
+      mov(r3, Operand(actual.immediate()));
+      const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
+      if (expected.immediate() == sentinel) {
+        // Don't worry about adapting arguments for builtins that
+        // don't want that done. Skip adaption code by making it look
+        // like we have a match between expected and actual number of
+        // arguments.
+        definitely_matches = true;
+      } else {
+        *definitely_mismatches = true;
+        mov(r5, Operand(expected.immediate()));
+      }
+    }
+  } else {
+    if (actual.is_immediate()) {
+      cmpi(expected.reg(), Operand(actual.immediate()));
+      beq(&regular_invoke);
+      mov(r3, Operand(actual.immediate()));
+    } else {
+      cmp(expected.reg(), actual.reg());
+      beq(&regular_invoke);
+    }
+  }
+
+  if (!definitely_matches) {
+    if (!code_constant.is_null()) {
+      mov(r6, Operand(code_constant));
+      addi(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
+    }
+
+    Handle<Code> adaptor =
+        isolate()->builtins()->ArgumentsAdaptorTrampoline();
+    if (flag == CALL_FUNCTION) {
+      call_wrapper.BeforeCall(CallSize(adaptor));
+      SetCallKind(r8, call_kind);
+      Call(adaptor);
+      call_wrapper.AfterCall();
+      if (!*definitely_mismatches) {
+        b(done);
+      }
+    } else {
+      SetCallKind(r8, call_kind);
+      Jump(adaptor, RelocInfo::CODE_TARGET);
+    }
+    bind(&regular_invoke);
+  }
+}
+
+
+void MacroAssembler::InvokeCode(Register code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                InvokeFlag flag,
+                                const CallWrapper& call_wrapper,
+                                CallKind call_kind) {
+  // You can't call a function without a valid frame.
+  ASSERT(flag == JUMP_FUNCTION || has_frame());
+
+  Label done;
+  bool definitely_mismatches = false;
+  InvokePrologue(expected, actual, Handle<Code>::null(), code,
+                 &done, &definitely_mismatches, flag,
+                 call_wrapper, call_kind);
+  if (!definitely_mismatches) {
+    if (flag == CALL_FUNCTION) {
+      call_wrapper.BeforeCall(CallSize(code));
+      SetCallKind(r8, call_kind);
+      Call(code);
+      call_wrapper.AfterCall();
+    } else {
+      ASSERT(flag == JUMP_FUNCTION);
+      SetCallKind(r8, call_kind);
+      Jump(code);
+    }
+
+    // Continue here if InvokePrologue does handle the invocation due to
+    // mismatched parameter counts.
+    bind(&done);
+  }
+}
+
+
+void MacroAssembler::InvokeCode(Handle<Code> code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                RelocInfo::Mode rmode,
+                                InvokeFlag flag,
+                                CallKind call_kind) {
+  // You can't call a function without a valid frame.
+  ASSERT(flag == JUMP_FUNCTION || has_frame());
+
+  Label done;
+  bool definitely_mismatches = false;
+  InvokePrologue(expected, actual, code, no_reg,
+                 &done, &definitely_mismatches, flag,
+                 NullCallWrapper(), call_kind);
+  if (!definitely_mismatches) {
+    if (flag == CALL_FUNCTION) {
+      SetCallKind(r8, call_kind);
+      Call(code, rmode);
+    } else {
+      SetCallKind(r8, call_kind);
+      Jump(code, rmode);
+    }
+
+    // Continue here if InvokePrologue does handle the invocation due to
+    // mismatched parameter counts.
+    bind(&done);
+  }
+}
+
+
+void MacroAssembler::InvokeFunction(Register fun,
+                                    const ParameterCount& actual,
+                                    InvokeFlag flag,
+                                    const CallWrapper& call_wrapper,
+                                    CallKind call_kind) {
+  // You can't call a function without a valid frame.
+  ASSERT(flag == JUMP_FUNCTION || has_frame());
+
+  // Contract with called JS functions requires that function is passed in r4.
+  ASSERT(fun.is(r4));
+
+  Register expected_reg = r5;
+  Register code_reg = r6;
+
+  LoadP(code_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+  LoadWordArith(expected_reg,
+      FieldMemOperand(code_reg,
+                      SharedFunctionInfo::kFormalParameterCountOffset));
+#if !defined(V8_TARGET_ARCH_PPC64)
+  SmiUntag(expected_reg);
+#endif
+  LoadP(code_reg,
+        FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
+
+  ParameterCount expected(expected_reg);
+  InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind);
+}
+
+
+void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
+                                    const ParameterCount& actual,
+                                    InvokeFlag flag,
+                                    const CallWrapper& call_wrapper,
+                                    CallKind call_kind) {
+  // You can't call a function without a valid frame.
+  ASSERT(flag == JUMP_FUNCTION || has_frame());
+
+  // Get the function and setup the context.
+  LoadHeapObject(r4, function);
+  LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  // We call indirectly through the code field in the function to
+  // allow recompilation to take effect without changing any of the
+  // call sites.
+  LoadP(r6, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
+  InvokeCode(r6, expected, actual, flag, call_wrapper, call_kind);
+}
+
+
+void MacroAssembler::IsObjectJSObjectType(Register heap_object,
+                                          Register map,
+                                          Register scratch,
+                                          Label* fail) {
+  LoadP(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
+  IsInstanceJSObjectType(map, scratch, fail);
+}
+
+
+void MacroAssembler::IsInstanceJSObjectType(Register map,
+                                            Register scratch,
+                                            Label* fail) {
+  lbz(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  cmpi(scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+  blt(fail);
+  cmpi(scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
+  bgt(fail);
+}
+
+
+void MacroAssembler::IsObjectJSStringType(Register object,
+                                          Register scratch,
+                                          Label* fail) {
+  ASSERT(kNotStringTag != 0);
+
+  LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+  lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  andi(r0, scratch, Operand(kIsNotStringMask));
+  bne(fail, cr0);
+}
+
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+void MacroAssembler::DebugBreak() {
+  li(r3, Operand(0, RelocInfo::NONE));
+  mov(r4, Operand(ExternalReference(Runtime::kDebugBreak, isolate())));
+  CEntryStub ces(1);
+  ASSERT(AllowThisStubCall(&ces));
+  Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
+}
+#endif
+
+
+void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
+                                    int handler_index) {
+  // Adjust this code if not the case.
+  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kStateSlot == 2 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
+
+  // For the JSEntry handler, we must preserve r1-r7, r0,r8-r15 are available.
+  // We want the stack to look like
+  // sp -> NextOffset
+  //       CodeObject
+  //       state
+  //       context
+  //       frame pointer
+
+  // Link the current handler as the next handler.
+  mov(r8, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
+  LoadP(r0, MemOperand(r8));
+  StorePU(r0, MemOperand(sp, -StackHandlerConstants::kSize));
+  // Set this new handler as the current one.
+  StoreP(sp, MemOperand(r8));
+
+  if (kind == StackHandler::JS_ENTRY) {
+    li(r8, Operand(0, RelocInfo::NONE));  // NULL frame pointer.
+    StoreP(r8, MemOperand(sp, StackHandlerConstants::kFPOffset));
+    LoadSmiLiteral(r8, Smi::FromInt(0));    // Indicates no context.
+    StoreP(r8, MemOperand(sp, StackHandlerConstants::kContextOffset));
+  } else {
+    // still not sure if fp is right
+    StoreP(fp, MemOperand(sp, StackHandlerConstants::kFPOffset));
+    StoreP(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
+  }
+  unsigned state =
+      StackHandler::IndexField::encode(handler_index) |
+      StackHandler::KindField::encode(kind);
+  LoadIntLiteral(r8, state);
+  StoreP(r8, MemOperand(sp, StackHandlerConstants::kStateSlot));
+  mov(r8, Operand(CodeObject()));
+  StoreP(r8, MemOperand(sp, StackHandlerConstants::kCodeOffset));
+}
+
+
+void MacroAssembler::PopTryHandler() {
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
+  pop(r4);
+  mov(ip, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
+  addi(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+  StoreP(r4, MemOperand(ip));
+}
+
+// PPC - make use of ip as a temporary register
+void MacroAssembler::JumpToHandlerEntry() {
+  // Compute the handler entry address and jump to it.  The handler table is
+  // a fixed array of (smi-tagged) code offsets.
+  // r3 = exception, r4 = code object, r5 = state.
+  LoadP(r6, FieldMemOperand(r4, Code::kHandlerTableOffset));  // Handler table.
+  addi(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  srwi(r5, r5, Operand(StackHandler::kKindWidth));  // Handler index.
+  slwi(ip, r5, Operand(kPointerSizeLog2));
+  add(ip, r6, ip);
+  LoadP(r5, MemOperand(ip));  // Smi-tagged offset.
+  addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start.
+  SmiUntag(ip, r5);
+  add(r0, r4, ip);
+  mtctr(r0);
+  bcr();
+}
+
+
+void MacroAssembler::Throw(Register value) {
+  // Adjust this code if not the case.
+  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
+  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kStateSlot == 2 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
+  Label skip;
+
+  // The exception is expected in r3.
+  if (!value.is(r3)) {
+    mr(r3, value);
+  }
+  // Drop the stack pointer to the top of the top handler.
+  mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
+  LoadP(sp, MemOperand(r6));
+  // Restore the next handler.
+  pop(r5);
+  StoreP(r5, MemOperand(r6));
+
+  // Get the code object (r4) and state (r5).  Restore the context and frame
+  // pointer.
+  pop(r4);
+  pop(r5);
+  pop(cp);
+  pop(fp);
+
+  // If the handler is a JS frame, restore the context to the frame.
+  // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
+  // or cp.
+  cmpi(cp, Operand::Zero());
+  beq(&skip);
+  StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  bind(&skip);
+
+  JumpToHandlerEntry();
+}
+
+
+void MacroAssembler::ThrowUncatchable(Register value) {
+  // Adjust this code if not the case.
+  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kStateSlot == 2 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
+
+  // The exception is expected in r3.
+  if (!value.is(r3)) {
+    mr(r3, value);
+  }
+  // Drop the stack pointer to the top of the top stack handler.
+  mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
+  LoadP(sp, MemOperand(r6));
+
+  // Unwind the handlers until the ENTRY handler is found.
+  Label fetch_next, check_kind;
+  b(&check_kind);
+  bind(&fetch_next);
+  LoadP(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
+
+  bind(&check_kind);
+  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
+  LoadP(r5, MemOperand(sp, StackHandlerConstants::kStateSlot));
+  andi(r0, r5, Operand(StackHandler::KindField::kMask));
+  bne(&fetch_next, cr0);
+
+  // Set the top handler address to next handler past the top ENTRY handler.
+  pop(r5);
+  StoreP(r5, MemOperand(r6));
+  // Get the code object (r4) and state (r5).  Clear the context and frame
+  // pointer (0 was saved in the handler).
+  pop(r4);
+  pop(r5);
+  pop(cp);
+  pop(fp);
+
+  JumpToHandlerEntry();
+}
+
+
+void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
+                                            Register scratch,
+                                            Label* miss) {
+  Label same_contexts;
+
+  ASSERT(!holder_reg.is(scratch));
+  ASSERT(!holder_reg.is(ip));
+  ASSERT(!scratch.is(ip));
+
+  // Load current lexical context from the stack frame.
+  LoadP(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  // In debug mode, make sure the lexical context is set.
+#ifdef DEBUG
+  cmpi(scratch, Operand(0, RelocInfo::NONE));
+  Check(ne, "we should not have an empty lexical context");
+#endif
+
+  // Load the native context of the current context.
+  int offset =
+      Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
+  LoadP(scratch, FieldMemOperand(scratch, offset));
+  LoadP(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
+
+  // Check the context is a native context.
+  if (emit_debug_code()) {
+    // TODO(119): avoid push(holder_reg)/pop(holder_reg)
+    // Cannot use ip as a temporary in this verification code. Due to the fact
+    // that ip is clobbered as part of cmp with an object Operand.
+    push(holder_reg);  // Temporarily save holder on the stack.
+    // Read the first word and compare to the native_context_map.
+    LoadP(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
+    LoadRoot(ip, Heap::kNativeContextMapRootIndex);
+    cmp(holder_reg, ip);
+    Check(eq, "JSGlobalObject::native_context should be a native context.");
+    pop(holder_reg);  // Restore holder.
+  }
+
+  // Check if both contexts are the same.
+  LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
+  cmp(scratch, ip);
+  beq(&same_contexts);
+
+  // Check the context is a native context.
+  if (emit_debug_code()) {
+    // TODO(119): avoid push(holder_reg)/pop(holder_reg)
+    // Cannot use ip as a temporary in this verification code. Due to the fact
+    // that ip is clobbered as part of cmp with an object Operand.
+    push(holder_reg);  // Temporarily save holder on the stack.
+    mr(holder_reg, ip);  // Move ip to its holding place.
+    LoadRoot(ip, Heap::kNullValueRootIndex);
+    cmp(holder_reg, ip);
+    Check(ne, "JSGlobalProxy::context() should not be null.");
+
+    LoadP(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
+    LoadRoot(ip, Heap::kNativeContextMapRootIndex);
+    cmp(holder_reg, ip);
+    Check(eq, "JSGlobalObject::native_context should be a native context.");
+    // Restore ip is not needed. ip is reloaded below.
+    pop(holder_reg);  // Restore holder.
+    // Restore ip to holder's context.
+    LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
+  }
+
+  // Check that the security token in the calling global object is
+  // compatible with the security token in the receiving global
+  // object.
+  int token_offset = Context::kHeaderSize +
+                     Context::SECURITY_TOKEN_INDEX * kPointerSize;
+
+  LoadP(scratch, FieldMemOperand(scratch, token_offset));
+  LoadP(ip, FieldMemOperand(ip, token_offset));
+  cmp(scratch, ip);
+  bne(miss);
+
+  bind(&same_contexts);
+}
+
+
+void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
+  // First of all we assign the hash seed to scratch.
+  LoadRoot(scratch, Heap::kHashSeedRootIndex);
+  SmiUntag(scratch);
+
+  // Xor original key with a seed.
+  xor_(t0, t0, scratch);
+
+  // Compute the hash code from the untagged key.  This must be kept in sync
+  // with ComputeIntegerHash in utils.h.
+  //
+  // hash = ~hash + (hash << 15);
+  notx(scratch, t0);
+  slwi(t0, t0, Operand(15));
+  add(t0, scratch, t0);
+  // hash = hash ^ (hash >> 12);
+  srwi(scratch, t0, Operand(12));
+  xor_(t0, t0, scratch);
+  // hash = hash + (hash << 2);
+  slwi(scratch, t0, Operand(2));
+  add(t0, t0, scratch);
+  // hash = hash ^ (hash >> 4);
+  srwi(scratch, t0, Operand(4));
+  xor_(t0, t0, scratch);
+  // hash = hash * 2057;
+  mr(r0, t0);
+  slwi(scratch, t0, Operand(3));
+  add(t0, t0, scratch);
+  slwi(scratch, r0, Operand(11));
+  add(t0, t0, scratch);
+  // hash = hash ^ (hash >> 16);
+  srwi(scratch, t0, Operand(16));
+  xor_(t0, t0, scratch);
+}
+
+
+void MacroAssembler::LoadFromNumberDictionary(Label* miss,
+                                              Register elements,
+                                              Register key,
+                                              Register result,
+                                              Register t0,
+                                              Register t1,
+                                              Register t2) {
+  // Register use:
+  //
+  // elements - holds the slow-case elements of the receiver on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // key      - holds the smi key on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // result   - holds the result on exit if the load succeeded.
+  //            Allowed to be the same as 'key' or 'result'.
+  //            Unchanged on bailout so 'key' or 'result' can be used
+  //            in further computation.
+  //
+  // Scratch registers:
+  //
+  // t0 - holds the untagged key on entry and holds the hash once computed.
+  //
+  // t1 - used to hold the capacity mask of the dictionary
+  //
+  // t2 - used for the index into the dictionary.
+  Label done;
+
+  GetNumberHash(t0, t1);
+
+  // Compute the capacity mask.
+  LoadP(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
+  SmiUntag(t1);
+  subi(t1, t1, Operand(1));
+
+  // Generate an unrolled loop that performs a few probes before giving up.
+  static const int kProbes = 4;
+  for (int i = 0; i < kProbes; i++) {
+    // Use t2 for index calculations and keep the hash intact in t0.
+    mr(t2, t0);
+    // Compute the masked index: (hash + i + i * i) & mask.
+    if (i > 0) {
+      addi(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
+    }
+    and_(t2, t2, t1);
+
+    // Scale the index by multiplying by the element size.
+    ASSERT(SeededNumberDictionary::kEntrySize == 3);
+    slwi(ip, t2, Operand(1));
+    add(t2, t2, ip);  // t2 = t2 * 3
+
+    // Check if the key is identical to the name.
+    slwi(t2, t2, Operand(kPointerSizeLog2));
+    add(t2, elements, t2);
+    LoadP(ip,
+          FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset));
+    cmp(key, ip);
+    if (i != kProbes - 1) {
+      beq(&done);
+    } else {
+      bne(miss);
+    }
+  }
+
+  bind(&done);
+  // Check that the value is a normal property.
+  // t2: elements + (index * kPointerSize)
+  const int kDetailsOffset =
+      SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
+  LoadP(t1, FieldMemOperand(t2, kDetailsOffset));
+  LoadSmiLiteral(ip, Smi::FromInt(PropertyDetails::TypeField::kMask));
+  and_(r0, t1, ip, SetRC);
+  bne(miss, cr0);
+
+  // Get the value at the masked, scaled index and return.
+  const int kValueOffset =
+      SeededNumberDictionary::kElementsStartOffset + kPointerSize;
+  LoadP(result, FieldMemOperand(t2, kValueOffset));
+}
+
+
+void MacroAssembler::AllocateInNewSpace(int object_size,
+                                        Register result,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Label* gc_required,
+                                        AllocationFlags flags) {
+  if (!FLAG_inline_new) {
+    if (emit_debug_code()) {
+      // Trash the registers to simulate an allocation failure.
+      li(result, Operand(0x7091));
+      li(scratch1, Operand(0x7191));
+      li(scratch2, Operand(0x7291));
+    }
+    b(gc_required);
+    return;
+  }
+
+  ASSERT(!result.is(scratch1));
+  ASSERT(!result.is(scratch2));
+  ASSERT(!scratch1.is(scratch2));
+  ASSERT(!scratch1.is(ip));
+  ASSERT(!scratch2.is(ip));
+
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
+  }
+  ASSERT_EQ(0, static_cast<int>(object_size & kObjectAlignmentMask));
+
+  // Check relative positions of allocation top and limit addresses.
+  // The values must be adjacent in memory to allow the use of LDM.
+  // Also, assert that the registers are numbered such that the values
+  // are loaded in the correct order.
+  ExternalReference new_space_allocation_top =
+      ExternalReference::new_space_allocation_top_address(isolate());
+  ExternalReference new_space_allocation_limit =
+      ExternalReference::new_space_allocation_limit_address(isolate());
+  intptr_t top   =
+      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+  intptr_t limit =
+      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+  ASSERT((limit - top) == kPointerSize);
+  ASSERT(result.code() < ip.code());
+
+  // Set up allocation top address and object size registers.
+  Register topaddr = scratch1;
+  Register obj_size_reg = scratch2;
+  mov(topaddr, Operand(new_space_allocation_top));
+  // this won't work for very large object on PowerPC
+  li(obj_size_reg, Operand(object_size));
+
+  // This code stores a temporary value in ip. This is OK, as the code below
+  // does not need ip for implicit literal generation.
+  if ((flags & RESULT_CONTAINS_TOP) == 0) {
+    // Load allocation top into result and allocation limit into ip.
+    LoadP(result, MemOperand(topaddr));
+    LoadP(ip, MemOperand(topaddr, kPointerSize));
+  } else {
+    if (emit_debug_code()) {
+      // Assert that result actually contains top on entry. ip is used
+      // immediately below so this use of ip does not cause difference with
+      // respect to register content between debug and release mode.
+      LoadP(ip, MemOperand(topaddr));
+      cmp(result, ip);
+      Check(eq, "Unexpected allocation top");
+    }
+    // Load allocation limit into ip. Result already contains allocation top.
+    LoadP(ip, MemOperand(topaddr, limit - top), r0);
+  }
+
+  // Calculate new top and bail out if new space is exhausted. Use result
+  // to calculate the new top.
+  li(r0, Operand(-1));
+  addc(scratch2, result, obj_size_reg);
+  addze(r0, r0, LeaveOE, SetRC);
+  beq(gc_required, cr0);
+  cmpl(scratch2, ip);
+  bgt(gc_required);
+  StoreP(scratch2, MemOperand(topaddr));
+
+  // Tag object if requested.
+  if ((flags & TAG_OBJECT) != 0) {
+    addi(result, result, Operand(kHeapObjectTag));
+  }
+}
+
+
+void MacroAssembler::AllocateInNewSpace(Register object_size,
+                                        Register result,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Label* gc_required,
+                                        AllocationFlags flags) {
+  if (!FLAG_inline_new) {
+    if (emit_debug_code()) {
+      // Trash the registers to simulate an allocation failure.
+      li(result, Operand(0x7091));
+      li(scratch1, Operand(0x7191));
+      li(scratch2, Operand(0x7291));
+    }
+    b(gc_required);
+    return;
+  }
+
+  // Assert that the register arguments are different and that none of
+  // them are ip. ip is used explicitly in the code generated below.
+  ASSERT(!result.is(scratch1));
+  ASSERT(!result.is(scratch2));
+  ASSERT(!scratch1.is(scratch2));
+  ASSERT(!object_size.is(ip));
+  ASSERT(!result.is(ip));
+  ASSERT(!scratch1.is(ip));
+  ASSERT(!scratch2.is(ip));
+
+  // Check relative positions of allocation top and limit addresses.
+  // The values must be adjacent in memory to allow the use of LDM.
+  // Also, assert that the registers are numbered such that the values
+  // are loaded in the correct order.
+  ExternalReference new_space_allocation_top =
+      ExternalReference::new_space_allocation_top_address(isolate());
+  ExternalReference new_space_allocation_limit =
+      ExternalReference::new_space_allocation_limit_address(isolate());
+  intptr_t top =
+      reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+  intptr_t limit =
+      reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+  ASSERT((limit - top) == kPointerSize);
+  ASSERT(result.code() < ip.code());
+
+  // Set up allocation top address.
+  Register topaddr = scratch1;
+  mov(topaddr, Operand(new_space_allocation_top));
+
+  // This code stores a temporary value in ip. This is OK, as the code below
+  // does not need ip for implicit literal generation.
+  if ((flags & RESULT_CONTAINS_TOP) == 0) {
+    // Load allocation top into result and allocation limit into ip.
+    LoadP(result, MemOperand(topaddr));
+    LoadP(ip, MemOperand(topaddr, kPointerSize));
+  } else {
+    if (emit_debug_code()) {
+      // Assert that result actually contains top on entry. ip is used
+      // immediately below so this use of ip does not cause difference with
+      // respect to register content between debug and release mode.
+      LoadP(ip, MemOperand(topaddr));
+      cmp(result, ip);
+      Check(eq, "Unexpected allocation top");
+    }
+    // Load allocation limit into ip. Result already contains allocation top.
+    LoadP(ip, MemOperand(topaddr, limit - top));
+  }
+
+  // Calculate new top and bail out if new space is exhausted. Use result
+  // to calculate the new top. Object size may be in words so a shift is
+  // required to get the number of bytes.
+  li(r0, Operand(-1));
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    ShiftLeftImm(scratch2, object_size, Operand(kPointerSizeLog2));
+    addc(scratch2, result, scratch2);
+  } else {
+    addc(scratch2, result, object_size);
+  }
+  addze(r0, r0, LeaveOE, SetRC);
+  beq(gc_required, cr0);
+  cmpl(scratch2, ip);
+  bgt(gc_required);
+
+  // Update allocation top. result temporarily holds the new top.
+  if (emit_debug_code()) {
+    andi(r0, scratch2, Operand(kObjectAlignmentMask));
+    Check(eq, "Unaligned allocation in new space", cr0);
+  }
+  StoreP(scratch2, MemOperand(topaddr));
+
+  // Tag object if requested.
+  if ((flags & TAG_OBJECT) != 0) {
+    addi(result, result, Operand(kHeapObjectTag));
+  }
+}
+
+
+void MacroAssembler::UndoAllocationInNewSpace(Register object,
+                                              Register scratch) {
+  ExternalReference new_space_allocation_top =
+      ExternalReference::new_space_allocation_top_address(isolate());
+
+  // Make sure the object has no tag before resetting top.
+  mov(r0, Operand(~kHeapObjectTagMask));
+  and_(object, object, r0);
+  // was.. and_(object, object, Operand(~kHeapObjectTagMask));
+#ifdef DEBUG
+  // Check that the object un-allocated is below the current top.
+  mov(scratch, Operand(new_space_allocation_top));
+  LoadP(scratch, MemOperand(scratch));
+  cmp(object, scratch);
+  Check(lt, "Undo allocation of non allocated memory");
+#endif
+  // Write the address of the object to un-allocate as the current top.
+  mov(scratch, Operand(new_space_allocation_top));
+  StoreP(object, MemOperand(scratch));
+}
+
+
+void MacroAssembler::AllocateTwoByteString(Register result,
+                                           Register length,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Register scratch3,
+                                           Label* gc_required) {
+  // Calculate the number of bytes needed for the characters in the string while
+  // observing object alignment.
+  ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
+  slwi(scratch1, length, Operand(1));  // Length in bytes, not chars.
+  addi(scratch1, scratch1,
+       Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize));
+  mov(r0, Operand(~kObjectAlignmentMask));
+  and_(scratch1, scratch1, r0);
+
+  // Allocate two-byte string in new space.
+  AllocateInNewSpace(scratch1,
+                     result,
+                     scratch2,
+                     scratch3,
+                     gc_required,
+                     TAG_OBJECT);
+
+  // Set the map, length and hash field.
+  InitializeNewString(result,
+                      length,
+                      Heap::kStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateAsciiString(Register result,
+                                         Register length,
+                                         Register scratch1,
+                                         Register scratch2,
+                                         Register scratch3,
+                                         Label* gc_required) {
+  // Calculate the number of bytes needed for the characters in the string while
+  // observing object alignment.
+  ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
+  ASSERT(kCharSize == 1);
+  addi(scratch1, length,
+       Operand(kObjectAlignmentMask + SeqAsciiString::kHeaderSize));
+  li(r0, Operand(~kObjectAlignmentMask));
+  and_(scratch1, scratch1, r0);
+
+  // Allocate ASCII string in new space.
+  AllocateInNewSpace(scratch1,
+                     result,
+                     scratch2,
+                     scratch3,
+                     gc_required,
+                     TAG_OBJECT);
+
+  // Set the map, length and hash field.
+  InitializeNewString(result,
+                      length,
+                      Heap::kAsciiStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateTwoByteConsString(Register result,
+                                               Register length,
+                                               Register scratch1,
+                                               Register scratch2,
+                                               Label* gc_required) {
+  AllocateInNewSpace(ConsString::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     gc_required,
+                     TAG_OBJECT);
+
+  InitializeNewString(result,
+                      length,
+                      Heap::kConsStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateAsciiConsString(Register result,
+                                             Register length,
+                                             Register scratch1,
+                                             Register scratch2,
+                                             Label* gc_required) {
+  AllocateInNewSpace(ConsString::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     gc_required,
+                     TAG_OBJECT);
+
+  InitializeNewString(result,
+                      length,
+                      Heap::kConsAsciiStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateTwoByteSlicedString(Register result,
+                                                 Register length,
+                                                 Register scratch1,
+                                                 Register scratch2,
+                                                 Label* gc_required) {
+  AllocateInNewSpace(SlicedString::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     gc_required,
+                     TAG_OBJECT);
+
+  InitializeNewString(result,
+                      length,
+                      Heap::kSlicedStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::AllocateAsciiSlicedString(Register result,
+                                               Register length,
+                                               Register scratch1,
+                                               Register scratch2,
+                                               Label* gc_required) {
+  AllocateInNewSpace(SlicedString::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     gc_required,
+                     TAG_OBJECT);
+
+  InitializeNewString(result,
+                      length,
+                      Heap::kSlicedAsciiStringMapRootIndex,
+                      scratch1,
+                      scratch2);
+}
+
+
+void MacroAssembler::CompareObjectType(Register object,
+                                       Register map,
+                                       Register type_reg,
+                                       InstanceType type) {
+  LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
+  CompareInstanceType(map, type_reg, type);
+}
+
+
+void MacroAssembler::CompareInstanceType(Register map,
+                                         Register type_reg,
+                                         InstanceType type) {
+  lbz(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  cmpi(type_reg, Operand(type));
+}
+
+
+void MacroAssembler::CompareRoot(Register obj,
+                                 Heap::RootListIndex index) {
+  ASSERT(!obj.is(ip));
+  LoadRoot(ip, index);
+  cmp(obj, ip);
+}
+
+
+void MacroAssembler::CheckFastElements(Register map,
+                                       Register scratch,
+                                       Label* fail) {
+  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
+  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
+  STATIC_ASSERT(FAST_ELEMENTS == 2);
+  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
+  lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
+  STATIC_ASSERT(Map::kMaximumBitField2FastHoleyElementValue < 0x8000);
+  cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue));
+  bgt(fail);
+}
+
+
+void MacroAssembler::CheckFastObjectElements(Register map,
+                                             Register scratch,
+                                             Label* fail) {
+  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
+  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
+  STATIC_ASSERT(FAST_ELEMENTS == 2);
+  STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
+  lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
+  cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
+  ble(fail);
+  cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue));
+  bgt(fail);
+}
+
+
+void MacroAssembler::CheckFastSmiElements(Register map,
+                                          Register scratch,
+                                          Label* fail) {
+  STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
+  STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
+  lbz(scratch, FieldMemOperand(map, Map::kBitField2Offset));
+  cmpli(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue));
+  bgt(fail);
+}
+
+
+void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
+                                                 Register key_reg,
+                                                 Register receiver_reg,
+                                                 Register elements_reg,
+                                                 Register scratch1,
+                                                 Register scratch2,
+                                                 Register scratch3,
+                                                 Register scratch4,
+                                                 Label* fail) {
+  Label smi_value, maybe_nan, have_double_value, is_nan, done;
+#if V8_TARGET_ARCH_PPC64
+  Register double_reg = scratch2;
+#else
+  Register mantissa_reg = scratch2;
+  Register exponent_reg = scratch3;
+#endif
+
+  // Handle smi values specially.
+  JumpIfSmi(value_reg, &smi_value);
+
+  // Ensure that the object is a heap number
+  CheckMap(value_reg,
+           scratch1,
+           isolate()->factory()->heap_number_map(),
+           fail,
+           DONT_DO_SMI_CHECK);
+
+  // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
+  // in the exponent.
+#if V8_TARGET_ARCH_PPC64
+  mov(scratch1, Operand(kLastNonNaNInt64));
+  addi(scratch3, value_reg, Operand(-kHeapObjectTag));
+  ld(double_reg, MemOperand(scratch3, HeapNumber::kValueOffset));
+  cmp(double_reg, scratch1);
+#else
+  mov(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32));
+  lwz(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
+  cmp(exponent_reg, scratch1);
+#endif
+  bge(&maybe_nan);
+
+#if !V8_TARGET_ARCH_PPC64
+  lwz(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+#endif
+
+  bind(&have_double_value);
+  SmiToDoubleArrayOffset(scratch1, key_reg);
+  add(scratch1, elements_reg, scratch1);
+#if V8_TARGET_ARCH_PPC64
+  addi(scratch1, scratch1, Operand(-kHeapObjectTag));
+  std(double_reg, MemOperand(scratch1, FixedDoubleArray::kHeaderSize));
+#else
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  stw(mantissa_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize));
+  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+  stw(exponent_reg, FieldMemOperand(scratch1, offset));
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  stw(exponent_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize));
+  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+  stw(mantissa_reg, FieldMemOperand(scratch1, offset));
+#endif
+#endif
+  b(&done);
+
+  bind(&maybe_nan);
+  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+  // it's an Infinity, and the non-NaN code path applies.
+  bgt(&is_nan);
+#if V8_TARGET_ARCH_PPC64
+  clrldi(r0, double_reg, Operand(32), SetRC);
+  beq(&have_double_value, cr0);
+#else
+  lwz(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+  cmpi(mantissa_reg, Operand::Zero());
+  beq(&have_double_value);
+#endif
+  bind(&is_nan);
+  // Load canonical NaN for storing into the double array.
+  uint64_t nan_int64 = BitCast<uint64_t>(
+      FixedDoubleArray::canonical_not_the_hole_nan_as_double());
+#if V8_TARGET_ARCH_PPC64
+  mov(double_reg, Operand(nan_int64));
+#else
+  mov(mantissa_reg, Operand(static_cast<intptr_t>(nan_int64)));
+  mov(exponent_reg, Operand(static_cast<intptr_t>(nan_int64 >> 32)));
+#endif
+  b(&have_double_value);
+
+  bind(&smi_value);
+  addi(scratch1, elements_reg,
+       Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+  SmiToDoubleArrayOffset(scratch4, key_reg);
+  add(scratch1, scratch1, scratch4);
+  // scratch1 is now effective address of the double element
+
+  Register untagged_value = elements_reg;
+  SmiUntag(untagged_value, value_reg);
+  FloatingPointHelper::ConvertIntToDouble(this,
+                                          untagged_value,
+                                          d0);
+  stfd(d0, MemOperand(scratch1, 0));
+
+  bind(&done);
+}
+
+
+void MacroAssembler::AddAndCheckForOverflow(Register dst,
+                                            Register left,
+                                            Register right,
+                                            Register overflow_dst,
+                                            Register scratch) {
+  ASSERT(!dst.is(overflow_dst));
+  ASSERT(!dst.is(scratch));
+  ASSERT(!overflow_dst.is(scratch));
+  ASSERT(!overflow_dst.is(left));
+  ASSERT(!overflow_dst.is(right));
+
+  // C = A+B; C overflows if A/B have same sign and C has diff sign than A
+  if (dst.is(left)) {
+    mr(scratch, left);            // Preserve left.
+    add(dst, left, right);        // Left is overwritten.
+    xor_(scratch, dst, scratch);  // Original left.
+    xor_(overflow_dst, dst, right);
+    and_(overflow_dst, overflow_dst, scratch, SetRC);
+  } else if (dst.is(right)) {
+    mr(scratch, right);           // Preserve right.
+    add(dst, left, right);        // Right is overwritten.
+    xor_(scratch, dst, scratch);  // Original right.
+    xor_(overflow_dst, dst, left);
+    and_(overflow_dst, overflow_dst, scratch, SetRC);
+  } else {
+    add(dst, left, right);
+    xor_(overflow_dst, dst, left);
+    xor_(scratch, dst, right);
+    and_(overflow_dst, scratch, overflow_dst, SetRC);
+  }
+}
+
+void MacroAssembler::SubAndCheckForOverflow(Register dst,
+                                            Register left,
+                                            Register right,
+                                            Register overflow_dst,
+                                            Register scratch) {
+  ASSERT(!dst.is(overflow_dst));
+  ASSERT(!dst.is(scratch));
+  ASSERT(!overflow_dst.is(scratch));
+  ASSERT(!overflow_dst.is(left));
+  ASSERT(!overflow_dst.is(right));
+
+  // C = A-B; C overflows if A/B have diff signs and C has diff sign than A
+  if (dst.is(left)) {
+    mr(scratch, left);            // Preserve left.
+    sub(dst, left, right);        // Left is overwritten.
+    xor_(overflow_dst, dst, scratch);
+    xor_(scratch, scratch, right);
+    and_(overflow_dst, overflow_dst, scratch, SetRC);
+  } else if (dst.is(right)) {
+    mr(scratch, right);           // Preserve right.
+    sub(dst, left, right);        // Right is overwritten.
+    xor_(overflow_dst, dst, left);
+    xor_(scratch, left, scratch);
+    and_(overflow_dst, overflow_dst, scratch, SetRC);
+  } else {
+    sub(dst, left, right);
+    xor_(overflow_dst, dst, left);
+    xor_(scratch, left, right);
+    and_(overflow_dst, scratch, overflow_dst, SetRC);
+  }
+}
+
+
+void MacroAssembler::CompareMap(Register obj,
+                                Register scratch,
+                                Handle<Map> map,
+                                Label* early_success,
+                                CompareMapMode mode) {
+  LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
+  CompareMap(scratch, map, early_success, mode);
+}
+
+
+void MacroAssembler::CompareMap(Register obj_map,
+                                Handle<Map> map,
+                                Label* early_success,
+                                CompareMapMode mode) {
+  mov(r0, Operand(map));
+  cmp(obj_map, r0);
+  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
+    ElementsKind kind = map->elements_kind();
+    if (IsFastElementsKind(kind)) {
+      bool packed = IsFastPackedElementsKind(kind);
+      Map* current_map = *map;
+      while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
+        kind = GetNextMoreGeneralFastElementsKind(kind, packed);
+        current_map = current_map->LookupElementsTransitionMap(kind);
+        if (!current_map) break;
+        beq(early_success);
+        mov(r0, Operand(Handle<Map>(current_map)));
+        cmp(obj_map, r0);
+      }
+    }
+  }
+}
+
+
+void MacroAssembler::CheckMap(Register obj,
+                              Register scratch,
+                              Handle<Map> map,
+                              Label* fail,
+                              SmiCheckType smi_check_type,
+                              CompareMapMode mode) {
+  if (smi_check_type == DO_SMI_CHECK) {
+    JumpIfSmi(obj, fail);
+  }
+
+  Label success;
+  CompareMap(obj, scratch, map, &success, mode);
+  bne(fail);
+  bind(&success);
+}
+
+
+void MacroAssembler::CheckMap(Register obj,
+                              Register scratch,
+                              Heap::RootListIndex index,
+                              Label* fail,
+                              SmiCheckType smi_check_type) {
+  if (smi_check_type == DO_SMI_CHECK) {
+    JumpIfSmi(obj, fail);
+  }
+  LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
+  LoadRoot(ip, index);
+  cmp(scratch, ip);
+  bne(fail);
+}
+
+
+void MacroAssembler::DispatchMap(Register obj,
+                                 Register scratch,
+                                 Handle<Map> map,
+                                 Handle<Code> success,
+                                 SmiCheckType smi_check_type) {
+  Label fail;
+  if (smi_check_type == DO_SMI_CHECK) {
+    JumpIfSmi(obj, &fail);
+  }
+  LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
+  mov(ip, Operand(map));
+  cmp(scratch, ip);
+  bne(&fail);
+  Jump(success, RelocInfo::CODE_TARGET, al);
+  bind(&fail);
+}
+
+
+void MacroAssembler::TryGetFunctionPrototype(Register function,
+                                             Register result,
+                                             Register scratch,
+                                             Label* miss,
+                                             bool miss_on_bound_function) {
+  // Check that the receiver isn't a smi.
+  JumpIfSmi(function, miss);
+
+  // Check that the function really is a function.  Load map into result reg.
+  CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
+  bne(miss);
+
+  if (miss_on_bound_function) {
+    LoadP(scratch,
+          FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
+    lwz(scratch,
+        FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
+    TestBit(scratch,
+#if V8_TARGET_ARCH_PPC64
+            SharedFunctionInfo::kBoundFunction,
+#else
+            SharedFunctionInfo::kBoundFunction + kSmiTagSize,
+#endif
+            r0);
+    bne(miss, cr0);
+  }
+
+  // Make sure that the function has an instance prototype.
+  Label non_instance;
+  lbz(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
+  andi(r0, scratch, Operand(1 << Map::kHasNonInstancePrototype));
+  bne(&non_instance, cr0);
+
+  // Get the prototype or initial map from the function.
+  LoadP(result,
+        FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+  // If the prototype or initial map is the hole, don't return it and
+  // simply miss the cache instead. This will allow us to allocate a
+  // prototype object on-demand in the runtime system.
+  LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  cmp(result, ip);
+  beq(miss);
+
+  // If the function does not have an initial map, we're done.
+  Label done;
+  CompareObjectType(result, scratch, scratch, MAP_TYPE);
+  bne(&done);
+
+  // Get the prototype from the initial map.
+  LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
+  b(&done);
+
+  // Non-instance prototype: Fetch prototype from constructor field
+  // in initial map.
+  bind(&non_instance);
+  LoadP(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+  // All done.
+  bind(&done);
+}
+
+
+void MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
+  ASSERT(AllowThisStubCall(stub));  // Stub calls are not allowed in some stubs.
+  Call(stub->GetCode(), RelocInfo::CODE_TARGET, TypeFeedbackId::None(), cond);
+}
+
+
+void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
+  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
+  Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
+}
+
+
+static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
+  return ref0.address() - ref1.address();
+}
+
+
+void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
+                                              int stack_space) {
+  ExternalReference next_address =
+      ExternalReference::handle_scope_next_address();
+  const int kNextOffset = 0;
+  const int kLimitOffset = AddressOffset(
+      ExternalReference::handle_scope_limit_address(),
+      next_address);
+  const int kLevelOffset = AddressOffset(
+      ExternalReference::handle_scope_level_address(),
+      next_address);
+
+  // Allocate HandleScope in callee-save registers.
+  // r26 - next_address
+  // r27 - next_address->kNextOffset
+  // r28 - next_address->kLimitOffset
+  // r29 - next_address->kLevelOffset
+  mov(r26, Operand(next_address));
+  LoadP(r27, MemOperand(r26, kNextOffset));
+  LoadP(r28, MemOperand(r26, kLimitOffset));
+  lwz(r29, MemOperand(r26, kLevelOffset));
+  addi(r29, r29, Operand(1));
+  stw(r29, MemOperand(r26, kLevelOffset));
+
+#if !ABI_RETURNS_HANDLES_IN_REGS
+  // PPC LINUX ABI
+  // The return value is pointer-sized non-scalar value.
+  // Space has already been allocated on the stack which will pass as an
+  // implicity first argument.
+  addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
+#endif
+
+  // Native call returns to the DirectCEntry stub which redirects to the
+  // return address pushed on stack (could have moved after GC).
+  // DirectCEntry stub itself is generated early and never moves.
+  DirectCEntryStub stub;
+  stub.GenerateCall(this, function);
+
+#if !ABI_RETURNS_HANDLES_IN_REGS
+  // Retrieve return value from stack buffer
+  LoadP(r3, MemOperand(r3));
+#endif
+
+  Label promote_scheduled_exception;
+  Label delete_allocated_handles;
+  Label leave_exit_frame;
+  Label skip1, skip2;
+
+  // If result is non-zero, dereference to get the result value
+  // otherwise set it to undefined.
+  cmpi(r3, Operand::Zero());
+  bne(&skip1);
+  LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+  b(&skip2);
+  bind(&skip1);
+  LoadP(r3, MemOperand(r3));
+  bind(&skip2);
+
+  // No more valid handles (the result handle was the last one). Restore
+  // previous handle scope.
+  StoreP(r27, MemOperand(r26, kNextOffset));
+  if (emit_debug_code()) {
+    lwz(r4, MemOperand(r26, kLevelOffset));
+    cmp(r4, r29);
+    Check(eq, "Unexpected level after return from api call");
+  }
+  subi(r29, r29, Operand(1));
+  stw(r29, MemOperand(r26, kLevelOffset));
+  LoadP(ip, MemOperand(r26, kLimitOffset));
+  cmp(r28, ip);
+  bne(&delete_allocated_handles);
+
+  // Check if the function scheduled an exception.
+  bind(&leave_exit_frame);
+  LoadRoot(r27, Heap::kTheHoleValueRootIndex);
+  mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate())));
+  LoadP(r28, MemOperand(ip));
+  cmp(r27, r28);
+  bne(&promote_scheduled_exception);
+
+  // LeaveExitFrame expects unwind space to be in a register.
+  mov(r27, Operand(stack_space));
+  LeaveExitFrame(false, r27);
+  blr();
+
+  bind(&promote_scheduled_exception);
+  TailCallExternalReference(
+      ExternalReference(Runtime::kPromoteScheduledException, isolate()),
+      0,
+      1);
+
+  // HandleScope limit has changed. Delete allocated extensions.
+  bind(&delete_allocated_handles);
+  StoreP(r28, MemOperand(r26, kLimitOffset));
+  mr(r27, r3);
+  PrepareCallCFunction(1, r28);
+  mov(r3, Operand(ExternalReference::isolate_address()));
+  CallCFunction(
+      ExternalReference::delete_handle_scope_extensions(isolate()), 1);
+  mr(r3, r27);
+  b(&leave_exit_frame);
+}
+
+
+bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
+  if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
+  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
+}
+
+
+void MacroAssembler::IllegalOperation(int num_arguments) {
+  if (num_arguments > 0) {
+    Add(sp, sp, num_arguments * kPointerSize, r0);
+  }
+  LoadRoot(r0, Heap::kUndefinedValueRootIndex);
+}
+
+
+void MacroAssembler::IndexFromHash(Register hash, Register index) {
+  // If the hash field contains an array index pick it out. The assert checks
+  // that the constants for the maximum number of digits for an array index
+  // cached in the hash field and the number of bits reserved for it does not
+  // conflict.
+  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
+         (1 << String::kArrayIndexValueBits));
+  // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
+  // the low kHashShift bits.
+  STATIC_ASSERT(String::kHashShift == 2);
+  STATIC_ASSERT(String::kArrayIndexValueBits == 24);
+  // index = SmiTag((hash >> 2) & 0x00FFFFFF);
+#if V8_TARGET_ARCH_PPC64
+  ExtractBitRange(index, hash, 25, 2);
+  SmiTag(index);
+#else
+  STATIC_ASSERT(kSmiShift == 1);
+  // 32-bit can do this in one instruction:
+  //    index = (hash & 0x03FFFFFC) >> 1;
+  rlwinm(index, hash, 31, 7, 30);
+#endif
+}
+
+void MacroAssembler::SmiToDoubleFPRegister(Register smi,
+                                            DwVfpRegister value,
+                                            Register scratch1) {
+  SmiUntag(scratch1, smi);
+  FloatingPointHelper::ConvertIntToDouble(this, scratch1, value);
+}
+
+
+// Tries to get a signed int32 out of a double precision floating point heap
+// number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
+// 32bits signed integer range.
+void MacroAssembler::ConvertToInt32(Register source,
+                                    Register dest,
+                                    Register scratch,
+                                    Register scratch2,
+                                    DwVfpRegister double_scratch,
+                                    Label *not_int32) {
+  // Retrieve double from heap
+  lfd(double_scratch, FieldMemOperand(source, HeapNumber::kValueOffset));
+
+  // Convert
+  fctidz(double_scratch, double_scratch);
+
+  addi(sp, sp, Operand(-kDoubleSize));
+  stfd(double_scratch, MemOperand(sp, 0));
+#if V8_TARGET_ARCH_PPC64
+  ld(dest, MemOperand(sp, 0));
+#else
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  lwz(scratch, MemOperand(sp, 4));
+  lwz(dest, MemOperand(sp, 0));
+#else
+  lwz(scratch, MemOperand(sp, 0));
+  lwz(dest, MemOperand(sp, 4));
+#endif
+#endif
+  addi(sp, sp, Operand(kDoubleSize));
+
+  // The result is not a 32-bit integer when the high 33 bits of the
+  // result are not identical.
+#if V8_TARGET_ARCH_PPC64
+  TestIfInt32(dest, scratch, scratch2);
+#else
+  TestIfInt32(scratch, dest, scratch2);
+#endif
+  bne(not_int32);
+}
+
+
+void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode,
+                                     Register result,
+                                     DwVfpRegister double_input,
+                                     Register scratch,
+                                     DwVfpRegister double_scratch,
+                                     CheckForInexactConversion check_inexact) {
+  // Convert
+  if (rounding_mode == kRoundToZero) {
+    fctidz(double_scratch, double_input);
+  } else {
+    SetRoundingMode(rounding_mode);
+    fctid(double_scratch, double_input);
+    ResetRoundingMode();
+  }
+
+  addi(sp, sp, Operand(-kDoubleSize));
+  stfd(double_scratch, MemOperand(sp, 0));
+#if V8_TARGET_ARCH_PPC64
+  ld(result, MemOperand(sp, 0));
+#else
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  lwz(scratch, MemOperand(sp, 4));
+  lwz(result, MemOperand(sp, 0));
+#else
+  lwz(scratch, MemOperand(sp, 0));
+  lwz(result, MemOperand(sp, 4));
+#endif
+#endif
+  addi(sp, sp, Operand(kDoubleSize));
+
+  // The result is a 32-bit integer when the high 33 bits of the
+  // result are identical.
+#if V8_TARGET_ARCH_PPC64
+  TestIfInt32(result, scratch, r0);
+#else
+  TestIfInt32(scratch, result, r0);
+#endif
+
+  if (check_inexact == kCheckForInexactConversion) {
+    Label done;
+    bne(&done);
+
+    // convert back and compare
+    fcfid(double_scratch, double_scratch);
+    fcmpu(double_scratch, double_input);
+    bind(&done);
+  }
+}
+
+
+void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
+                                                 Register input_high,
+                                                 Register input_low,
+                                                 Register scratch) {
+  Label done, high_shift_needed, pos_shift, neg_shift, shift_done;
+
+  li(result, Operand::Zero());
+
+  // check for NaN or +/-Infinity
+  // by extracting exponent (mask: 0x7ff00000)
+  STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u);
+  ExtractBitMask(scratch, input_high, HeapNumber::kExponentMask);
+  cmpli(scratch, Operand(0x7ff));
+  beq(&done);
+
+  // Express exponent as delta to (number of mantissa bits + 31).
+  addi(scratch,
+       scratch,
+       Operand(-(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31)));
+
+  // If the delta is strictly positive, all bits would be shifted away,
+  // which means that we can return 0.
+  cmpi(scratch, Operand::Zero());
+  bgt(&done);
+
+  const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
+  // Calculate shift.
+  addi(scratch, scratch, Operand(kShiftBase + HeapNumber::kMantissaBits));
+
+  // Save the sign.
+  STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
+  Register sign = result;
+  result = no_reg;
+  ExtractSignBit32(sign, input_high);
+
+  // Shifts >= 32 bits should result in zero.
+  // slw extracts only the 6 most significant bits of the shift value.
+  cmpi(scratch, Operand(32));
+  blt(&high_shift_needed);
+  li(input_high, Operand::Zero());
+  subfic(scratch, scratch, Operand(32));
+  b(&neg_shift);
+
+  // Set the implicit 1 before the mantissa part in input_high.
+  bind(&high_shift_needed);
+  STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord >= 16);
+  oris(input_high,
+       input_high,
+       Operand(1 << ((HeapNumber::kMantissaBitsInTopWord) - 16)));
+  // Shift the mantissa bits to the correct position.
+  // We don't need to clear non-mantissa bits as they will be shifted away.
+  // If they weren't, it would mean that the answer is in the 32bit range.
+  slw(input_high, input_high, scratch);
+  subfic(scratch, scratch, Operand(32));
+  b(&pos_shift);
+
+  // Replace the shifted bits with bits from the lower mantissa word.
+
+  bind(&neg_shift);
+  neg(scratch, scratch);
+  slw(input_low, input_low, scratch);
+  b(&shift_done);
+
+  bind(&pos_shift);
+  srw(input_low, input_low, scratch);
+
+  bind(&shift_done);
+  orx(input_high, input_high, input_low);
+
+  // Restore sign if necessary.
+  cmpi(sign, Operand::Zero());
+  result = sign;
+  sign = no_reg;
+  mr(result, input_high);
+  beq(&done);
+  neg(result, result);
+
+  bind(&done);
+}
+
+
+void MacroAssembler::EmitECMATruncate(Register result,
+                                      DwVfpRegister double_input,
+                                      DwVfpRegister double_scratch,
+                                      Register scratch,
+                                      Register input_high,
+                                      Register input_low) {
+  ASSERT(!input_high.is(result));
+  ASSERT(!input_low.is(result));
+  ASSERT(!input_low.is(input_high));
+  ASSERT(!scratch.is(result) &&
+         !scratch.is(input_high) &&
+         !scratch.is(input_low));
+  ASSERT(!double_scratch.is(double_input));
+
+  Label done;
+
+  fctidz(double_scratch, double_input);
+
+  // reserve a slot on the stack
+  stfdu(double_scratch, MemOperand(sp, -8));
+#if V8_TARGET_ARCH_PPC64
+  ld(result, MemOperand(sp, 0));
+#else
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  lwz(scratch, MemOperand(sp, 4));
+  lwz(result, MemOperand(sp));
+#else
+  lwz(scratch, MemOperand(sp, 0));
+  lwz(result, MemOperand(sp, 4));
+#endif
+#endif
+
+  // The result is a 32-bit integer when the high 33 bits of the
+  // result are identical.
+#if V8_TARGET_ARCH_PPC64
+  TestIfInt32(result, scratch, r0);
+#else
+  TestIfInt32(scratch, result, r0);
+#endif
+  beq(&done);
+
+  // Load the double value and perform a manual truncation.
+  stfd(double_input, MemOperand(sp));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  lwz(input_low, MemOperand(sp));
+  lwz(input_high, MemOperand(sp, 4));
+#else
+  lwz(input_high, MemOperand(sp));
+  lwz(input_low, MemOperand(sp, 4));
+#endif
+  EmitOutOfInt32RangeTruncate(result,
+                              input_high,
+                              input_low,
+                              scratch);
+
+  bind(&done);
+
+  // restore the stack
+  addi(sp, sp, Operand(8));
+}
+
+
+void MacroAssembler::GetLeastBitsFromSmi(Register dst,
+                                         Register src,
+                                         int num_least_bits) {
+#if V8_TARGET_ARCH_PPC64
+  rldicl(dst, src, kBitsPerPointer - kSmiShift,
+         kBitsPerPointer - num_least_bits);
+#else
+  rlwinm(dst, src, kBitsPerPointer - kSmiShift,
+         kBitsPerPointer - num_least_bits, 31);
+#endif
+}
+
+
+void MacroAssembler::GetLeastBitsFromInt32(Register dst,
+                                           Register src,
+                                           int num_least_bits) {
+  rlwinm(dst, src, 0, 32 - num_least_bits, 31);
+}
+
+
+void MacroAssembler::CallRuntime(const Runtime::Function* f,
+                                 int num_arguments) {
+  // All parameters are on the stack.  r3 has the return value after call.
+
+  // If the expected number of arguments of the runtime function is
+  // constant, we check that the actual number of arguments match the
+  // expectation.
+  if (f->nargs >= 0 && f->nargs != num_arguments) {
+    IllegalOperation(num_arguments);
+    return;
+  }
+
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  mov(r3, Operand(num_arguments));
+  mov(r4, Operand(ExternalReference(f, isolate())));
+#if V8_TARGET_ARCH_PPC64
+  CEntryStub stub(f->result_size);
+#else
+  CEntryStub stub(1);
+#endif
+  CallStub(&stub);
+}
+
+
+void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
+  CallRuntime(Runtime::FunctionForId(fid), num_arguments);
+}
+
+
+void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
+  const Runtime::Function* function = Runtime::FunctionForId(id);
+  li(r3, Operand(function->nargs));
+  mov(r4, Operand(ExternalReference(function, isolate())));
+  CEntryStub stub(1, kSaveFPRegs);
+  CallStub(&stub);
+}
+
+
+void MacroAssembler::CallExternalReference(const ExternalReference& ext,
+                                           int num_arguments) {
+  mov(r3, Operand(num_arguments));
+  mov(r4, Operand(ext));
+
+  CEntryStub stub(1);
+  CallStub(&stub);
+}
+
+
+void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
+                                               int num_arguments,
+                                               int result_size) {
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  mov(r3, Operand(num_arguments));
+  JumpToExternalReference(ext);
+}
+
+
+void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
+                                     int num_arguments,
+                                     int result_size) {
+  TailCallExternalReference(ExternalReference(fid, isolate()),
+                            num_arguments,
+                            result_size);
+}
+
+
+void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
+  mov(r4, Operand(builtin));
+  CEntryStub stub(1);
+  Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
+}
+
+
+void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
+                                   InvokeFlag flag,
+                                   const CallWrapper& call_wrapper) {
+  // You can't call a builtin without a valid frame.
+  ASSERT(flag == JUMP_FUNCTION || has_frame());
+
+  GetBuiltinEntry(r5, id);
+  if (flag == CALL_FUNCTION) {
+    call_wrapper.BeforeCall(CallSize(r2));
+    SetCallKind(r8, CALL_AS_METHOD);
+    Call(r5);
+    call_wrapper.AfterCall();
+  } else {
+    ASSERT(flag == JUMP_FUNCTION);
+    SetCallKind(r8, CALL_AS_METHOD);
+    Jump(r5);
+  }
+}
+
+
+void MacroAssembler::GetBuiltinFunction(Register target,
+                                        Builtins::JavaScript id) {
+  // Load the builtins object into target register.
+  LoadP(target,
+        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  LoadP(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
+  // Load the JavaScript builtin function from the builtins object.
+  LoadP(target,
+        FieldMemOperand(target,
+                        JSBuiltinsObject::OffsetOfFunctionWithId(id)), r0);
+}
+
+
+void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
+  ASSERT(!target.is(r4));
+  GetBuiltinFunction(r4, id);
+  // Load the code entry point from the builtins object.
+  LoadP(target, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
+}
+
+
+void MacroAssembler::SetCounter(StatsCounter* counter, int value,
+                                Register scratch1, Register scratch2) {
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    mov(scratch1, Operand(value));
+    mov(scratch2, Operand(ExternalReference(counter)));
+    stw(scratch1, MemOperand(scratch2));
+  }
+}
+
+
+void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
+                                      Register scratch1, Register scratch2) {
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    mov(scratch2, Operand(ExternalReference(counter)));
+    lwz(scratch1, MemOperand(scratch2));
+    addi(scratch1, scratch1, Operand(value));
+    stw(scratch1, MemOperand(scratch2));
+  }
+}
+
+
+void MacroAssembler::DecrementCounter(StatsCounter* counter, int value,
+                                      Register scratch1, Register scratch2) {
+  ASSERT(value > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    mov(scratch2, Operand(ExternalReference(counter)));
+    lwz(scratch1, MemOperand(scratch2));
+    subi(scratch1, scratch1, Operand(value));
+    stw(scratch1, MemOperand(scratch2));
+  }
+}
+
+
+void MacroAssembler::Assert(Condition cond, const char* msg, CRegister cr) {
+  if (emit_debug_code())
+    Check(cond, msg, cr);
+}
+
+
+void MacroAssembler::AssertRegisterIsRoot(Register reg,
+                                          Heap::RootListIndex index) {
+  if (emit_debug_code()) {
+    LoadRoot(ip, index);
+    cmp(reg, ip);
+    Check(eq, "Register did not match expected root");
+  }
+}
+
+
+void MacroAssembler::AssertFastElements(Register elements) {
+  if (emit_debug_code()) {
+    ASSERT(!elements.is(ip));
+    Label ok;
+    push(elements);
+    LoadP(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
+    LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
+    cmp(elements, ip);
+    beq(&ok);
+    LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex);
+    cmp(elements, ip);
+    beq(&ok);
+    LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
+    cmp(elements, ip);
+    beq(&ok);
+    Abort("JSObject with fast elements map has slow elements");
+    bind(&ok);
+    pop(elements);
+  }
+}
+
+
+void MacroAssembler::Check(Condition cond, const char* msg, CRegister cr) {
+  Label L;
+  b(cond, &L, cr);
+  Abort(msg);
+  // will not return here
+  bind(&L);
+}
+
+
+void MacroAssembler::Abort(const char* msg) {
+  Label abort_start;
+  bind(&abort_start);
+  // We want to pass the msg string like a smi to avoid GC
+  // problems, however msg is not guaranteed to be aligned
+  // properly. Instead, we pass an aligned pointer that is
+  // a proper v8 smi, but also pass the alignment difference
+  // from the real pointer as a smi.
+  intptr_t p1 = reinterpret_cast<intptr_t>(msg);
+  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
+  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
+#ifdef DEBUG
+  if (msg != NULL) {
+    RecordComment("Abort message: ");
+    RecordComment(msg);
+  }
+#endif
+
+  mov(r0, Operand(p0));
+  push(r0);
+  LoadSmiLiteral(r0, Smi::FromInt(p1 - p0));
+  push(r0);
+  // Disable stub call restrictions to always allow calls to abort.
+  if (!has_frame_) {
+    // We don't actually want to generate a pile of code for this, so just
+    // claim there is a stack frame, without generating one.
+    FrameScope scope(this, StackFrame::NONE);
+    CallRuntime(Runtime::kAbort, 2);
+  } else {
+    CallRuntime(Runtime::kAbort, 2);
+  }
+  // will not return here
+}
+
+
+void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
+  if (context_chain_length > 0) {
+    // Move up the chain of contexts to the context containing the slot.
+    LoadP(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX)));
+    for (int i = 1; i < context_chain_length; i++) {
+      LoadP(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX)));
+    }
+  } else {
+    // Slot is in the current function context.  Move it into the
+    // destination register in case we store into it (the write barrier
+    // cannot be allowed to destroy the context in esi).
+    mr(dst, cp);
+  }
+}
+
+
+void MacroAssembler::LoadTransitionedArrayMapConditional(
+    ElementsKind expected_kind,
+    ElementsKind transitioned_kind,
+    Register map_in_out,
+    Register scratch,
+    Label* no_map_match) {
+  // Load the global or builtins object from the current context.
+  LoadP(scratch,
+      MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  LoadP(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset));
+
+  // Check that the function's map is the same as the expected cached map.
+  LoadP(scratch,
+      MemOperand(scratch,
+                 Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX)));
+  size_t offset = expected_kind * kPointerSize +
+      FixedArrayBase::kHeaderSize;
+  LoadP(ip, FieldMemOperand(scratch, offset));
+  cmp(map_in_out, ip);
+  bne(no_map_match);
+
+  // Use the transitioned cached map.
+  offset = transitioned_kind * kPointerSize +
+      FixedArrayBase::kHeaderSize;
+  LoadP(map_in_out, FieldMemOperand(scratch, offset));
+}
+
+
+void MacroAssembler::LoadInitialArrayMap(
+    Register function_in, Register scratch,
+    Register map_out, bool can_have_holes) {
+  ASSERT(!function_in.is(map_out));
+  Label done;
+  LoadP(map_out, FieldMemOperand(function_in,
+                                 JSFunction::kPrototypeOrInitialMapOffset));
+  if (!FLAG_smi_only_arrays) {
+    ElementsKind kind = can_have_holes ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
+    LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
+                                        kind,
+                                        map_out,
+                                        scratch,
+                                        &done);
+  } else if (can_have_holes) {
+    LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
+                                        FAST_HOLEY_SMI_ELEMENTS,
+                                        map_out,
+                                        scratch,
+                                        &done);
+  }
+  bind(&done);
+}
+
+
+void MacroAssembler::LoadGlobalFunction(int index, Register function) {
+  // Load the global or builtins object from the current context.
+  LoadP(function,
+        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  // Load the native context from the global or builtins object.
+  LoadP(function, FieldMemOperand(function,
+                                  GlobalObject::kNativeContextOffset));
+  // Load the function from the native context.
+  LoadP(function, MemOperand(function, Context::SlotOffset(index)), r0);
+}
+
+
+void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
+                                                  Register map,
+                                                  Register scratch) {
+  // Load the initial map. The global functions all have initial maps.
+  LoadP(map,
+        FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+  if (emit_debug_code()) {
+    Label ok, fail;
+    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK);
+    b(&ok);
+    bind(&fail);
+    Abort("Global functions must have initial map");
+    bind(&ok);
+  }
+}
+
+
+void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
+    Register reg,
+    Register scratch,
+    Label* not_power_of_two_or_zero) {
+  subi(scratch, reg, Operand(1));
+  cmpi(scratch, Operand::Zero());
+  blt(not_power_of_two_or_zero);
+  and_(r0, scratch, reg, SetRC);
+  bne(not_power_of_two_or_zero, cr0);
+}
+
+
+void MacroAssembler::JumpIfNotPowerOfTwoOrZeroAndNeg(
+    Register reg,
+    Register scratch,
+    Label* zero_and_neg,
+    Label* not_power_of_two) {
+  subi(scratch, reg, Operand(1));
+  cmpi(scratch, Operand::Zero());
+  blt(zero_and_neg);
+  and_(r0, scratch, reg, SetRC);
+  bne(not_power_of_two, cr0);
+}
+
+#if !V8_TARGET_ARCH_PPC64
+void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) {
+  ASSERT(!reg.is(overflow));
+  mr(overflow, reg);  // Save original value.
+  SmiTag(reg);
+  xor_(overflow, overflow, reg, SetRC);  // Overflow if (value ^ 2 * value) < 0.
+}
+
+
+void MacroAssembler::SmiTagCheckOverflow(Register dst,
+                                         Register src,
+                                         Register overflow) {
+  if (dst.is(src)) {
+    // Fall back to slower case.
+    SmiTagCheckOverflow(dst, overflow);
+  } else {
+    ASSERT(!dst.is(src));
+    ASSERT(!dst.is(overflow));
+    ASSERT(!src.is(overflow));
+    SmiTag(dst, src);
+    xor_(overflow, dst, src, SetRC);  // Overflow if (value ^ 2 * value) < 0.
+  }
+}
+#endif
+
+void MacroAssembler::JumpIfNotBothSmi(Register reg1,
+                                      Register reg2,
+                                      Label* on_not_both_smi) {
+  STATIC_ASSERT(kSmiTag == 0);
+  ASSERT_EQ(1, static_cast<int>(kSmiTagMask));
+  orx(r0, reg1, reg2, LeaveRC);
+  JumpIfNotSmi(r0, on_not_both_smi);
+}
+
+
+void MacroAssembler::UntagAndJumpIfSmi(
+    Register dst, Register src, Label* smi_case) {
+  STATIC_ASSERT(kSmiTag == 0);
+  STATIC_ASSERT(kSmiTagSize == 1);
+  TestBit(src, 0, r0);
+  SmiUntag(dst, src);
+  beq(smi_case, cr0);
+}
+
+
+void MacroAssembler::UntagAndJumpIfNotSmi(
+    Register dst, Register src, Label* non_smi_case) {
+  STATIC_ASSERT(kSmiTag == 0);
+  STATIC_ASSERT(kSmiTagSize == 1);
+  TestBit(src, 0, r0);
+  SmiUntag(dst, src);
+  bne(non_smi_case, cr0);
+}
+
+
+void MacroAssembler::JumpIfEitherSmi(Register reg1,
+                                     Register reg2,
+                                     Label* on_either_smi) {
+  STATIC_ASSERT(kSmiTag == 0);
+  JumpIfSmi(reg1, on_either_smi);
+  JumpIfSmi(reg2, on_either_smi);
+}
+
+
+void MacroAssembler::AssertNotSmi(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    andi(r0, object, Operand(kSmiTagMask));
+    Check(ne, "Operand is a smi", cr0);
+  }
+}
+
+
+void MacroAssembler::AssertSmi(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    andi(r0, object, Operand(kSmiTagMask));
+    Check(eq, "Operand is not smi", cr0);
+  }
+}
+
+
+void MacroAssembler::AssertString(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    andi(r0, object, Operand(kSmiTagMask));
+    Check(ne, "Operand is not a string", cr0);
+    push(object);
+    LoadP(object, FieldMemOperand(object, HeapObject::kMapOffset));
+    CompareInstanceType(object, object, FIRST_NONSTRING_TYPE);
+    pop(object);
+    Check(lt, "Operand is not a string");
+  }
+}
+
+
+
+void MacroAssembler::AssertRootValue(Register src,
+                                     Heap::RootListIndex root_value_index,
+                                     const char* message) {
+  if (emit_debug_code()) {
+    CompareRoot(src, root_value_index);
+    Check(eq, message);
+  }
+}
+
+
+void MacroAssembler::JumpIfNotHeapNumber(Register object,
+                                         Register heap_number_map,
+                                         Register scratch,
+                                         Label* on_not_heap_number) {
+  LoadP(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+  cmp(scratch, heap_number_map);
+  bne(on_not_heap_number);
+}
+
+
+void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
+    Register first,
+    Register second,
+    Register scratch1,
+    Register scratch2,
+    Label* failure) {
+  // Test that both first and second are sequential ASCII strings.
+  // Assume that they are non-smis.
+  LoadP(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
+  LoadP(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
+  lbz(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  lbz(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
+
+  JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1,
+                                               scratch2,
+                                               scratch1,
+                                               scratch2,
+                                               failure);
+}
+
+void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
+                                                         Register second,
+                                                         Register scratch1,
+                                                         Register scratch2,
+                                                         Label* failure) {
+  // Check that neither is a smi.
+  STATIC_ASSERT(kSmiTag == 0);
+  and_(scratch1, first, second);
+  JumpIfSmi(scratch1, failure);
+  JumpIfNonSmisNotBothSequentialAsciiStrings(first,
+                                             second,
+                                             scratch1,
+                                             scratch2,
+                                             failure);
+}
+
+
+// Allocates a heap number or jumps to the need_gc label if the young space
+// is full and a scavenge is needed.
+void MacroAssembler::AllocateHeapNumber(Register result,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Register heap_number_map,
+                                        Label* gc_required,
+                                        TaggingMode tagging_mode) {
+  // Allocate an object in the heap for the heap number and tag it as a heap
+  // object.
+  AllocateInNewSpace(HeapNumber::kSize,
+                     result,
+                     scratch1,
+                     scratch2,
+                     gc_required,
+                     tagging_mode == TAG_RESULT ? TAG_OBJECT :
+                                                  NO_ALLOCATION_FLAGS);
+
+  // Store heap number map in the allocated object.
+  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+  if (tagging_mode == TAG_RESULT) {
+    StoreP(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset),
+           r0);
+  } else {
+    StoreP(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
+  }
+}
+
+
+void MacroAssembler::AllocateHeapNumberWithValue(Register result,
+                                                 DwVfpRegister value,
+                                                 Register scratch1,
+                                                 Register scratch2,
+                                                 Register heap_number_map,
+                                                 Label* gc_required) {
+  AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
+  stfd(value, FieldMemOperand(result, HeapNumber::kValueOffset));
+}
+
+
+// Copies a fixed number of fields of heap objects from src to dst.
+void MacroAssembler::CopyFields(Register dst,
+                                Register src,
+                                RegList temps,
+                                int field_count) {
+  // At least one bit set in the first 15 registers.
+  ASSERT((temps & ((1 << 15) - 1)) != 0);
+  ASSERT((temps & dst.bit()) == 0);
+  ASSERT((temps & src.bit()) == 0);
+  // Primitive implementation using only one temporary register.
+
+  Register tmp = no_reg;
+  // Find a temp register in temps list.
+  for (int i = 0; i < 15; i++) {
+    if ((temps & (1 << i)) != 0) {
+      tmp.set_code(i);
+      break;
+    }
+  }
+  ASSERT(!tmp.is(no_reg));
+
+  for (int i = 0; i < field_count; i++) {
+    LoadP(tmp, FieldMemOperand(src, i * kPointerSize), r0);
+    StoreP(tmp, FieldMemOperand(dst, i * kPointerSize), r0);
+  }
+}
+
+
+void MacroAssembler::CopyBytes(Register src,
+                               Register dst,
+                               Register length,
+                               Register scratch) {
+  Label align_loop, aligned, word_loop, byte_loop, byte_loop_1, done;
+
+  ASSERT(!scratch.is(r0));
+
+  cmpi(length, Operand::Zero());
+  beq(&done);
+
+  // Check src alignment and length to see whether word_loop is possible
+  andi(scratch, src, Operand(kPointerSize - 1));
+  beq(&aligned, cr0);
+  subfic(scratch, scratch, Operand(kPointerSize * 2));
+  cmp(length, scratch);
+  blt(&byte_loop);
+
+  // Align src before copying in word size chunks.
+  subi(scratch, scratch, Operand(kPointerSize));
+  mtctr(scratch);
+  bind(&align_loop);
+  lbz(scratch, MemOperand(src));
+  addi(src, src, Operand(1));
+  subi(length, length, Operand(1));
+  stb(scratch, MemOperand(dst));
+  addi(dst, dst, Operand(1));
+  bdnz(&align_loop);
+
+  bind(&aligned);
+
+  // Copy bytes in word size chunks.
+  if (emit_debug_code()) {
+    andi(r0, src, Operand(kPointerSize - 1));
+    Assert(eq, "Expecting alignment for CopyBytes", cr0);
+  }
+
+  ShiftRightImm(scratch, length, Operand(kPointerSizeLog2));
+  cmpi(scratch, Operand::Zero());
+  beq(&byte_loop);
+
+  mtctr(scratch);
+  bind(&word_loop);
+  LoadP(scratch, MemOperand(src));
+  addi(src, src, Operand(kPointerSize));
+  subi(length, length, Operand(kPointerSize));
+  if (CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) {
+    // currently false for PPC - but possible future opt
+    StoreP(scratch, MemOperand(dst));
+    addi(dst, dst, Operand(kPointerSize));
+  } else {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+    stb(scratch, MemOperand(dst, 0));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 1));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 2));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 3));
+#if V8_TARGET_ARCH_PPC64
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 4));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 5));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 6));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 7));
+#endif
+#else
+#if V8_TARGET_ARCH_PPC64
+    stb(scratch, MemOperand(dst, 7));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 6));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 5));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 4));
+    ShiftRightImm(scratch, scratch, Operand(8));
+#endif
+    stb(scratch, MemOperand(dst, 3));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 2));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 1));
+    ShiftRightImm(scratch, scratch, Operand(8));
+    stb(scratch, MemOperand(dst, 0));
+#endif
+    addi(dst, dst, Operand(kPointerSize));
+  }
+  bdnz(&word_loop);
+
+  // Copy the last bytes if any left.
+  cmpi(length, Operand::Zero());
+  beq(&done);
+
+  bind(&byte_loop);
+  mtctr(length);
+  bind(&byte_loop_1);
+  lbz(scratch, MemOperand(src));
+  addi(src, src, Operand(1));
+  stb(scratch, MemOperand(dst));
+  addi(dst, dst, Operand(1));
+  bdnz(&byte_loop_1);
+
+  bind(&done);
+}
+
+
+void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
+                                                Register end_offset,
+                                                Register filler) {
+  Label loop, entry;
+  b(&entry);
+  bind(&loop);
+  StoreP(filler, MemOperand(start_offset), r0);
+  addi(start_offset, start_offset, Operand(kPointerSize));
+  bind(&entry);
+  cmp(start_offset, end_offset);
+  blt(&loop);
+}
+
+
+void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii(
+    Register first,
+    Register second,
+    Register scratch1,
+    Register scratch2,
+    Label* failure) {
+  int kFlatAsciiStringMask =
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
+  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
+  andi(scratch1, first, Operand(kFlatAsciiStringMask));
+  andi(scratch2, second, Operand(kFlatAsciiStringMask));
+  cmpi(scratch1, Operand(kFlatAsciiStringTag));
+  bne(failure);
+  cmpi(scratch2, Operand(kFlatAsciiStringTag));
+  bne(failure);
+}
+
+
+void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type,
+                                                            Register scratch,
+                                                            Label* failure) {
+  int kFlatAsciiStringMask =
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
+  int kFlatAsciiStringTag = ASCII_STRING_TYPE;
+  andi(scratch, type, Operand(kFlatAsciiStringMask));
+  cmpi(scratch, Operand(kFlatAsciiStringTag));
+  bne(failure);
+}
+
+static const int kRegisterPassedArguments = 8;
+
+
+int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments,
+                                              int num_double_arguments) {
+  int stack_passed_words = 0;
+  if (num_double_arguments > DoubleRegister::kNumRegisters) {
+      stack_passed_words +=
+          2 * (num_double_arguments - DoubleRegister::kNumRegisters);
+  }
+  // Up to four simple arguments are passed in registers r0..r3.
+  if (num_reg_arguments > kRegisterPassedArguments) {
+    stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
+  }
+  return stack_passed_words;
+}
+
+
+void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
+                                          int num_double_arguments,
+                                          Register scratch) {
+  int frame_alignment = ActivationFrameAlignment();
+  int stack_passed_arguments = CalculateStackPassedWords(
+      num_reg_arguments, num_double_arguments);
+  if (frame_alignment > kPointerSize) {
+    // Make stack end at alignment and make room for stack arguments,
+    // the original value of sp and, on native, the required slots to
+    // make ABI work.
+    mr(scratch, sp);
+#if !defined(USE_SIMULATOR)
+    subi(sp, sp, Operand((stack_passed_arguments +
+                          kNumRequiredStackFrameSlots) * kPointerSize));
+#else
+    subi(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
+#endif
+    ASSERT(IsPowerOf2(frame_alignment));
+    li(r0, Operand(-frame_alignment));
+    and_(sp, sp, r0);
+#if !defined(USE_SIMULATOR)
+    // On the simulator we pass args on the stack
+    StoreP(scratch, MemOperand(sp));
+#else
+    // On the simulator we pass args on the stack
+    StoreP(scratch,
+           MemOperand(sp, stack_passed_arguments * kPointerSize), r0);
+#endif
+  } else {
+    subi(sp, sp, Operand((stack_passed_arguments +
+                          kNumRequiredStackFrameSlots) * kPointerSize));
+  }
+}
+
+
+void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
+                                          Register scratch) {
+  PrepareCallCFunction(num_reg_arguments, 0, scratch);
+}
+
+
+void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
+  Move(d1, dreg);
+}
+
+
+void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
+                                             DoubleRegister dreg2) {
+  if (dreg2.is(d1)) {
+    ASSERT(!dreg1.is(d2));
+    Move(d2, dreg2);
+    Move(d1, dreg1);
+  } else {
+    Move(d1, dreg1);
+    Move(d2, dreg2);
+  }
+}
+
+
+void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
+                                             Register reg) {
+  Move(d1, dreg);
+  Move(r3, reg);
+}
+
+
+void MacroAssembler::CallCFunction(ExternalReference function,
+                                   int num_reg_arguments,
+                                   int num_double_arguments) {
+  mov(ip, Operand(function));
+  CallCFunctionHelper(ip, num_reg_arguments, num_double_arguments);
+}
+
+
+void MacroAssembler::CallCFunction(Register function,
+                                   int num_reg_arguments,
+                                   int num_double_arguments) {
+  CallCFunctionHelper(function, num_reg_arguments, num_double_arguments);
+}
+
+
+void MacroAssembler::CallCFunction(ExternalReference function,
+                                   int num_arguments) {
+  CallCFunction(function, num_arguments, 0);
+}
+
+
+void MacroAssembler::CallCFunction(Register function,
+                                   int num_arguments) {
+  CallCFunction(function, num_arguments, 0);
+}
+
+
+void MacroAssembler::CallCFunctionHelper(Register function,
+                                         int num_reg_arguments,
+                                         int num_double_arguments) {
+  ASSERT(has_frame());
+  // Make sure that the stack is aligned before calling a C function unless
+  // running in the simulator. The simulator has its own alignment check which
+  // provides more information.
+
+  // Just call directly. The function called cannot cause a GC, or
+  // allow preemption, so the return address in the link register
+  // stays correct.
+#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
+  // AIX uses a function descriptor. When calling C code be aware
+  // of this descriptor and pick up values from it
+  Register dest = ip;
+  LoadP(ToRegister(2), MemOperand(function, kPointerSize));
+  LoadP(dest, MemOperand(function, 0));
+#elif ABI_TOC_ADDRESSABILITY_VIA_IP
+  Register dest = ip;
+  Move(ip, function);
+#else
+  Register dest = function;
+#endif
+
+  Call(dest);
+
+  int stack_passed_arguments = CalculateStackPassedWords(
+      num_reg_arguments, num_double_arguments);
+  if (ActivationFrameAlignment() > kPointerSize) {
+#if !defined(USE_SIMULATOR)
+    // On real hardware we follow the ABI
+    LoadP(sp, MemOperand(sp));
+#else
+    // On the simulator we pass args on the stack
+    LoadP(sp, MemOperand(sp, stack_passed_arguments * kPointerSize), r0);
+#endif
+  } else {
+    addi(sp, sp, Operand((stack_passed_arguments +
+                          kNumRequiredStackFrameSlots) * kPointerSize));
+  }
+}
+
+
+void MacroAssembler::FlushICache(Register address, size_t size,
+                                 Register scratch) {
+  Label done;
+
+  dcbf(r0, address);
+  sync();
+  icbi(r0, address);
+  isync();
+
+  // This code handles ranges which cross a single cacheline boundary.
+  // scratch is last cacheline which intersects range.
+  ASSERT(size > 0 && size <= kCacheLineSize);
+  addi(scratch, address, Operand(size - 1));
+  ClearRightImm(scratch, scratch, Operand(kCacheLineSizeLog2));
+  cmpl(scratch, address);
+  ble(&done);
+
+  dcbf(r0, scratch);
+  sync();
+  icbi(r0, scratch);
+  isync();
+
+  bind(&done);
+}
+
+// This code assumes a FIXED_SEQUENCE for lis/ori
+void MacroAssembler::PatchRelocatedValue(Register lis_location,
+                                         Register scratch,
+                                         Register new_value) {
+  lwz(scratch, MemOperand(lis_location));
+  // At this point scratch is a lis instruction.
+  if (emit_debug_code()) {
+    And(scratch, scratch, Operand(kOpcodeMask | (0x1f * B16)));
+    Cmpi(scratch, Operand(ADDIS), r0);
+    Check(eq, "The instruction to patch should be a lis.");
+    lwz(scratch, MemOperand(lis_location));
+  }
+
+  // insert new high word into lis instruction
+#if V8_TARGET_ARCH_PPC64
+  srdi(ip, new_value, Operand(32));
+  rlwimi(scratch, ip, 16, 16, 31);
+#else
+  rlwimi(scratch, new_value, 16, 16, 31);
+#endif
+
+  stw(scratch, MemOperand(lis_location));
+
+  lwz(scratch, MemOperand(lis_location, kInstrSize));
+  // scratch is now ori.
+  if (emit_debug_code()) {
+    And(scratch, scratch, Operand(kOpcodeMask));
+    Cmpi(scratch, Operand(ORI), r0);
+    Check(eq, "The instruction should be an ori");
+    lwz(scratch, MemOperand(lis_location, kInstrSize));
+  }
+
+  // insert new low word into ori instruction
+#if V8_TARGET_ARCH_PPC64
+  rlwimi(scratch, ip, 0, 16, 31);
+#else
+  rlwimi(scratch, new_value, 0, 16, 31);
+#endif
+  stw(scratch, MemOperand(lis_location, kInstrSize));
+
+#if V8_TARGET_ARCH_PPC64
+  if (emit_debug_code()) {
+    lwz(scratch, MemOperand(lis_location, 2*kInstrSize));
+    // scratch is now sldi.
+    And(scratch, scratch, Operand(kOpcodeMask|kExt5OpcodeMask));
+    Cmpi(scratch, Operand(EXT5|RLDICR), r0);
+    Check(eq, "The instruction should be an sldi");
+  }
+
+  lwz(scratch, MemOperand(lis_location, 3*kInstrSize));
+  // scratch is now ori.
+  if (emit_debug_code()) {
+    And(scratch, scratch, Operand(kOpcodeMask));
+    Cmpi(scratch, Operand(ORIS), r0);
+    Check(eq, "The instruction should be an oris");
+    lwz(scratch, MemOperand(lis_location, 3*kInstrSize));
+  }
+
+  rlwimi(scratch, new_value, 16, 16, 31);
+  stw(scratch, MemOperand(lis_location, 3*kInstrSize));
+
+  lwz(scratch, MemOperand(lis_location, 4*kInstrSize));
+  // scratch is now ori.
+  if (emit_debug_code()) {
+    And(scratch, scratch, Operand(kOpcodeMask));
+    Cmpi(scratch, Operand(ORI), r0);
+    Check(eq, "The instruction should be an ori");
+    lwz(scratch, MemOperand(lis_location, 4*kInstrSize));
+  }
+  rlwimi(scratch, new_value, 0, 16, 31);
+  stw(scratch, MemOperand(lis_location, 4*kInstrSize));
+#endif
+
+  // Update the I-cache so the new lis and addic can be executed.
+#if V8_TARGET_ARCH_PPC64
+  FlushICache(lis_location, 5 * kInstrSize, scratch);
+#else
+  FlushICache(lis_location, 2 * kInstrSize, scratch);
+#endif
+}
+
+// This code assumes a FIXED_SEQUENCE for lis/ori
+void MacroAssembler::GetRelocatedValueLocation(Register lis_location,
+                                               Register result,
+                                               Register scratch) {
+  lwz(result, MemOperand(lis_location));
+  if (emit_debug_code()) {
+    And(result, result, Operand(kOpcodeMask | (0x1f * B16)));
+    Cmpi(result, Operand(ADDIS), r0);
+    Check(eq, "The instruction should be a lis.");
+    lwz(result, MemOperand(lis_location));
+  }
+
+  // result now holds a lis instruction. Extract the immediate.
+  slwi(result, result, Operand(16));
+
+  lwz(scratch, MemOperand(lis_location, kInstrSize));
+  if (emit_debug_code()) {
+    And(scratch, scratch, Operand(kOpcodeMask));
+    Cmpi(scratch, Operand(ORI), r0);
+    Check(eq, "The instruction should be an ori");
+    lwz(scratch, MemOperand(lis_location, kInstrSize));
+  }
+  // Copy the low 16bits from ori instruction into result
+  rlwimi(result, scratch, 0, 16, 31);
+
+#if V8_TARGET_ARCH_PPC64
+  if (emit_debug_code()) {
+    lwz(scratch, MemOperand(lis_location, 2*kInstrSize));
+    // scratch is now sldi.
+    And(scratch, scratch, Operand(kOpcodeMask|kExt5OpcodeMask));
+    Cmpi(scratch, Operand(EXT5|RLDICR), r0);
+    Check(eq, "The instruction should be an sldi");
+  }
+
+  lwz(scratch, MemOperand(lis_location, 3*kInstrSize));
+  // scratch is now ori.
+  if (emit_debug_code()) {
+    And(scratch, scratch, Operand(kOpcodeMask));
+    Cmpi(scratch, Operand(ORIS), r0);
+    Check(eq, "The instruction should be an oris");
+    lwz(scratch, MemOperand(lis_location, 3*kInstrSize));
+  }
+  sldi(result, result, Operand(16));
+  rldimi(result, scratch, 0, 48);
+
+  lwz(scratch, MemOperand(lis_location, 4*kInstrSize));
+  // scratch is now ori.
+  if (emit_debug_code()) {
+    And(scratch, scratch, Operand(kOpcodeMask));
+    Cmpi(scratch, Operand(ORI), r0);
+    Check(eq, "The instruction should be an ori");
+    lwz(scratch, MemOperand(lis_location, 4*kInstrSize));
+  }
+  sldi(result, result, Operand(16));
+  rldimi(result, scratch, 0, 48);
+#endif
+}
+
+
+void MacroAssembler::CheckPageFlag(
+    Register object,
+    Register scratch,  // scratch may be same register as object
+    int mask,
+    Condition cc,
+    Label* condition_met) {
+  ASSERT(cc == ne || cc == eq);
+  ClearRightImm(scratch, object, Operand(kPageSizeBits));
+  LoadP(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset));
+
+  And(r0, scratch, Operand(mask), SetRC);
+
+  if (cc == ne) {
+    bne(condition_met, cr0);
+  }
+  if (cc == eq) {
+    beq(condition_met, cr0);
+  }
+}
+
+
+void MacroAssembler::JumpIfBlack(Register object,
+                                 Register scratch0,
+                                 Register scratch1,
+                                 Label* on_black) {
+  HasColor(object, scratch0, scratch1, on_black, 1, 0);  // kBlackBitPattern.
+  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
+}
+
+
+void MacroAssembler::HasColor(Register object,
+                              Register bitmap_scratch,
+                              Register mask_scratch,
+                              Label* has_color,
+                              int first_bit,
+                              int second_bit) {
+  ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, no_reg));
+
+  GetMarkBits(object, bitmap_scratch, mask_scratch);
+
+  Label other_color, word_boundary;
+  lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
+  // Test the first bit
+  and_(r0, ip, mask_scratch, SetRC);
+  b(first_bit == 1 ? eq : ne, &other_color, cr0);
+  // Shift left 1
+  // May need to load the next cell
+  slwi(mask_scratch, mask_scratch, Operand(1), SetRC);
+  beq(&word_boundary, cr0);
+  // Test the second bit
+  and_(r0, ip, mask_scratch, SetRC);
+  b(second_bit == 1 ? ne : eq, has_color, cr0);
+  b(&other_color);
+
+  bind(&word_boundary);
+  lwz(ip, MemOperand(bitmap_scratch,
+                     MemoryChunk::kHeaderSize + kIntSize));
+  andi(r0, ip, Operand(1));
+  b(second_bit == 1 ? ne : eq, has_color, cr0);
+  bind(&other_color);
+}
+
+
+// Detect some, but not all, common pointer-free objects.  This is used by the
+// incremental write barrier which doesn't care about oddballs (they are always
+// marked black immediately so this code is not hit).
+void MacroAssembler::JumpIfDataObject(Register value,
+                                      Register scratch,
+                                      Label* not_data_object) {
+  Label is_data_object;
+  LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
+  CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
+  beq(&is_data_object);
+  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
+  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
+  // If it's a string and it's not a cons string then it's an object containing
+  // no GC pointers.
+  lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  STATIC_ASSERT((kIsIndirectStringMask | kIsNotStringMask) == 0x81);
+  andi(scratch, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask));
+  bne(not_data_object, cr0);
+  bind(&is_data_object);
+}
+
+
+void MacroAssembler::GetMarkBits(Register addr_reg,
+                                 Register bitmap_reg,
+                                 Register mask_reg) {
+  ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg));
+  ASSERT((~Page::kPageAlignmentMask & 0xffff) == 0);
+  lis(r0, Operand((~Page::kPageAlignmentMask >> 16)));
+  and_(bitmap_reg, addr_reg, r0);
+  const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2;
+  ExtractBitRange(mask_reg, addr_reg,
+                  kLowBits - 1,
+                  kPointerSizeLog2);
+  ExtractBitRange(ip, addr_reg,
+                  kPageSizeBits - 1,
+                  kLowBits);
+  ShiftLeftImm(ip, ip, Operand(Bitmap::kBytesPerCellLog2));
+  add(bitmap_reg, bitmap_reg, ip);
+  li(ip, Operand(1));
+  slw(mask_reg, ip, mask_reg);
+}
+
+
+void MacroAssembler::EnsureNotWhite(
+    Register value,
+    Register bitmap_scratch,
+    Register mask_scratch,
+    Register load_scratch,
+    Label* value_is_white_and_not_data) {
+  ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ip));
+  GetMarkBits(value, bitmap_scratch, mask_scratch);
+
+  // If the value is black or grey we don't need to do anything.
+  ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
+  ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
+  ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
+  ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
+
+  Label done;
+
+  // Since both black and grey have a 1 in the first position and white does
+  // not have a 1 there we only need to check one bit.
+  lwz(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
+  and_(r0, mask_scratch, load_scratch, SetRC);
+  bne(&done, cr0);
+
+  if (emit_debug_code()) {
+    // Check for impossible bit pattern.
+    Label ok;
+    // LSL may overflow, making the check conservative.
+    slwi(r0, mask_scratch, Operand(1));
+    and_(r0, load_scratch, r0, SetRC);
+    beq(&ok, cr0);
+    stop("Impossible marking bit pattern");
+    bind(&ok);
+  }
+
+  // Value is white.  We check whether it is data that doesn't need scanning.
+  // Currently only checks for HeapNumber and non-cons strings.
+  Register map = load_scratch;  // Holds map while checking type.
+  Register length = load_scratch;  // Holds length of object after testing type.
+  Label is_data_object, maybe_string_object, is_string_object, is_encoded;
+#if V8_TARGET_ARCH_PPC64
+  Label length_computed;
+#endif
+
+
+  // Check for heap-number
+  LoadP(map, FieldMemOperand(value, HeapObject::kMapOffset));
+  CompareRoot(map, Heap::kHeapNumberMapRootIndex);
+  bne(&maybe_string_object);
+  li(length, Operand(HeapNumber::kSize));
+  b(&is_data_object);
+  bind(&maybe_string_object);
+
+  // Check for strings.
+  ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
+  ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
+  // If it's a string and it's not a cons string then it's an object containing
+  // no GC pointers.
+  Register instance_type = load_scratch;
+  lbz(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  andi(r0, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask));
+  bne(value_is_white_and_not_data, cr0);
+  // It's a non-indirect (non-cons and non-slice) string.
+  // If it's external, the length is just ExternalString::kSize.
+  // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
+  // External strings are the only ones with the kExternalStringTag bit
+  // set.
+  ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
+  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
+  andi(r0, instance_type, Operand(kExternalStringTag));
+  beq(&is_string_object, cr0);
+  li(length, Operand(ExternalString::kSize));
+  b(&is_data_object);
+  bind(&is_string_object);
+
+  // Sequential string, either ASCII or UC16.
+  // For ASCII (char-size of 1) we untag the smi to get the length.
+  // For UC16 (char-size of 2):
+  //   - (32-bit) we just leave the smi tag in place, thereby getting
+  //              the length multiplied by 2.
+  //   - (64-bit) we compute the offset in the 2-byte array
+  ASSERT(kAsciiStringTag == 4 && kStringEncodingMask == 4);
+  LoadP(ip, FieldMemOperand(value, String::kLengthOffset));
+  andi(r0, instance_type, Operand(kStringEncodingMask));
+  beq(&is_encoded, cr0);
+  SmiUntag(ip);
+#if V8_TARGET_ARCH_PPC64
+  b(&length_computed);
+#endif
+  bind(&is_encoded);
+#if V8_TARGET_ARCH_PPC64
+  SmiToShortArrayOffset(ip, ip);
+  bind(&length_computed);
+#else
+  ASSERT(kSmiShift == 1);
+#endif
+  addi(length, ip, Operand(SeqString::kHeaderSize + kObjectAlignmentMask));
+  li(r0, Operand(~kObjectAlignmentMask));
+  and_(length, length, r0);
+
+  bind(&is_data_object);
+  // Value is a data object, and it is white.  Mark it black.  Since we know
+  // that the object is white we can make it black by flipping one bit.
+  lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
+  orx(ip, ip, mask_scratch);
+  stw(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize));
+
+  mov(ip, Operand(~Page::kPageAlignmentMask));
+  and_(bitmap_scratch, bitmap_scratch, ip);
+  lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
+  add(ip, ip, length);
+  stw(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
+
+  bind(&done);
+}
+
+// Saturate a value into 8-bit unsigned integer
+//   if input_value < 0, output_value is 0
+//   if input_value > 255, output_value is 255
+//   otherwise output_value is the input_value
+void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
+  Label done, negative_label, overflow_label;
+  int satval = (1 << 8) - 1;
+
+  cmpi(input_reg, Operand::Zero());
+  blt(&negative_label);
+
+  cmpi(input_reg, Operand(satval));
+  bgt(&overflow_label);
+  if (!output_reg.is(input_reg)) {
+    mr(output_reg, input_reg);
+  }
+  b(&done);
+
+  bind(&negative_label);
+  li(output_reg, Operand::Zero());  // set to 0 if negative
+  b(&done);
+
+
+  bind(&overflow_label);  // set to satval if > satval
+  li(output_reg, Operand(satval));
+
+  bind(&done);
+}
+
+void MacroAssembler::SetRoundingMode(VFPRoundingMode RN) {
+  mtfsfi(7, RN);
+}
+
+void MacroAssembler::ResetRoundingMode() {
+  mtfsfi(7, kRoundToNearest);  // reset (default is kRoundToNearest)
+}
+
+void MacroAssembler::ClampDoubleToUint8(Register result_reg,
+                                        DoubleRegister input_reg,
+                                        DoubleRegister temp_double_reg,
+                                        DoubleRegister temp_double_reg2) {
+  Label above_zero;
+  Label done;
+  Label in_bounds;
+
+  LoadDoubleLiteral(temp_double_reg, 0.0, result_reg);
+  fcmpu(input_reg, temp_double_reg);
+  bgt(&above_zero);
+
+  // Double value is less than zero, NaN or Inf, return 0.
+  LoadIntLiteral(result_reg, 0);
+  b(&done);
+
+  // Double value is >= 255, return 255.
+  bind(&above_zero);
+  LoadDoubleLiteral(temp_double_reg, 255.0, result_reg);
+  fcmpu(input_reg, temp_double_reg);
+  ble(&in_bounds);
+  LoadIntLiteral(result_reg, 255);
+  b(&done);
+
+  // In 0-255 range, round and truncate.
+  bind(&in_bounds);
+
+  // round to nearest (default rounding mode)
+  fctiw(temp_double_reg, input_reg);
+
+  // reserve a slot on the stack
+  stfdu(temp_double_reg, MemOperand(sp, -8));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  lwz(result_reg, MemOperand(sp));
+#else
+  lwz(result_reg, MemOperand(sp, 4));
+#endif
+  // restore the stack
+  addi(sp, sp, Operand(8));
+
+  bind(&done);
+}
+
+void MacroAssembler::LoadInstanceDescriptors(Register map,
+                                             Register descriptors) {
+  LoadP(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset));
+}
+
+
+void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) {
+  LoadP(dst, FieldMemOperand(map, Map::kBitField3Offset));
+  DecodeField<Map::NumberOfOwnDescriptorsBits>(dst);
+}
+
+
+void MacroAssembler::EnumLength(Register dst, Register map) {
+  STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
+  LoadP(dst, FieldMemOperand(map, Map::kBitField3Offset));
+  LoadSmiLiteral(r0, Smi::FromInt(Map::EnumLengthBits::kMask));
+  and_(dst, dst, r0);
+}
+
+
+void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
+  Register  empty_fixed_array_value = r9;
+  LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
+  Label next, start;
+  mr(r5, r3);
+
+  // Check if the enum length field is properly initialized, indicating that
+  // there is an enum cache.
+  LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
+
+  EnumLength(r6, r4);
+  CmpSmiLiteral(r6, Smi::FromInt(Map::kInvalidEnumCache), r0);
+  beq(call_runtime);
+
+  b(&start);
+
+  bind(&next);
+  LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
+
+  // For all objects but the receiver, check that the cache is empty.
+  EnumLength(r6, r4);
+  CmpSmiLiteral(r6, Smi::FromInt(0), r0);
+  bne(call_runtime);
+
+  bind(&start);
+
+  // Check that there are no elements. Register r5 contains the current JS
+  // object we've reached through the prototype chain.
+  LoadP(r5, FieldMemOperand(r5, JSObject::kElementsOffset));
+  cmp(r5, empty_fixed_array_value);
+  bne(call_runtime);
+
+  LoadP(r5, FieldMemOperand(r4, Map::kPrototypeOffset));
+  cmp(r5, null_value);
+  bne(&next);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// New MacroAssembler Interfaces added for PPC
+//
+////////////////////////////////////////////////////////////////////////////////
+void MacroAssembler::LoadIntLiteral(Register dst, int value) {
+  if (is_int16(value)) {
+    li(dst, Operand(value));
+  } else {
+    int hi_word = static_cast<int>(value) >> 16;
+    if ((hi_word << 16) == value) {
+      lis(dst, Operand(hi_word));
+    } else {
+      mov(dst, Operand(value));
+    }
+  }
+}
+
+void MacroAssembler::LoadSmiLiteral(Register dst, Smi *smi) {
+  intptr_t value = reinterpret_cast<intptr_t>(smi);
+#if V8_TARGET_ARCH_PPC64
+  ASSERT((value & 0xffffffff) == 0);
+  LoadIntLiteral(dst, value >> 32);
+  ShiftLeftImm(dst, dst, Operand(32));
+#else
+  LoadIntLiteral(dst, value);
+#endif
+}
+
+void MacroAssembler::LoadDoubleLiteral(DwVfpRegister result,
+                                       double value,
+                                       Register scratch) {
+  addi(sp, sp, Operand(-8));  // reserve 1 temp double on the stack
+
+  // avoid gcc strict aliasing error using union cast
+  union {
+    double dval;
+#if V8_TARGET_ARCH_PPC64
+    intptr_t ival;
+#else
+    intptr_t ival[2];
+#endif
+  } litVal;
+
+  litVal.dval = value;
+#if V8_TARGET_ARCH_PPC64
+  mov(scratch, Operand(litVal.ival));
+  std(scratch, MemOperand(sp));
+#else
+  LoadIntLiteral(scratch, litVal.ival[0]);
+  stw(scratch, MemOperand(sp, 0));
+  LoadIntLiteral(scratch, litVal.ival[1]);
+  stw(scratch, MemOperand(sp, 4));
+#endif
+  lfd(result, MemOperand(sp, 0));
+
+  addi(sp, sp, Operand(8));  // restore the stack ptr
+}
+
+void MacroAssembler::Add(Register dst, Register src,
+                         intptr_t value, Register scratch) {
+  if (is_int16(value)) {
+    addi(dst, src, Operand(value));
+  } else {
+    mov(scratch, Operand(value));
+    add(dst, src, scratch);
+  }
+}
+
+void MacroAssembler::Cmpi(Register src1, const Operand& src2, Register scratch,
+                          CRegister cr) {
+  intptr_t value = src2.immediate();
+  if (is_int16(value)) {
+    cmpi(src1, src2, cr);
+  } else {
+    mov(scratch, src2);
+    cmp(src1, scratch, cr);
+  }
+}
+
+void MacroAssembler::Cmpli(Register src1, const Operand& src2, Register scratch,
+                           CRegister cr) {
+  intptr_t value = src2.immediate();
+  if (is_uint16(value)) {
+    cmpli(src1, src2, cr);
+  } else {
+    mov(scratch, src2);
+    cmpl(src1, scratch, cr);
+  }
+}
+
+void MacroAssembler::And(Register ra, Register rs, const Operand& rb,
+                         RCBit rc) {
+  if (rb.is_reg()) {
+    and_(ra, rs, rb.rm(), rc);
+  } else {
+    if (is_uint16(rb.imm_) && rb.rmode_ == RelocInfo::NONE
+        && rc == SetRC) {
+      andi(ra, rs, rb);
+    } else {
+      // mov handles the relocation.
+      ASSERT(!rs.is(r0));
+      mov(r0, rb);
+      and_(ra, rs, r0, rc);
+    }
+  }
+}
+
+void MacroAssembler::Or(Register ra, Register rs, const Operand& rb, RCBit rc) {
+  if (rb.is_reg()) {
+    orx(ra, rs, rb.rm(), rc);
+  } else {
+    if (is_uint16(rb.imm_) && rb.rmode_ == RelocInfo::NONE && rc == LeaveRC) {
+      ori(ra, rs, rb);
+    } else {
+      // mov handles the relocation.
+      ASSERT(!rs.is(r0));
+      mov(r0, rb);
+      orx(ra, rs, r0, rc);
+    }
+  }
+}
+
+void MacroAssembler::Xor(Register ra, Register rs, const Operand& rb,
+                         RCBit rc) {
+  if (rb.is_reg()) {
+    xor_(ra, rs, rb.rm(), rc);
+  } else {
+    if (is_uint16(rb.imm_) && rb.rmode_ == RelocInfo::NONE && rc == LeaveRC) {
+      xori(ra, rs, rb);
+    } else {
+      // mov handles the relocation.
+      ASSERT(!rs.is(r0));
+      mov(r0, rb);
+      xor_(ra, rs, r0, rc);
+    }
+  }
+}
+
+void MacroAssembler::CmpSmiLiteral(Register src1, Smi *smi, Register scratch,
+                                   CRegister cr) {
+#if V8_TARGET_ARCH_PPC64
+  LoadSmiLiteral(scratch, smi);
+  cmp(src1, scratch, cr);
+#else
+  Cmpi(src1, Operand(smi), scratch, cr);
+#endif
+}
+
+void MacroAssembler::CmplSmiLiteral(Register src1, Smi *smi, Register scratch,
+                                   CRegister cr) {
+#if V8_TARGET_ARCH_PPC64
+  LoadSmiLiteral(scratch, smi);
+  cmpl(src1, scratch, cr);
+#else
+  Cmpli(src1, Operand(smi), scratch, cr);
+#endif
+}
+
+void MacroAssembler::AddSmiLiteral(Register dst, Register src, Smi *smi,
+                                   Register scratch) {
+#if V8_TARGET_ARCH_PPC64
+  LoadSmiLiteral(scratch, smi);
+  add(dst, src, scratch);
+#else
+  Add(dst, src, reinterpret_cast<intptr_t>(smi), scratch);
+#endif
+}
+
+void MacroAssembler::SubSmiLiteral(Register dst, Register src, Smi *smi,
+                                   Register scratch) {
+#if V8_TARGET_ARCH_PPC64
+  LoadSmiLiteral(scratch, smi);
+  sub(dst, src, scratch);
+#else
+  Add(dst, src, -(reinterpret_cast<intptr_t>(smi)), scratch);
+#endif
+}
+
+void MacroAssembler::AndSmiLiteral(Register dst, Register src, Smi *smi,
+                                   Register scratch, RCBit rc) {
+#if V8_TARGET_ARCH_PPC64
+  LoadSmiLiteral(scratch, smi);
+  and_(dst, src, scratch, rc);
+#else
+  And(dst, src, Operand(smi), rc);
+#endif
+}
+
+
+// Load a "pointer" sized value from the memory location
+void MacroAssembler::LoadP(Register dst, const MemOperand& mem,
+                           Register scratch) {
+  int offset = mem.offset();
+
+  if (!scratch.is(no_reg) && !is_int16(offset)) {
+    /* cannot use d-form */
+    LoadIntLiteral(scratch, offset);
+#if V8_TARGET_ARCH_PPC64
+    ldx(dst, MemOperand(mem.ra(), scratch));
+#else
+    lwzx(dst, MemOperand(mem.ra(), scratch));
+#endif
+  } else {
+#if V8_TARGET_ARCH_PPC64
+    int misaligned = (offset & 3);
+    if (misaligned) {
+      // adjust base to conform to offset alignment requirements
+      // Todo: enhance to use scratch if dst is unsuitable
+      ASSERT(!dst.is(r0));
+      addi(dst, mem.ra(), Operand((offset & 3) - 4));
+      ld(dst, MemOperand(dst, (offset & ~3) + 4));
+    } else {
+      ld(dst, mem);
+    }
+#else
+    lwz(dst, mem);
+#endif
+  }
+}
+
+// Store a "pointer" sized value to the memory location
+void MacroAssembler::StoreP(Register src, const MemOperand& mem,
+                            Register scratch) {
+  int offset = mem.offset();
+
+  if (!scratch.is(no_reg) && !is_int16(offset)) {
+    /* cannot use d-form */
+    LoadIntLiteral(scratch, offset);
+#if V8_TARGET_ARCH_PPC64
+    stdx(src, MemOperand(mem.ra(), scratch));
+#else
+    stwx(src, MemOperand(mem.ra(), scratch));
+#endif
+  } else {
+#if V8_TARGET_ARCH_PPC64
+    int misaligned = (offset & 3);
+    if (misaligned) {
+      // adjust base to conform to offset alignment requirements
+      // a suitable scratch is required here
+      ASSERT(!scratch.is(no_reg));
+      if (scratch.is(r0)) {
+        LoadIntLiteral(scratch, offset);
+        stdx(src, MemOperand(mem.ra(), scratch));
+      } else {
+        addi(scratch, mem.ra(), Operand((offset & 3) - 4));
+        std(src, MemOperand(scratch, (offset & ~3) + 4));
+      }
+    } else {
+      std(src, mem);
+    }
+#else
+    stw(src, mem);
+#endif
+  }
+}
+
+void MacroAssembler::LoadWordArith(Register dst, const MemOperand& mem,
+                                   Register scratch) {
+  int offset = mem.offset();
+
+  if (!scratch.is(no_reg) && !is_int16(offset)) {
+    /* cannot use d-form */
+    LoadIntLiteral(scratch, offset);
+#if V8_TARGET_ARCH_PPC64
+    // lwax(dst, MemOperand(mem.ra(), scratch));
+    ASSERT(0);  // lwax not yet implemented
+#else
+    lwzx(dst, MemOperand(mem.ra(), scratch));
+#endif
+  } else {
+#if V8_TARGET_ARCH_PPC64
+    int misaligned = (offset & 3);
+    if (misaligned) {
+      // adjust base to conform to offset alignment requirements
+      // Todo: enhance to use scratch if dst is unsuitable
+      ASSERT(!dst.is(r0));
+      addi(dst, mem.ra(), Operand((offset & 3) - 4));
+      lwa(dst, MemOperand(dst, (offset & ~3) + 4));
+    } else {
+      lwa(dst, mem);
+    }
+#else
+    lwz(dst, mem);
+#endif
+  }
+}
+
+// Variable length depending on whether offset fits into immediate field
+// MemOperand currently only supports d-form
+void MacroAssembler::LoadWord(Register dst, const MemOperand& mem,
+                              Register scratch, bool updateForm) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  bool use_dform = true;
+  if (!is_int16(offset)) {
+    use_dform = false;
+    LoadIntLiteral(scratch, offset);
+  }
+
+  if (!updateForm) {
+    if (use_dform) {
+      lwz(dst, mem);
+    } else {
+      lwzx(dst, MemOperand(base, scratch));
+    }
+  } else {
+    if (use_dform) {
+      lwzu(dst, mem);
+    } else {
+      lwzux(dst, MemOperand(base, scratch));
+    }
+  }
+}
+
+// Variable length depending on whether offset fits into immediate field
+// MemOperand current only supports d-form
+void MacroAssembler::StoreWord(Register src, const MemOperand& mem,
+                               Register scratch, bool updateForm) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  bool use_dform = true;
+  if (!is_int16(offset)) {
+    use_dform = false;
+    LoadIntLiteral(scratch, offset);
+  }
+
+  if (!updateForm) {
+    if (use_dform) {
+      stw(src, mem);
+    } else {
+      stwx(src, MemOperand(base, scratch));
+    }
+  } else {
+    if (use_dform) {
+      stwu(src, mem);
+    } else {
+      stwux(src, MemOperand(base, scratch));
+    }
+  }
+}
+
+// Variable length depending on whether offset fits into immediate field
+// MemOperand currently only supports d-form
+void MacroAssembler::LoadHalfWord(Register dst, const MemOperand& mem,
+                                  Register scratch, bool updateForm) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  bool use_dform = true;
+  if (!is_int16(offset)) {
+    use_dform = false;
+    LoadIntLiteral(scratch, offset);
+  }
+
+  if (!updateForm) {
+    if (use_dform) {
+      lhz(dst, mem);
+    } else {
+      lhzx(dst, MemOperand(base, scratch));
+    }
+  } else {
+    // If updateForm is ever true, then lhzu will
+    // need to be implemented
+    assert(0);
+#if 0  // LoadHalfWord w\ update not yet needed
+    if (use_dform) {
+      lhzu(dst, mem);
+    } else {
+      lhzux(dst, MemOperand(base, scratch));
+    }
+#endif
+  }
+}
+
+// Variable length depending on whether offset fits into immediate field
+// MemOperand current only supports d-form
+void MacroAssembler::StoreHalfWord(Register src, const MemOperand& mem,
+                                   Register scratch, bool updateForm) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  bool use_dform = true;
+  if (!is_int16(offset)) {
+    use_dform = false;
+    LoadIntLiteral(scratch, offset);
+  }
+
+  if (!updateForm) {
+    if (use_dform) {
+      sth(src, mem);
+    } else {
+      sthx(src, MemOperand(base, scratch));
+    }
+  } else {
+    // If updateForm is ever true, then sthu will
+    // need to be implemented
+    assert(0);
+#if 0  // StoreHalfWord w\ update not yet needed
+    if (use_dform) {
+      sthu(src, mem);
+    } else {
+      sthux(src, MemOperand(base, scratch));
+    }
+#endif
+  }
+}
+
+// Variable length depending on whether offset fits into immediate field
+// MemOperand currently only supports d-form
+void MacroAssembler::LoadByte(Register dst, const MemOperand& mem,
+                              Register scratch, bool updateForm) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  bool use_dform = true;
+  if (!is_int16(offset)) {
+    use_dform = false;
+    LoadIntLiteral(scratch, offset);
+  }
+
+  if (!updateForm) {
+    if (use_dform) {
+      lbz(dst, mem);
+    } else {
+      lbzx(dst, MemOperand(base, scratch));
+    }
+  } else {
+    // If updateForm is ever true, then lbzu will
+    // need to be implemented
+    assert(0);
+#if 0  // LoadByte w\ update not yet needed
+    if (use_dform) {
+      lbzu(dst, mem);
+    } else {
+      lbzux(dst, MemOperand(base, scratch));
+    }
+#endif
+  }
+}
+
+// Variable length depending on whether offset fits into immediate field
+// MemOperand current only supports d-form
+void MacroAssembler::StoreByte(Register src, const MemOperand& mem,
+                               Register scratch, bool updateForm) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  bool use_dform = true;
+  if (!is_int16(offset)) {
+    use_dform = false;
+    LoadIntLiteral(scratch, offset);
+  }
+
+  if (!updateForm) {
+    if (use_dform) {
+      stb(src, mem);
+    } else {
+      stbx(src, MemOperand(base, scratch));
+    }
+  } else {
+    // If updateForm is ever true, then stbu will
+    // need to be implemented
+    assert(0);
+#if 0  // StoreByte w\ update not yet needed
+    if (use_dform) {
+      stbu(src, mem);
+    } else {
+      stbux(src, MemOperand(base, scratch));
+    }
+#endif
+  }
+}
+
+#ifdef DEBUG
+bool AreAliased(Register reg1,
+                Register reg2,
+                Register reg3,
+                Register reg4,
+                Register reg5,
+                Register reg6) {
+  int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() +
+    reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid();
+
+  RegList regs = 0;
+  if (reg1.is_valid()) regs |= reg1.bit();
+  if (reg2.is_valid()) regs |= reg2.bit();
+  if (reg3.is_valid()) regs |= reg3.bit();
+  if (reg4.is_valid()) regs |= reg4.bit();
+  if (reg5.is_valid()) regs |= reg5.bit();
+  if (reg6.is_valid()) regs |= reg6.bit();
+  int n_of_non_aliasing_regs = NumRegs(regs);
+
+  return n_of_valid_regs != n_of_non_aliasing_regs;
+}
+#endif
+
+
+CodePatcher::CodePatcher(byte* address, int instructions)
+    : address_(address),
+      instructions_(instructions),
+      size_(instructions * Assembler::kInstrSize),
+      masm_(NULL, address, size_ + Assembler::kGap) {
+  // Create a new macro assembler pointing to the address of the code to patch.
+  // The size is adjusted with kGap on order for the assembler to generate size
+  // bytes of instructions without failing with buffer size constraints.
+  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
+}
+
+
+CodePatcher::~CodePatcher() {
+  // Indicate that code has changed.
+  CPU::FlushICache(address_, size_);
+
+  // Check that the code was patched as expected.
+  ASSERT(masm_.pc_ == address_ + size_);
+  ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
+}
+
+
+void CodePatcher::Emit(Instr instr) {
+  masm()->emit(instr);
+}
+
+
+void CodePatcher::EmitCondition(Condition cond) {
+  Instr instr = Assembler::instr_at(masm_.pc_);
+  switch (cond) {
+    case eq:
+      instr = (instr & ~kCondMask) | BT;
+      break;
+    case ne:
+      instr = (instr & ~kCondMask) | BF;
+      break;
+    default:
+      UNIMPLEMENTED();
+  }
+  masm_.emit(instr);
+}
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/macro-assembler-ppc.h b/src/ppc/macro-assembler-ppc.h
new file mode 100644
index 0000000..6e1b5e6
--- /dev/null
+++ b/src/ppc/macro-assembler-ppc.h
@@ -0,0 +1,1657 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_MACRO_ASSEMBLER_PPC_H_
+#define V8_PPC_MACRO_ASSEMBLER_PPC_H_
+
+#include "assembler.h"
+#include "frames.h"
+#include "v8globals.h"
+
+namespace v8 {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+// Static helper functions
+
+// Generate a MemOperand for loading a field from an object.
+inline MemOperand FieldMemOperand(Register object, int offset) {
+  return MemOperand(object, offset - kHeapObjectTag);
+}
+
+
+
+// Give alias names to registers
+const Register cp = { 20 };  // JavaScript context pointer
+const Register kRootRegister = { 21 };  // Roots array pointer.
+
+// Flags used for the AllocateInNewSpace functions.
+enum AllocationFlags {
+  // No special flags.
+  NO_ALLOCATION_FLAGS = 0,
+  // Return the pointer to the allocated already tagged as a heap object.
+  TAG_OBJECT = 1 << 0,
+  // The content of the result register already contains the allocation top in
+  // new space.
+  RESULT_CONTAINS_TOP = 1 << 1,
+  // Specify that the requested size of the space to allocate is specified in
+  // words instead of bytes.
+  SIZE_IN_WORDS = 1 << 2
+};
+
+// Flags used for AllocateHeapNumber
+enum TaggingMode {
+  // Tag the result.
+  TAG_RESULT,
+  // Don't tag
+  DONT_TAG_RESULT
+};
+
+// Flags used for the ObjectToDoubleVFPRegister function.
+enum ObjectToDoubleFlags {
+  // No special flags.
+  NO_OBJECT_TO_DOUBLE_FLAGS = 0,
+  // Object is known to be a non smi.
+  OBJECT_NOT_SMI = 1 << 0,
+  // Don't load NaNs or infinities, branch to the non number case instead.
+  AVOID_NANS_AND_INFINITIES = 1 << 1
+};
+
+
+enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
+enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
+enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
+
+
+#ifdef DEBUG
+bool AreAliased(Register reg1,
+                Register reg2,
+                Register reg3 = no_reg,
+                Register reg4 = no_reg,
+                Register reg5 = no_reg,
+                Register reg6 = no_reg);
+#endif
+
+// These exist to provide portability between 32 and 64bit
+#if V8_TARGET_ARCH_PPC64
+#define LoadPU             ldu
+#define LoadPX             ldx
+#define LoadPUX            ldux
+#define StorePU            stdu
+#define StorePX            stdx
+#define StorePUX           stdux
+#define ShiftLeftImm       sldi
+#define ShiftRightImm      srdi
+#define ClearLeftImm       clrldi
+#define ClearRightImm      clrrdi
+#define ShiftRightArithImm sradi
+#define ShiftLeft          sld
+#define ShiftRight         srd
+#define ShiftRightArith    srad
+#define Mul                mulld
+#define Div                divd
+#else
+#define LoadPU             lwzu
+#define LoadPX             lwzx
+#define LoadPUX            lwzux
+#define StorePU            stwu
+#define StorePX            stwx
+#define StorePUX           stwux
+#define ShiftLeftImm       slwi
+#define ShiftRightImm      srwi
+#define ClearLeftImm       clrlwi
+#define ClearRightImm      clrrwi
+#define ShiftRightArithImm srawi
+#define ShiftLeft          slw
+#define ShiftRight         srw
+#define ShiftRightArith    sraw
+#define Mul                mullw
+#define Div                divw
+#endif
+
+
+// MacroAssembler implements a collection of frequently used macros.
+class MacroAssembler: public Assembler {
+ public:
+  // The isolate parameter can be NULL if the macro assembler should
+  // not use isolate-dependent functionality. In this case, it's the
+  // responsibility of the caller to never invoke such function on the
+  // macro assembler.
+  MacroAssembler(Isolate* isolate, void* buffer, int size);
+
+  // Jump, Call, and Ret pseudo instructions implementing inter-working.
+  void Jump(Register target, Condition cond = al);
+  void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al,
+            CRegister cr = cr7);
+  void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
+  static int CallSize(Register target, Condition cond = al);
+  void Call(Register target, Condition cond = al);
+  int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
+  static int CallSizeNotPredictableCodeSize(Address target,
+                                            RelocInfo::Mode rmode,
+                                            Condition cond = al);
+  void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
+  int CallSize(Handle<Code> code,
+               RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
+               TypeFeedbackId ast_id = TypeFeedbackId::None(),
+               Condition cond = al);
+  void Call(Handle<Code> code,
+            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
+            TypeFeedbackId ast_id = TypeFeedbackId::None(),
+            Condition cond = al);
+  void Ret(Condition cond = al);
+
+  // Emit code to discard a non-negative number of pointer-sized elements
+  // from the stack, clobbering only the sp register.
+  void Drop(int count, Condition cond = al);
+
+  void Ret(int drop, Condition cond = al);
+
+  void Call(Label* target);
+
+  // Emit call to the code we are currently generating.
+  void CallSelf() {
+    Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
+    Call(self, RelocInfo::CODE_TARGET);
+  }
+
+  // Register move. May do nothing if the registers are identical.
+  void Move(Register dst, Handle<Object> value);
+  void Move(Register dst, Register src, Condition cond = al);
+  void Move(DoubleRegister dst, DoubleRegister src);
+
+  void MultiPush(RegList regs);
+  void MultiPop(RegList regs);
+
+  // Load an object from the root table.
+  void LoadRoot(Register destination,
+                Heap::RootListIndex index,
+                Condition cond = al);
+  // Store an object to the root table.
+  void StoreRoot(Register source,
+                 Heap::RootListIndex index,
+                 Condition cond = al);
+
+  void LoadHeapObject(Register dst, Handle<HeapObject> object);
+
+  void LoadObject(Register result, Handle<Object> object) {
+    if (object->IsHeapObject()) {
+      LoadHeapObject(result, Handle<HeapObject>::cast(object));
+    } else {
+      Move(result, object);
+    }
+  }
+
+  // ---------------------------------------------------------------------------
+  // GC Support
+
+  void IncrementalMarkingRecordWriteHelper(Register object,
+                                           Register value,
+                                           Register address);
+
+  enum RememberedSetFinalAction {
+    kReturnAtEnd,
+    kFallThroughAtEnd
+  };
+
+  // Record in the remembered set the fact that we have a pointer to new space
+  // at the address pointed to by the addr register.  Only works if addr is not
+  // in new space.
+  void RememberedSetHelper(Register object,  // Used for debug code.
+                           Register addr,
+                           Register scratch,
+                           SaveFPRegsMode save_fp,
+                           RememberedSetFinalAction and_then);
+
+  void CheckPageFlag(Register object,
+                     Register scratch,
+                     int mask,
+                     Condition cc,
+                     Label* condition_met);
+
+  // Check if object is in new space.  Jumps if the object is not in new space.
+  // The register scratch can be object itself, but scratch will be clobbered.
+  void JumpIfNotInNewSpace(Register object,
+                           Register scratch,
+                           Label* branch) {
+    InNewSpace(object, scratch, ne, branch);
+  }
+
+  // Check if object is in new space.  Jumps if the object is in new space.
+  // The register scratch can be object itself, but it will be clobbered.
+  void JumpIfInNewSpace(Register object,
+                        Register scratch,
+                        Label* branch) {
+    InNewSpace(object, scratch, eq, branch);
+  }
+
+  // Check if an object has a given incremental marking color.
+  void HasColor(Register object,
+                Register scratch0,
+                Register scratch1,
+                Label* has_color,
+                int first_bit,
+                int second_bit);
+
+  void JumpIfBlack(Register object,
+                   Register scratch0,
+                   Register scratch1,
+                   Label* on_black);
+
+  // Checks the color of an object.  If the object is already grey or black
+  // then we just fall through, since it is already live.  If it is white and
+  // we can determine that it doesn't need to be scanned, then we just mark it
+  // black and fall through.  For the rest we jump to the label so the
+  // incremental marker can fix its assumptions.
+  void EnsureNotWhite(Register object,
+                      Register scratch1,
+                      Register scratch2,
+                      Register scratch3,
+                      Label* object_is_white_and_not_data);
+
+  // Detects conservatively whether an object is data-only, i.e. it does need to
+  // be scanned by the garbage collector.
+  void JumpIfDataObject(Register value,
+                        Register scratch,
+                        Label* not_data_object);
+
+  // Notify the garbage collector that we wrote a pointer into an object.
+  // |object| is the object being stored into, |value| is the object being
+  // stored.  value and scratch registers are clobbered by the operation.
+  // The offset is the offset from the start of the object, not the offset from
+  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
+  void RecordWriteField(
+      Register object,
+      int offset,
+      Register value,
+      Register scratch,
+      LinkRegisterStatus lr_status,
+      SaveFPRegsMode save_fp,
+      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
+      SmiCheck smi_check = INLINE_SMI_CHECK);
+
+  // As above, but the offset has the tag presubtracted.  For use with
+  // MemOperand(reg, off).
+  inline void RecordWriteContextSlot(
+      Register context,
+      int offset,
+      Register value,
+      Register scratch,
+      LinkRegisterStatus lr_status,
+      SaveFPRegsMode save_fp,
+      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
+      SmiCheck smi_check = INLINE_SMI_CHECK) {
+    RecordWriteField(context,
+                     offset + kHeapObjectTag,
+                     value,
+                     scratch,
+                     lr_status,
+                     save_fp,
+                     remembered_set_action,
+                     smi_check);
+  }
+
+  // For a given |object| notify the garbage collector that the slot |address|
+  // has been written.  |value| is the object being stored. The value and
+  // address registers are clobbered by the operation.
+  void RecordWrite(
+      Register object,
+      Register address,
+      Register value,
+      LinkRegisterStatus lr_status,
+      SaveFPRegsMode save_fp,
+      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
+      SmiCheck smi_check = INLINE_SMI_CHECK);
+
+  // Push a handle.
+  void Push(Handle<Object> handle);
+
+  // Push two registers.  Pushes leftmost register first (to highest address).
+  void Push(Register src1, Register src2, Condition cond = al) {
+    ASSERT(!src1.is(src2));
+    StorePU(src1, MemOperand(sp, -kPointerSize));
+    StorePU(src2, MemOperand(sp, -kPointerSize));
+  }
+
+  // Push three registers.  Pushes leftmost register first (to highest address).
+  void Push(Register src1, Register src2, Register src3, Condition cond = al) {
+    ASSERT(!src1.is(src2));
+    ASSERT(!src2.is(src3));
+    ASSERT(!src1.is(src3));
+    StorePU(src1, MemOperand(sp, -kPointerSize));
+    Push(src2, src3, cond);
+  }
+
+  // Push four registers.  Pushes leftmost register first (to highest address).
+  void Push(Register src1,
+            Register src2,
+            Register src3,
+            Register src4,
+            Condition cond = al) {
+    ASSERT(!src1.is(src2));
+    ASSERT(!src2.is(src3));
+    ASSERT(!src1.is(src3));
+    ASSERT(!src1.is(src4));
+    ASSERT(!src2.is(src4));
+    ASSERT(!src3.is(src4));
+
+    StorePU(src1, MemOperand(sp, -kPointerSize));
+    Push(src2, src3, src4, cond);
+  }
+
+  // Pop two registers. Pops rightmost register first (from lower address).
+  void Pop(Register src1, Register src2, Condition cond = al) {
+    ASSERT(!src1.is(src2));
+    ASSERT(cond == al);
+    LoadP(src2, MemOperand(sp, 0));
+    LoadP(src1, MemOperand(sp, kPointerSize));
+    addi(sp, sp, Operand(2 * kPointerSize));
+  }
+
+  // Pop three registers.  Pops rightmost register first (from lower address).
+  void Pop(Register src1, Register src2, Register src3, Condition cond = al) {
+    ASSERT(!src1.is(src2));
+    ASSERT(!src2.is(src3));
+    ASSERT(!src1.is(src3));
+    ASSERT(cond == al);
+    LoadP(src3, MemOperand(sp, 0));
+    LoadP(src2, MemOperand(sp, kPointerSize));
+    LoadP(src1, MemOperand(sp, 2 * kPointerSize));
+    addi(sp, sp, Operand(3 * kPointerSize));
+  }
+
+  // Pop four registers.  Pops rightmost register first (from lower address).
+  void Pop(Register src1,
+           Register src2,
+           Register src3,
+           Register src4,
+           Condition cond = al) {
+    ASSERT(!src1.is(src2));
+    ASSERT(!src2.is(src3));
+    ASSERT(!src1.is(src3));
+    ASSERT(!src1.is(src4));
+    ASSERT(!src2.is(src4));
+    ASSERT(!src3.is(src4));
+    ASSERT(cond == al);
+    LoadP(src4, MemOperand(sp, 0));
+    LoadP(src3, MemOperand(sp, kPointerSize));
+    LoadP(src2, MemOperand(sp, 2 * kPointerSize));
+    LoadP(src1, MemOperand(sp, 3 * kPointerSize));
+    addi(sp, sp, Operand(4 * kPointerSize));
+  }
+
+  // Push and pop the registers that can hold pointers, as defined by the
+  // RegList constant kSafepointSavedRegisters.
+  void PushSafepointRegisters();
+  void PopSafepointRegisters();
+
+  // Store value in register src in the safepoint stack slot for
+  // register dst.
+  void StoreToSafepointRegisterSlot(Register src, Register dst);
+  // Load the value of the src register from its safepoint stack slot
+  // into register dst.
+  void LoadFromSafepointRegisterSlot(Register dst, Register src);
+
+  // Flush the I-cache from asm code. You should use CPU::FlushICache from C.
+  // Does not handle errors.
+  void FlushICache(Register address, size_t size,
+                   Register scratch);
+
+  // Enter exit frame.
+  // stack_space - extra stack space, used for alignment before call to C.
+  void EnterExitFrame(bool save_doubles, int stack_space = 0);
+
+  // Leave the current exit frame. Expects the return value in r0.
+  // Expect the number of values, pushed prior to the exit frame, to
+  // remove in a register (or no_reg, if there is nothing to remove).
+  void LeaveExitFrame(bool save_doubles, Register argument_count);
+
+  // Get the actual activation frame alignment for target environment.
+  static int ActivationFrameAlignment();
+
+  void LoadContext(Register dst, int context_chain_length);
+
+  // Conditionally load the cached Array transitioned map of type
+  // transitioned_kind from the native context if the map in register
+  // map_in_out is the cached Array map in the native context of
+  // expected_kind.
+  void LoadTransitionedArrayMapConditional(
+      ElementsKind expected_kind,
+      ElementsKind transitioned_kind,
+      Register map_in_out,
+      Register scratch,
+      Label* no_map_match);
+
+  // Load the initial map for new Arrays from a JSFunction.
+  void LoadInitialArrayMap(Register function_in,
+                           Register scratch,
+                           Register map_out,
+                           bool can_have_holes);
+
+  void LoadGlobalFunction(int index, Register function);
+
+  // Load the initial map from the global function. The registers
+  // function and map can be the same, function is then overwritten.
+  void LoadGlobalFunctionInitialMap(Register function,
+                                    Register map,
+                                    Register scratch);
+
+  void InitializeRootRegister() {
+    ExternalReference roots_array_start =
+        ExternalReference::roots_array_start(isolate());
+    mov(kRootRegister, Operand(roots_array_start));
+  }
+
+  // ----------------------------------------------------------------
+  // new PPC macro-assembler interfaces that are slightly higher level
+  // than assembler-ppc and may generate variable length sequences
+
+  // load a literal signed int value <value> to GPR <dst>
+  void LoadIntLiteral(Register dst, int value);
+
+  // load an SMI value <value> to GPR <dst>
+  void LoadSmiLiteral(Register dst, Smi *smi);
+
+  // load a literal double value <value> to FPR <result>
+  void LoadDoubleLiteral(DwVfpRegister result,
+                         double value,
+                         Register scratch);
+
+  void LoadWord(Register dst,
+                const MemOperand& mem,
+                Register scratch,
+                bool updateForm = false);
+
+  void LoadWordArith(Register dst,
+                     const MemOperand& mem,
+                     Register scratch = no_reg);
+
+  void StoreWord(Register src,
+                 const MemOperand& mem,
+                 Register scratch,
+                 bool updateForm = false);
+
+  void LoadHalfWord(Register dst,
+                    const MemOperand& mem,
+                    Register scratch,
+                    bool updateForm = false);
+
+  void StoreHalfWord(Register src,
+                     const MemOperand& mem,
+                     Register scratch,
+                     bool updateForm = false);
+
+  void LoadByte(Register dst,
+                const MemOperand& mem,
+                Register scratch,
+                bool updateForm = false);
+
+  void StoreByte(Register src,
+                 const MemOperand& mem,
+                 Register scratch,
+                 bool updateForm = false);
+
+
+
+  void Add(Register dst, Register src, intptr_t value, Register scratch);
+  void Cmpi(Register src1, const Operand& src2, Register scratch,
+            CRegister cr = cr7);
+  void Cmpli(Register src1, const Operand& src2, Register scratch,
+             CRegister cr = cr7);
+  void And(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
+  void Or(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
+  void Xor(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
+
+  void AddSmiLiteral(Register dst, Register src, Smi *smi, Register scratch);
+  void SubSmiLiteral(Register dst, Register src, Smi *smi, Register scratch);
+  void CmpSmiLiteral(Register src1, Smi *smi, Register scratch,
+                     CRegister cr = cr7);
+  void CmplSmiLiteral(Register src1, Smi *smi, Register scratch,
+                      CRegister cr = cr7);
+  void AndSmiLiteral(Register dst, Register src, Smi *smi, Register scratch,
+                     RCBit rc = LeaveRC);
+
+  // Set new rounding mode RN to FPSCR
+  void SetRoundingMode(VFPRoundingMode RN);
+
+  // reset rounding mode to default (kRoundToNearest)
+  void ResetRoundingMode();
+
+  // These exist to provide portability between 32 and 64bit
+  void LoadP(Register dst, const MemOperand& mem, Register scratch = no_reg);
+  void StoreP(Register src, const MemOperand& mem, Register scratch = no_reg);
+
+  // ---------------------------------------------------------------------------
+  // JavaScript invokes
+
+  // Set up call kind marking in ecx. The method takes ecx as an
+  // explicit first parameter to make the code more readable at the
+  // call sites.
+  void SetCallKind(Register dst, CallKind kind);
+
+  // Invoke the JavaScript function code by either calling or jumping.
+  void InvokeCode(Register code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  InvokeFlag flag,
+                  const CallWrapper& call_wrapper,
+                  CallKind call_kind);
+
+  void InvokeCode(Handle<Code> code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  RelocInfo::Mode rmode,
+                  InvokeFlag flag,
+                  CallKind call_kind);
+
+  // Invoke the JavaScript function in the given register. Changes the
+  // current context to the context in the function before invoking.
+  void InvokeFunction(Register function,
+                      const ParameterCount& actual,
+                      InvokeFlag flag,
+                      const CallWrapper& call_wrapper,
+                      CallKind call_kind);
+
+  void InvokeFunction(Handle<JSFunction> function,
+                      const ParameterCount& actual,
+                      InvokeFlag flag,
+                      const CallWrapper& call_wrapper,
+                      CallKind call_kind);
+
+  void IsObjectJSObjectType(Register heap_object,
+                            Register map,
+                            Register scratch,
+                            Label* fail);
+
+  void IsInstanceJSObjectType(Register map,
+                              Register scratch,
+                              Label* fail);
+
+  void IsObjectJSStringType(Register object,
+                            Register scratch,
+                            Label* fail);
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  // ---------------------------------------------------------------------------
+  // Debugger Support
+
+  void DebugBreak();
+#endif
+
+  // ---------------------------------------------------------------------------
+  // Exception handling
+
+  // Push a new try handler and link into try handler chain.
+  void PushTryHandler(StackHandler::Kind kind, int handler_index);
+
+  // Unlink the stack handler on top of the stack from the try handler chain.
+  // Must preserve the result register.
+  void PopTryHandler();
+
+  // Passes thrown value to the handler of top of the try handler chain.
+  void Throw(Register value);
+
+  // Propagates an uncatchable exception to the top of the current JS stack's
+  // handler chain.
+  void ThrowUncatchable(Register value);
+
+  // ---------------------------------------------------------------------------
+  // Inline caching support
+
+  // Generate code for checking access rights - used for security checks
+  // on access to global objects across environments. The holder register
+  // is left untouched, whereas both scratch registers are clobbered.
+  void CheckAccessGlobalProxy(Register holder_reg,
+                              Register scratch,
+                              Label* miss);
+
+  void GetNumberHash(Register t0, Register scratch);
+
+  void LoadFromNumberDictionary(Label* miss,
+                                Register elements,
+                                Register key,
+                                Register result,
+                                Register t0,
+                                Register t1,
+                                Register t2);
+
+
+  inline void MarkCode(NopMarkerTypes type) {
+    nop(type);
+  }
+
+  // Check if the given instruction is a 'type' marker.
+  // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
+  // These instructions are generated to mark special location in the code,
+  // like some special IC code.
+  static inline bool IsMarkedCode(Instr instr, int type) {
+    ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
+    return IsNop(instr, type);
+  }
+
+
+  static inline int GetCodeMarker(Instr instr) {
+    int dst_reg_offset = 12;
+    int dst_mask = 0xf << dst_reg_offset;
+    int src_mask = 0xf;
+    int dst_reg = (instr & dst_mask) >> dst_reg_offset;
+    int src_reg = instr & src_mask;
+    uint32_t non_register_mask = ~(dst_mask | src_mask);
+    uint32_t mov_mask = al | 13 << 21;
+
+    // Return <n> if we have a mov rn rn, else return -1.
+    int type = ((instr & non_register_mask) == mov_mask) &&
+               (dst_reg == src_reg) &&
+               (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
+                   ? src_reg
+                   : -1;
+    ASSERT((type == -1) ||
+           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
+    return type;
+  }
+
+
+  // ---------------------------------------------------------------------------
+  // Allocation support
+
+  // Allocate an object in new space. The object_size is specified
+  // either in bytes or in words if the allocation flag SIZE_IN_WORDS
+  // is passed. If the new space is exhausted control continues at the
+  // gc_required label. The allocated object is returned in result. If
+  // the flag tag_allocated_object is true the result is tagged as as
+  // a heap object. All registers are clobbered also when control
+  // continues at the gc_required label.
+  void AllocateInNewSpace(int object_size,
+                          Register result,
+                          Register scratch1,
+                          Register scratch2,
+                          Label* gc_required,
+                          AllocationFlags flags);
+  void AllocateInNewSpace(Register object_size,
+                          Register result,
+                          Register scratch1,
+                          Register scratch2,
+                          Label* gc_required,
+                          AllocationFlags flags);
+
+  // Undo allocation in new space. The object passed and objects allocated after
+  // it will no longer be allocated. The caller must make sure that no pointers
+  // are left to the object(s) no longer allocated as they would be invalid when
+  // allocation is undone.
+  void UndoAllocationInNewSpace(Register object, Register scratch);
+
+
+  void AllocateTwoByteString(Register result,
+                             Register length,
+                             Register scratch1,
+                             Register scratch2,
+                             Register scratch3,
+                             Label* gc_required);
+  void AllocateAsciiString(Register result,
+                           Register length,
+                           Register scratch1,
+                           Register scratch2,
+                           Register scratch3,
+                           Label* gc_required);
+  void AllocateTwoByteConsString(Register result,
+                                 Register length,
+                                 Register scratch1,
+                                 Register scratch2,
+                                 Label* gc_required);
+  void AllocateAsciiConsString(Register result,
+                               Register length,
+                               Register scratch1,
+                               Register scratch2,
+                               Label* gc_required);
+  void AllocateTwoByteSlicedString(Register result,
+                                   Register length,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Label* gc_required);
+  void AllocateAsciiSlicedString(Register result,
+                                 Register length,
+                                 Register scratch1,
+                                 Register scratch2,
+                                 Label* gc_required);
+
+  // Allocates a heap number or jumps to the gc_required label if the young
+  // space is full and a scavenge is needed. All registers are clobbered also
+  // when control continues at the gc_required label.
+  void AllocateHeapNumber(Register result,
+                          Register scratch1,
+                          Register scratch2,
+                          Register heap_number_map,
+                          Label* gc_required,
+                          TaggingMode tagging_mode = TAG_RESULT);
+  void AllocateHeapNumberWithValue(Register result,
+                                   DwVfpRegister value,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Register heap_number_map,
+                                   Label* gc_required);
+
+  // Copies a fixed number of fields of heap objects from src to dst.
+  void CopyFields(Register dst, Register src, RegList temps, int field_count);
+
+  // Copies a number of bytes from src to dst. All registers are clobbered. On
+  // exit src and dst will point to the place just after where the last byte was
+  // read or written and length will be zero.
+  void CopyBytes(Register src,
+                 Register dst,
+                 Register length,
+                 Register scratch);
+
+  // Initialize fields with filler values.  Fields starting at |start_offset|
+  // not including end_offset are overwritten with the value in |filler|.  At
+  // the end the loop, |start_offset| takes the value of |end_offset|.
+  void InitializeFieldsWithFiller(Register start_offset,
+                                  Register end_offset,
+                                  Register filler);
+
+  // ---------------------------------------------------------------------------
+  // Support functions.
+
+  // Try to get function prototype of a function and puts the value in
+  // the result register. Checks that the function really is a
+  // function and jumps to the miss label if the fast checks fail. The
+  // function register will be untouched; the other registers may be
+  // clobbered.
+  void TryGetFunctionPrototype(Register function,
+                               Register result,
+                               Register scratch,
+                               Label* miss,
+                               bool miss_on_bound_function = false);
+
+  // Compare object type for heap object.  heap_object contains a non-Smi
+  // whose object type should be compared with the given type.  This both
+  // sets the flags and leaves the object type in the type_reg register.
+  // It leaves the map in the map register (unless the type_reg and map register
+  // are the same register).  It leaves the heap object in the heap_object
+  // register unless the heap_object register is the same register as one of the
+  // other registers.
+  void CompareObjectType(Register heap_object,
+                         Register map,
+                         Register type_reg,
+                         InstanceType type);
+
+  // Compare instance type in a map.  map contains a valid map object whose
+  // object type should be compared with the given type.  This both
+  // sets the flags and leaves the object type in the type_reg register.
+  void CompareInstanceType(Register map,
+                           Register type_reg,
+                           InstanceType type);
+
+
+  // Check if a map for a JSObject indicates that the object has fast elements.
+  // Jump to the specified label if it does not.
+  void CheckFastElements(Register map,
+                         Register scratch,
+                         Label* fail);
+
+  // Check if a map for a JSObject indicates that the object can have both smi
+  // and HeapObject elements.  Jump to the specified label if it does not.
+  void CheckFastObjectElements(Register map,
+                               Register scratch,
+                               Label* fail);
+
+  // Check if a map for a JSObject indicates that the object has fast smi only
+  // elements.  Jump to the specified label if it does not.
+  void CheckFastSmiElements(Register map,
+                            Register scratch,
+                            Label* fail);
+
+  // Check to see if maybe_number can be stored as a double in
+  // FastDoubleElements. If it can, store it at the index specified by key in
+  // the FastDoubleElements array elements. Otherwise jump to fail, in which
+  // case scratch2, scratch3 and scratch4 are unmodified.
+  void StoreNumberToDoubleElements(Register value_reg,
+                                   Register key_reg,
+                                   Register receiver_reg,
+                                   // All regs below here overwritten.
+                                   Register elements_reg,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Register scratch3,
+                                   Register scratch4,
+                                   Label* fail);
+
+  // Compare an object's map with the specified map and its transitioned
+  // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
+  // set with result of map compare. If multiple map compares are required, the
+  // compare sequences branches to early_success.
+  void CompareMap(Register obj,
+                  Register scratch,
+                  Handle<Map> map,
+                  Label* early_success,
+                  CompareMapMode mode = REQUIRE_EXACT_MAP);
+
+  // As above, but the map of the object is already loaded into the register
+  // which is preserved by the code generated.
+  void CompareMap(Register obj_map,
+                  Handle<Map> map,
+                  Label* early_success,
+                  CompareMapMode mode = REQUIRE_EXACT_MAP);
+
+  // Check if the map of an object is equal to a specified map and branch to
+  // label if not. Skip the smi check if not required (object is known to be a
+  // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
+  // against maps that are ElementsKind transition maps of the specified map.
+  void CheckMap(Register obj,
+                Register scratch,
+                Handle<Map> map,
+                Label* fail,
+                SmiCheckType smi_check_type,
+                CompareMapMode mode = REQUIRE_EXACT_MAP);
+
+
+  void CheckMap(Register obj,
+                Register scratch,
+                Heap::RootListIndex index,
+                Label* fail,
+                SmiCheckType smi_check_type);
+
+
+  // Check if the map of an object is equal to a specified map and branch to a
+  // specified target if equal. Skip the smi check if not required (object is
+  // known to be a heap object)
+  void DispatchMap(Register obj,
+                   Register scratch,
+                   Handle<Map> map,
+                   Handle<Code> success,
+                   SmiCheckType smi_check_type);
+
+
+  // Compare the object in a register to a value from the root list.
+  // Uses the ip register as scratch.
+  void CompareRoot(Register obj, Heap::RootListIndex index);
+
+
+  // Load and check the instance type of an object for being a string.
+  // Loads the type into the second argument register.
+  // Returns a condition that will be enabled if the object was a string.
+  Condition IsObjectStringType(Register obj,
+                               Register type) {
+    LoadP(type, FieldMemOperand(obj, HeapObject::kMapOffset));
+    lbz(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
+    andi(r0, type, Operand(kIsNotStringMask));
+    ASSERT_EQ(0, kStringTag);
+    return eq;
+  }
+
+
+  // Generates code for reporting that an illegal operation has
+  // occurred.
+  void IllegalOperation(int num_arguments);
+
+  // Picks out an array index from the hash field.
+  // Register use:
+  //   hash - holds the index's hash. Clobbered.
+  //   index - holds the overwritten index on exit.
+  void IndexFromHash(Register hash, Register index);
+
+  // Get the number of least significant bits from a register
+  void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
+  void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
+
+  // Load the value of a smi object into a FP double register. The register
+  // scratch1 can be the same register as smi in which case smi will hold the
+  // untagged value afterwards.
+  void SmiToDoubleFPRegister(Register smi,
+                              DwVfpRegister value,
+                              Register scratch1);
+
+  // Overflow handling functions.
+  // Usage: call the appropriate arithmetic function and then call one of the
+  // flow control functions with the corresponding label.
+
+  // Compute dst = left + right, setting condition codes. dst may be same as
+  // either left or right (or a unique register). left and right must not be
+  // the same register.
+  void AddAndCheckForOverflow(Register dst,
+                              Register left,
+                              Register right,
+                              Register overflow_dst,
+                              Register scratch = r0);
+
+  // Compute dst = left - right, setting condition codes. dst may be same as
+  // either left or right (or a unique register). left and right must not be
+  // the same register.
+  void SubAndCheckForOverflow(Register dst,
+                              Register left,
+                              Register right,
+                              Register overflow_dst,
+                              Register scratch = r0);
+
+  void BranchOnOverflow(Label* label) {
+    blt(label, cr0);
+  }
+
+  void BranchOnNoOverflow(Label* label) {
+    bge(label, cr0);
+  }
+
+  void RetOnOverflow(void) {
+    Label label;
+
+    blt(&label, cr0);
+    Ret();
+    bind(&label);
+  }
+
+  void RetOnNoOverflow(void) {
+    Label label;
+
+    bge(&label, cr0);
+    Ret();
+    bind(&label);
+  }
+
+  // Convert the HeapNumber pointed to by source to a 32bits signed integer
+  // dest. If the HeapNumber does not fit into a 32bits signed integer branch
+  // to not_int32 label. If VFP3 is available double_scratch is used but not
+  // scratch2
+  void ConvertToInt32(Register source,
+                      Register dest,
+                      Register scratch,
+                      Register scratch2,
+                      DwVfpRegister double_scratch,
+                      Label *not_int32);
+
+  // Truncates a double using a specific rounding mode, and writes the value
+  // to the result register.
+  // Clears the z flag (ne condition) if an overflow occurs.
+  // If kCheckForInexactConversion is passed, the z flag is also cleared if the
+  // conversion was inexact, i.e. if the double value could not be converted
+  // exactly to a 32-bit integer.
+  void EmitVFPTruncate(VFPRoundingMode rounding_mode,
+                       Register result,
+                       DwVfpRegister double_input,
+                       Register scratch,
+                       DwVfpRegister double_scratch,
+                       CheckForInexactConversion check
+                           = kDontCheckForInexactConversion);
+
+  // Helper for EmitECMATruncate.
+  // This will truncate a floating-point value outside of the signed 32bit
+  // integer range to a 32bit signed integer.
+  // Expects the double value loaded in input_high and input_low.
+  // Exits with the answer in 'result'.
+  // Note that this code does not work for values in the 32bit range!
+  void EmitOutOfInt32RangeTruncate(Register result,
+                                   Register input_high,
+                                   Register input_low,
+                                   Register scratch);
+
+  // Performs a truncating conversion of a floating point number as used by
+  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
+  // Exits with 'result' holding the answer and all other registers clobbered.
+  void EmitECMATruncate(Register result,
+                        DwVfpRegister double_input,
+                        DwVfpRegister double_scratch,
+                        Register scratch,
+                        Register scratch2,
+                        Register scratch3);
+
+  // ---------------------------------------------------------------------------
+  // Runtime calls
+
+  // Call a code stub.
+  void CallStub(CodeStub* stub, Condition cond = al);
+
+  // Call a code stub.
+  void TailCallStub(CodeStub* stub, Condition cond = al);
+
+  // Call a runtime routine.
+  void CallRuntime(const Runtime::Function* f, int num_arguments);
+  void CallRuntimeSaveDoubles(Runtime::FunctionId id);
+
+  // Convenience function: Same as above, but takes the fid instead.
+  void CallRuntime(Runtime::FunctionId fid, int num_arguments);
+
+  // Convenience function: call an external reference.
+  void CallExternalReference(const ExternalReference& ext,
+                             int num_arguments);
+
+  // Tail call of a runtime routine (jump).
+  // Like JumpToExternalReference, but also takes care of passing the number
+  // of parameters.
+  void TailCallExternalReference(const ExternalReference& ext,
+                                 int num_arguments,
+                                 int result_size);
+
+  // Convenience function: tail call a runtime routine (jump).
+  void TailCallRuntime(Runtime::FunctionId fid,
+                       int num_arguments,
+                       int result_size);
+
+  int CalculateStackPassedWords(int num_reg_arguments,
+                                int num_double_arguments);
+
+  // Before calling a C-function from generated code, align arguments on stack.
+  // After aligning the frame, non-register arguments must be stored in
+  // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
+  // are word sized. If double arguments are used, this function assumes that
+  // all double arguments are stored before core registers; otherwise the
+  // correct alignment of the double values is not guaranteed.
+  // Some compilers/platforms require the stack to be aligned when calling
+  // C++ code.
+  // Needs a scratch register to do some arithmetic. This register will be
+  // trashed.
+  void PrepareCallCFunction(int num_reg_arguments,
+                            int num_double_registers,
+                            Register scratch);
+  void PrepareCallCFunction(int num_reg_arguments,
+                            Register scratch);
+
+  // There are two ways of passing double arguments on ARM, depending on
+  // whether soft or hard floating point ABI is used. These functions
+  // abstract parameter passing for the three different ways we call
+  // C functions from generated code.
+  void SetCallCDoubleArguments(DoubleRegister dreg);
+  void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
+  void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
+
+  // Calls a C function and cleans up the space for arguments allocated
+  // by PrepareCallCFunction. The called function is not allowed to trigger a
+  // garbage collection, since that might move the code and invalidate the
+  // return address (unless this is somehow accounted for by the called
+  // function).
+  void CallCFunction(ExternalReference function, int num_arguments);
+  void CallCFunction(Register function, int num_arguments);
+  void CallCFunction(ExternalReference function,
+                     int num_reg_arguments,
+                     int num_double_arguments);
+  void CallCFunction(Register function,
+                     int num_reg_arguments,
+                     int num_double_arguments);
+
+  void GetCFunctionDoubleResult(const DoubleRegister dst);
+
+  // Calls an API function.  Allocates HandleScope, extracts returned value
+  // from handle and propagates exceptions.  Restores context.  stack_space
+  // - space to be unwound on exit (includes the call JS arguments space and
+  // the additional space allocated for the fast call).
+  void CallApiFunctionAndReturn(ExternalReference function, int stack_space);
+
+  // Jump to a runtime routine.
+  void JumpToExternalReference(const ExternalReference& builtin);
+
+  // Invoke specified builtin JavaScript function. Adds an entry to
+  // the unresolved list if the name does not resolve.
+  void InvokeBuiltin(Builtins::JavaScript id,
+                     InvokeFlag flag,
+                     const CallWrapper& call_wrapper = NullCallWrapper());
+
+  // Store the code object for the given builtin in the target register and
+  // setup the function in r1.
+  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
+
+  // Store the function for the given builtin in the target register.
+  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
+
+  Handle<Object> CodeObject() {
+    ASSERT(!code_object_.is_null());
+    return code_object_;
+  }
+
+
+  // ---------------------------------------------------------------------------
+  // StatsCounter support
+
+  void SetCounter(StatsCounter* counter, int value,
+                  Register scratch1, Register scratch2);
+  void IncrementCounter(StatsCounter* counter, int value,
+                        Register scratch1, Register scratch2);
+  void DecrementCounter(StatsCounter* counter, int value,
+                        Register scratch1, Register scratch2);
+
+
+  // ---------------------------------------------------------------------------
+  // Debugging
+
+  // Calls Abort(msg) if the condition cond is not satisfied.
+  // Use --debug_code to enable.
+  void Assert(Condition cond, const char* msg, CRegister cr = cr7);
+  void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
+  void AssertFastElements(Register elements);
+
+  // Like Assert(), but always enabled.
+  void Check(Condition cond, const char* msg, CRegister cr = cr7);
+
+  // Print a message to stdout and abort execution.
+  void Abort(const char* msg);
+
+  // Verify restrictions about code generated in stubs.
+  void set_generating_stub(bool value) { generating_stub_ = value; }
+  bool generating_stub() { return generating_stub_; }
+  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
+  bool allow_stub_calls() { return allow_stub_calls_; }
+  void set_has_frame(bool value) { has_frame_ = value; }
+  bool has_frame() { return has_frame_; }
+  inline bool AllowThisStubCall(CodeStub* stub);
+
+  // ---------------------------------------------------------------------------
+  // Number utilities
+
+  // Check whether the value of reg is a power of two and not zero. If not
+  // control continues at the label not_power_of_two. If reg is a power of two
+  // the register scratch contains the value of (reg - 1) when control falls
+  // through.
+  void JumpIfNotPowerOfTwoOrZero(Register reg,
+                                 Register scratch,
+                                 Label* not_power_of_two_or_zero);
+  // Check whether the value of reg is a power of two and not zero.
+  // Control falls through if it is, with scratch containing the mask
+  // value (reg - 1).
+  // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
+  // zero or negative, or jumps to the 'not_power_of_two' label if the value is
+  // strictly positive but not a power of two.
+  void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
+                                       Register scratch,
+                                       Label* zero_and_neg,
+                                       Label* not_power_of_two);
+
+  // ---------------------------------------------------------------------------
+  // Bit testing/extraction
+  //
+  // Bit numbering is such that the least significant bit is bit 0
+  // (for consistency between 32/64-bit).
+
+  // Extract consecutive bits (defined by rangeStart - rangeEnd) from src
+  // and place them into the least significant bits of dst.
+  inline void ExtractBitRange(Register dst, Register src,
+                              int rangeStart, int rangeEnd,
+                              RCBit rc = LeaveRC) {
+    ASSERT(rangeStart >= rangeEnd && rangeStart < kBitsPerPointer);
+    int rotate = (rangeEnd == 0) ? 0 : kBitsPerPointer - rangeEnd;
+    int width  = rangeStart - rangeEnd + 1;
+#if V8_TARGET_ARCH_PPC64
+    rldicl(dst, src, rotate, kBitsPerPointer - width, rc);
+#else
+    rlwinm(dst, src, rotate, kBitsPerPointer - width, kBitsPerPointer - 1, rc);
+#endif
+  }
+
+  inline void ExtractBit(Register dst, Register src, uint32_t bitNumber,
+                         RCBit rc = LeaveRC) {
+    ExtractBitRange(dst, src, bitNumber, bitNumber, rc);
+  }
+
+  // Extract consecutive bits (defined by mask) from src and place them
+  // into the least significant bits of dst.
+  inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
+                             RCBit rc = LeaveRC) {
+    int start = kBitsPerPointer - 1;
+    int end;
+    uintptr_t bit = (1L << start);
+
+    while (bit && (mask & bit) == 0) {
+        start--;
+        bit >>= 1;
+    }
+    end = start;
+    bit >>= 1;
+
+    while (bit && (mask & bit)) {
+        end--;
+        bit >>= 1;
+    }
+
+    // 1-bits in mask must be contiguous
+    ASSERT(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
+
+    ExtractBitRange(dst, src, start, end, rc);
+  }
+
+  // Test single bit in value.
+  inline void TestBit(Register value, int bitNumber,
+                      Register scratch = r0) {
+    ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC);
+  }
+
+  // Test consecutive bit range in value.  Range is defined by
+  // rangeStart - rangeEnd.
+  inline void TestBitRange(Register value,
+                           int rangeStart, int rangeEnd,
+                           Register scratch = r0) {
+    ExtractBitRange(scratch, value, rangeStart, rangeEnd, SetRC);
+  }
+
+  // Test consecutive bit range in value.  Range is defined by mask.
+  inline void TestBitMask(Register value, uintptr_t mask,
+                          Register scratch = r0) {
+    ExtractBitMask(scratch, value, mask, SetRC);
+  }
+
+  inline void ExtractSignBit(Register dst, Register src,
+                             RCBit rc = LeaveRC) {
+    const int bitNumber = kBitsPerPointer - 1;
+    ExtractBitRange(dst, src, bitNumber, bitNumber, rc);
+  }
+
+  inline void ExtractSignBit32(Register dst, Register src,
+                               RCBit rc = LeaveRC) {
+    const int bitNumber = 31;
+    ExtractBitRange(dst, src, bitNumber, bitNumber, rc);
+  }
+
+  inline void TestSignBit(Register value,
+                          Register scratch = r0) {
+    const int bitNumber = kBitsPerPointer - 1;
+    ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC);
+  }
+
+  inline void TestSignBit32(Register value,
+                            Register scratch = r0) {
+    const int bitNumber = 31;
+    ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC);
+  }
+
+
+  // ---------------------------------------------------------------------------
+  // Smi utilities
+
+  // Shift left by 1
+  void SmiTag(Register reg, RCBit rc = LeaveRC) {
+    SmiTag(reg, reg, rc);
+  }
+  void SmiTag(Register dst, Register src, RCBit rc = LeaveRC) {
+    ShiftLeftImm(dst, src, Operand(kSmiShift), rc);
+  }
+
+#if !V8_TARGET_ARCH_PPC64
+  // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
+  void SmiTagCheckOverflow(Register reg, Register overflow);
+  void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
+
+  inline void JumpIfNotSmiCandidate(Register value, Register scratch,
+                                    Label* not_smi_label) {
+    // High bits must be identical to fit into an Smi
+    addis(scratch, value, Operand(0x40000000u >> 16));
+    cmpi(scratch, Operand::Zero());
+    blt(not_smi_label);
+  }
+#endif
+  inline void JumpIfNotUnsignedSmiCandidate(Register value, Register scratch,
+                                            Label* not_smi_label) {
+    // The test is different for unsigned int values. Since we need
+    // the value to be in the range of a positive smi, we can't
+    // handle any of the high bits being set in the value.
+    TestBitRange(value,
+                 kBitsPerPointer - 1,
+                 kBitsPerPointer - 1 - kSmiShift,
+                 scratch);
+    bne(not_smi_label, cr0);
+  }
+
+  void SmiUntag(Register reg, RCBit rc = LeaveRC) {
+    SmiUntag(reg, reg, rc);
+  }
+
+  void SmiUntag(Register dst, Register src, RCBit rc = LeaveRC) {
+    ShiftRightArithImm(dst, src, kSmiShift, rc);
+  }
+
+  void SmiToPtrArrayOffset(Register dst, Register src) {
+#if V8_TARGET_ARCH_PPC64
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kPointerSizeLog2);
+    ShiftRightArithImm(dst, src, kSmiShift - kPointerSizeLog2);
+#else
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kPointerSizeLog2);
+    ShiftLeftImm(dst, src, Operand(kPointerSizeLog2 - kSmiShift));
+#endif
+  }
+
+  void SmiToByteArrayOffset(Register dst, Register src) {
+    SmiUntag(dst, src);
+  }
+
+  void SmiToShortArrayOffset(Register dst, Register src) {
+#if V8_TARGET_ARCH_PPC64
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 1);
+    ShiftRightArithImm(dst, src, kSmiShift - 1);
+#else
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift == 1);
+    if (!dst.is(src)) {
+      mr(dst, src);
+    }
+#endif
+  }
+
+  void SmiToIntArrayOffset(Register dst, Register src) {
+#if V8_TARGET_ARCH_PPC64
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 2);
+    ShiftRightArithImm(dst, src, kSmiShift - 2);
+#else
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift < 2);
+    ShiftLeftImm(dst, src, Operand(2 - kSmiShift));
+#endif
+  }
+
+#define SmiToFloatArrayOffset SmiToIntArrayOffset
+
+  void SmiToDoubleArrayOffset(Register dst, Register src) {
+#if V8_TARGET_ARCH_PPC64
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kDoubleSizeLog2);
+    ShiftRightArithImm(dst, src, kSmiShift - kDoubleSizeLog2);
+#else
+    STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kDoubleSizeLog2);
+    ShiftLeftImm(dst, src, Operand(kDoubleSizeLog2 - kSmiShift));
+#endif
+  }
+
+  void SmiToArrayOffset(Register dst, Register src, int elementSizeLog2) {
+    if (kSmiShift < elementSizeLog2) {
+      ShiftLeftImm(dst, src, Operand(elementSizeLog2 - kSmiShift));
+    } else if (kSmiShift > elementSizeLog2) {
+      ShiftRightArithImm(dst, src, kSmiShift - elementSizeLog2);
+    } else if (!dst.is(src)) {
+      mr(dst, src);
+    }
+  }
+
+  void IndexToArrayOffset(Register dst, Register src, int elementSizeLog2,
+                          bool isSmi) {
+    if (isSmi) {
+      SmiToArrayOffset(dst, src, elementSizeLog2);
+    } else {
+      ShiftLeftImm(dst, src, Operand(elementSizeLog2));
+    }
+  }
+
+  // Untag the source value into destination and jump if source is a smi.
+  // Souce and destination can be the same register.
+  void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
+
+  // Untag the source value into destination and jump if source is not a smi.
+  // Souce and destination can be the same register.
+  void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
+
+  inline void TestIfSmi(Register value, Register scratch) {
+    TestBit(value, 0, scratch);  // tst(value, Operand(kSmiTagMask));
+  }
+
+  inline void TestIfPositiveSmi(Register value, Register scratch) {
+    STATIC_ASSERT((kSmiTagMask | kSmiSignMask) ==
+                  (intptr_t)(1UL << (kBitsPerPointer - 1) | 1));
+#if V8_TARGET_ARCH_PPC64
+    rldicl(scratch, value, 1, kBitsPerPointer - 2, SetRC);
+#else
+    rlwinm(scratch, value, 1, kBitsPerPointer - 2, kBitsPerPointer - 1, SetRC);
+#endif
+  }
+
+  // Jump the register contains a smi.
+  inline void JumpIfSmi(Register value, Label* smi_label) {
+    TestIfSmi(value, r0);
+    beq(smi_label, cr0);  // branch if SMI
+  }
+  // Jump if either of the registers contain a non-smi.
+  inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
+    TestIfSmi(value, r0);
+    bne(not_smi_label, cr0);
+  }
+  // Jump if either of the registers contain a non-smi.
+  void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
+  // Jump if either of the registers contain a smi.
+  void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
+
+  // Abort execution if argument is a smi, enabled via --debug-code.
+  void AssertNotSmi(Register object);
+  void AssertSmi(Register object);
+
+
+#if V8_TARGET_ARCH_PPC64
+  inline void TestIfInt32(Register value,
+                          Register scratch1, Register scratch2,
+                          CRegister cr = cr7) {
+    // High bits must be identical to fit into an 32-bit integer
+    srawi(scratch1, value, 31);
+    sradi(scratch2, value, 32);
+    cmp(scratch1, scratch2, cr);
+  }
+#else
+  inline void TestIfInt32(Register hi_word, Register lo_word,
+                          Register scratch, CRegister cr = cr7) {
+    // High bits must be identical to fit into an 32-bit integer
+    srawi(scratch, lo_word, 31);
+    cmp(scratch, hi_word, cr);
+  }
+#endif
+
+  // Abort execution if argument is not a string, enabled via --debug-code.
+  void AssertString(Register object);
+
+  // Abort execution if argument is not the root value with the given index.
+  void AssertRootValue(Register src,
+                       Heap::RootListIndex root_value_index,
+                       const char* message);
+
+  // ---------------------------------------------------------------------------
+  // HeapNumber utilities
+
+  void JumpIfNotHeapNumber(Register object,
+                           Register heap_number_map,
+                           Register scratch,
+                           Label* on_not_heap_number);
+
+  // ---------------------------------------------------------------------------
+  // String utilities
+
+  // Checks if both objects are sequential ASCII strings and jumps to label
+  // if either is not. Assumes that neither object is a smi.
+  void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
+                                                  Register object2,
+                                                  Register scratch1,
+                                                  Register scratch2,
+                                                  Label* failure);
+
+  // Checks if both objects are sequential ASCII strings and jumps to label
+  // if either is not.
+  void JumpIfNotBothSequentialAsciiStrings(Register first,
+                                           Register second,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Label* not_flat_ascii_strings);
+
+  // Checks if both instance types are sequential ASCII strings and jumps to
+  // label if either is not.
+  void JumpIfBothInstanceTypesAreNotSequentialAscii(
+      Register first_object_instance_type,
+      Register second_object_instance_type,
+      Register scratch1,
+      Register scratch2,
+      Label* failure);
+
+  // Check if instance type is sequential ASCII string and jump to label if
+  // it is not.
+  void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
+                                              Register scratch,
+                                              Label* failure);
+
+
+  // ---------------------------------------------------------------------------
+  // Patching helpers.
+
+  // Patch the relocated value (lis/ori pair).
+  void PatchRelocatedValue(Register lis_location,
+                           Register scratch,
+                           Register new_value);
+  // Get the relocatad value (loaded data) from the lis/ori pair.
+  void GetRelocatedValueLocation(Register lis_location,
+                                 Register result,
+                                 Register scratch);
+
+  void ClampUint8(Register output_reg, Register input_reg);
+
+  // Saturate a value into 8-bit unsigned integer
+  //   if input_value < 0, output_value is 0
+  //   if input_value > 255, output_value is 255
+  //   otherwise output_value is the (int)input_value (round to nearest)
+  void ClampDoubleToUint8(Register result_reg,
+                          DoubleRegister input_reg,
+                          DoubleRegister temp_double_reg,
+                          DoubleRegister temp_double_reg2);
+
+
+  void LoadInstanceDescriptors(Register map, Register descriptors);
+  void EnumLength(Register dst, Register map);
+  void NumberOfOwnDescriptors(Register dst, Register map);
+
+  template<typename Field>
+  void DecodeField(Register reg) {
+    uintptr_t mask = reinterpret_cast<intptr_t>(Smi::FromInt(Field::kMask));
+    ExtractBitMask(reg, reg, mask);
+    SmiTag(reg);
+  }
+
+  // Activation support.
+  void EnterFrame(StackFrame::Type type);
+  void LeaveFrame(StackFrame::Type type);
+
+  // Expects object in r0 and returns map with validated enum cache
+  // in r0.  Assumes that any other register can be used as a scratch.
+  void CheckEnumCache(Register null_value, Label* call_runtime);
+
+ private:
+  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
+
+  void CallCFunctionHelper(Register function,
+                           int num_reg_arguments,
+                           int num_double_arguments);
+
+  void Jump(intptr_t target, RelocInfo::Mode rmode,
+            Condition cond = al, CRegister cr = cr7);
+
+  // Helper functions for generating invokes.
+  void InvokePrologue(const ParameterCount& expected,
+                      const ParameterCount& actual,
+                      Handle<Code> code_constant,
+                      Register code_reg,
+                      Label* done,
+                      bool* definitely_mismatches,
+                      InvokeFlag flag,
+                      const CallWrapper& call_wrapper,
+                      CallKind call_kind);
+
+  void InitializeNewString(Register string,
+                           Register length,
+                           Heap::RootListIndex map_index,
+                           Register scratch1,
+                           Register scratch2);
+
+  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
+  void InNewSpace(Register object,
+                  Register scratch,
+                  Condition cond,  // eq for new space, ne otherwise.
+                  Label* branch);
+
+  // Helper for finding the mark bits for an address.  Afterwards, the
+  // bitmap register points at the word with the mark bits and the mask
+  // the position of the first bit.  Leaves addr_reg unchanged.
+  inline void GetMarkBits(Register addr_reg,
+                          Register bitmap_reg,
+                          Register mask_reg);
+
+  // Helper for throwing exceptions.  Compute a handler address and jump to
+  // it.  See the implementation for register usage.
+  void JumpToHandlerEntry();
+
+  // Compute memory operands for safepoint stack slots.
+  static int SafepointRegisterStackIndex(int reg_code);
+  MemOperand SafepointRegisterSlot(Register reg);
+  MemOperand SafepointRegistersAndDoublesSlot(Register reg);
+
+  bool generating_stub_;
+  bool allow_stub_calls_;
+  bool has_frame_;
+  // This handle will be patched with the code object on installation.
+  Handle<Object> code_object_;
+
+  // Needs access to SafepointRegisterStackIndex for optimized frame
+  // traversal.
+  friend class OptimizedFrame;
+};
+
+
+// The code patcher is used to patch (typically) small parts of code e.g. for
+// debugging and other types of instrumentation. When using the code patcher
+// the exact number of bytes specified must be emitted. It is not legal to emit
+// relocation information. If any of these constraints are violated it causes
+// an assertion to fail.
+class CodePatcher {
+ public:
+  CodePatcher(byte* address, int instructions);
+  virtual ~CodePatcher();
+
+  // Macro assembler to emit code.
+  MacroAssembler* masm() { return &masm_; }
+
+  // Emit an instruction directly.
+  void Emit(Instr instr);
+
+  // Emit the condition part of an instruction leaving the rest of the current
+  // instruction unchanged.
+  void EmitCondition(Condition cond);
+
+ private:
+  byte* address_;  // The address of the code being patched.
+  int instructions_;  // Number of instructions of the expected patch size.
+  int size_;  // Number of bytes of the expected patch size.
+  MacroAssembler masm_;  // Macro assembler used to generate the code.
+};
+
+
+// -----------------------------------------------------------------------------
+// Static helper functions.
+
+inline MemOperand ContextOperand(Register context, int index) {
+  return MemOperand(context, Context::SlotOffset(index));
+}
+
+
+inline MemOperand GlobalObjectOperand()  {
+  return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX);
+}
+
+
+#ifdef GENERATED_CODE_COVERAGE
+#define CODE_COVERAGE_STRINGIFY(x) #x
+#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
+#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
+#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
+#else
+#define ACCESS_MASM(masm) masm->
+#endif
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_PPC_MACRO_ASSEMBLER_PPC_H_
diff --git a/src/ppc/regexp-macro-assembler-ppc.cc b/src/ppc/regexp-macro-assembler-ppc.cc
new file mode 100644
index 0000000..d041593
--- /dev/null
+++ b/src/ppc/regexp-macro-assembler-ppc.cc
@@ -0,0 +1,1464 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "unicode.h"
+#include "log.h"
+#include "code-stubs.h"
+#include "regexp-stack.h"
+#include "macro-assembler.h"
+#include "regexp-macro-assembler.h"
+#include "ppc/regexp-macro-assembler-ppc.h"
+
+namespace v8 {
+namespace internal {
+
+#ifndef V8_INTERPRETED_REGEXP
+/*
+ * This assembler uses the following register assignment convention
+ * - r25: Temporarily stores the index of capture start after a matching pass
+ *        for a global regexp.
+ * - r26: Pointer to current code object (Code*) including heap object tag.
+ * - r27: Current position in input, as negative offset from end of string.
+ *        Please notice that this is the byte offset, not the character offset!
+ * - r28: Currently loaded character. Must be loaded using
+ *        LoadCurrentCharacter before using any of the dispatch methods.
+ * - r29: Points to tip of backtrack stack
+ * - r30: End of input (points to byte after last character in input).
+ * - r31: Frame pointer. Used to access arguments, local variables and
+ *         RegExp registers.
+ * - r12: IP register, used by assembler. Very volatile.
+ * - r1/sp : Points to tip of C stack.
+ *
+ * The remaining registers are free for computations.
+ * Each call to a public method should retain this convention.
+ *
+ * The stack will have the following structure:
+ *  - fp[44]  Isolate* isolate   (address of the current isolate)
+ *  - fp[40]  secondary link/return address used by native call.
+ *  - fp[36]  lr save area (currently unused)
+ *  - fp[32]  backchain    (currently unused)
+ *  --- sp when called ---
+ *  - fp[28]  return address     (lr).
+ *  - fp[24]  old frame pointer  (r31).
+ *  - fp[0..20]  backup of registers r25..r30
+ *  --- frame pointer ----
+ *  - fp[-4]  direct_call        (if 1, direct call from JavaScript code,
+ *                                if 0, call through the runtime system).
+ *  - fp[-8]  stack_area_base    (high end of the memory area to use as
+ *                                backtracking stack).
+ *  - fp[-12] capture array size (may fit multiple sets of matches)
+ *  - fp[-16] int* capture_array (int[num_saved_registers_], for output).
+ *  - fp[-20] end of input       (address of end of string).
+ *  - fp[-24] start of input     (address of first character in string).
+ *  - fp[-28] start index        (character index of start).
+ *  - fp[-32] void* input_string (location of a handle containing the string).
+ *  - fp[-36] success counter    (only for global regexps to count matches).
+ *  - fp[-40] Offset of location before start of input (effectively character
+ *            position -1). Used to initialize capture registers to a
+ *            non-position.
+ *  - fp[-44] At start (if 1, we are starting at the start of the
+ *    string, otherwise 0)
+ *  - fp[-48] register 0         (Only positions must be stored in the first
+ *  -         register 1          num_saved_registers_ registers)
+ *  -         ...
+ *  -         register num_registers-1
+ *  --- sp ---
+ *
+ * The first num_saved_registers_ registers are initialized to point to
+ * "character -1" in the string (i.e., char_size() bytes before the first
+ * character of the string). The remaining registers start out as garbage.
+ *
+ * The data up to the return address must be placed there by the calling
+ * code and the remaining arguments are passed in registers, e.g. by calling the
+ * code entry as cast to a function with the signature:
+ * int (*match)(String* input_string,
+ *              int start_index,
+ *              Address start,
+ *              Address end,
+ *              int* capture_output_array,
+ *              byte* stack_area_base,
+ *              Address secondary_return_address,  // Only used by native call.
+ *              bool direct_call = false)
+ * The call is performed by NativeRegExpMacroAssembler::Execute()
+ * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
+ * in ppc/simulator-ppc.h.
+ * When calling as a non-direct call (i.e., from C++ code), the return address
+ * area is overwritten with the LR register by the RegExp code. When doing a
+ * direct call from generated code, the return address is placed there by
+ * the calling code, as in a normal exit frame.
+ */
+
+#define __ ACCESS_MASM(masm_)
+
+RegExpMacroAssemblerPPC::RegExpMacroAssemblerPPC(
+    Mode mode,
+    int registers_to_save,
+    Zone* zone)
+    : NativeRegExpMacroAssembler(zone),
+      masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)),
+      mode_(mode),
+      num_registers_(registers_to_save),
+      num_saved_registers_(registers_to_save),
+      entry_label_(),
+      start_label_(),
+      success_label_(),
+      backtrack_label_(),
+      exit_label_(),
+      internal_failure_label_() {
+  ASSERT_EQ(0, registers_to_save % 2);
+
+  // Called from C
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+
+  __ b(&entry_label_);   // We'll write the entry code later.
+  // If the code gets too big or corrupted, an internal exception will be
+  // raised, and we will exit right away.
+  __ bind(&internal_failure_label_);
+  __ li(r3, Operand(FAILURE));
+  __ Ret();
+  __ bind(&start_label_);  // And then continue from here.
+}
+
+
+RegExpMacroAssemblerPPC::~RegExpMacroAssemblerPPC() {
+  delete masm_;
+  // Unuse labels in case we throw away the assembler without calling GetCode.
+  entry_label_.Unuse();
+  start_label_.Unuse();
+  success_label_.Unuse();
+  backtrack_label_.Unuse();
+  exit_label_.Unuse();
+  check_preempt_label_.Unuse();
+  stack_overflow_label_.Unuse();
+  internal_failure_label_.Unuse();
+}
+
+
+int RegExpMacroAssemblerPPC::stack_limit_slack()  {
+  return RegExpStack::kStackLimitSlack;
+}
+
+
+void RegExpMacroAssemblerPPC::AdvanceCurrentPosition(int by) {
+  if (by != 0) {
+    __ addi(current_input_offset(),
+            current_input_offset(), Operand(by * char_size()));
+  }
+}
+
+
+void RegExpMacroAssemblerPPC::AdvanceRegister(int reg, int by) {
+  ASSERT(reg >= 0);
+  ASSERT(reg < num_registers_);
+  if (by != 0) {
+    __ LoadP(r3, register_location(reg), r0);
+    __ mov(r0, Operand(by));
+    __ add(r3, r3, r0);
+    __ StoreP(r3, register_location(reg), r0);
+  }
+}
+
+
+void RegExpMacroAssemblerPPC::Backtrack() {
+  CheckPreemption();
+  // Pop Code* offset from backtrack stack, add Code* and jump to location.
+  Pop(r3);
+  __ add(r3, r3, code_pointer());
+  __ mtctr(r3);
+  __ bcr();
+}
+
+
+void RegExpMacroAssemblerPPC::Bind(Label* label) {
+  __ bind(label);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckCharacter(uint32_t c, Label* on_equal) {
+  __ Cmpli(current_character(), Operand(c), r0);
+  BranchOrBacktrack(eq, on_equal);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckCharacterGT(uc16 limit, Label* on_greater) {
+  __ Cmpli(current_character(), Operand(limit), r0);
+  BranchOrBacktrack(gt, on_greater);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckAtStart(Label* on_at_start) {
+  Label not_at_start;
+  // Did we start the match at the start of the string at all?
+  __ LoadP(r3, MemOperand(frame_pointer(), kStartIndex));
+  __ cmpi(r3, Operand::Zero());
+  BranchOrBacktrack(ne, &not_at_start);
+
+  // If we did, are we still at the start of the input?
+  __ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
+  __ mr(r0, current_input_offset());
+  __ add(r3, end_of_input_address(), r0);
+  __ cmp(r4, r3);
+  BranchOrBacktrack(eq, on_at_start);
+  __ bind(&not_at_start);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckNotAtStart(Label* on_not_at_start) {
+  // Did we start the match at the start of the string at all?
+  __ LoadP(r3, MemOperand(frame_pointer(), kStartIndex));
+  __ cmpi(r3, Operand::Zero());
+  BranchOrBacktrack(ne, on_not_at_start);
+  // If we did, are we still at the start of the input?
+  __ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
+  __ add(r3, end_of_input_address(), current_input_offset());
+  __ cmp(r3, r4);
+  BranchOrBacktrack(ne, on_not_at_start);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckCharacterLT(uc16 limit, Label* on_less) {
+  __ Cmpli(current_character(), Operand(limit), r0);
+  BranchOrBacktrack(lt, on_less);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckCharacters(Vector<const uc16> str,
+                                              int cp_offset,
+                                              Label* on_failure,
+                                              bool check_end_of_string) {
+  if (on_failure == NULL) {
+    // Instead of inlining a backtrack for each test, (re)use the global
+    // backtrack target.
+    on_failure = &backtrack_label_;
+  }
+
+  if (check_end_of_string) {
+    // Is last character of required match inside string.
+    CheckPosition(cp_offset + str.length() - 1, on_failure);
+  }
+
+  __ add(r3, end_of_input_address(), current_input_offset());
+  if (cp_offset != 0) {
+    int byte_offset = cp_offset * char_size();
+    __ addi(r3, r3, Operand(byte_offset));
+  }
+
+  // r3 : Address of characters to match against str.
+  int stored_high_byte = 0;
+  for (int i = 0; i < str.length(); i++) {
+    if (mode_ == ASCII) {
+      __ lbz(r4, MemOperand(r3));
+      __ addi(r3, r3, Operand(char_size()));
+      ASSERT(str[i] <= String::kMaxAsciiCharCode);
+      __ cmpi(r4, Operand(str[i]));
+    } else {
+      __ lhz(r4, MemOperand(r3));
+      __ addi(r3, r3, Operand(char_size()));
+      uc16 match_char = str[i];
+      int match_high_byte = (match_char >> 8);
+      if (match_high_byte == 0) {
+        __ cmpi(r4, Operand(str[i]));
+      } else {
+        if (match_high_byte != stored_high_byte) {
+          __ li(r5, Operand(match_high_byte));
+          stored_high_byte = match_high_byte;
+        }
+        __ addi(r6, r5, Operand(match_char & 0xff));
+        __ cmp(r4, r6);
+      }
+    }
+    BranchOrBacktrack(ne, on_failure);
+  }
+}
+
+
+void RegExpMacroAssemblerPPC::CheckGreedyLoop(Label* on_equal) {
+  Label backtrack_non_equal;
+  __ LoadP(r3, MemOperand(backtrack_stackpointer(), 0));
+  __ cmp(current_input_offset(), r3);
+  __ bne(&backtrack_non_equal);
+  __ addi(backtrack_stackpointer(),
+         backtrack_stackpointer(), Operand(kPointerSize));
+
+  __ bind(&backtrack_non_equal);
+  BranchOrBacktrack(eq, on_equal);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
+    int start_reg,
+    Label* on_no_match) {
+  Label fallthrough;
+  __ LoadP(r3, register_location(start_reg), r0);  // Index of start of capture
+  __ LoadP(r4, register_location(start_reg + 1), r0);  // Index of end
+  __ sub(r4, r4, r3, LeaveOE, SetRC);  // Length of capture.
+
+  // If length is zero, either the capture is empty or it is not participating.
+  // In either case succeed immediately.
+  __ beq(&fallthrough, cr0);
+
+  // Check that there are enough characters left in the input.
+  __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
+//  __ cmn(r1, Operand(current_input_offset()));
+  BranchOrBacktrack(gt, on_no_match, cr0);
+
+  if (mode_ == ASCII) {
+    Label success;
+    Label fail;
+    Label loop_check;
+
+    // r3 - offset of start of capture
+    // r4 - length of capture
+    __ add(r3, r3, end_of_input_address());
+    __ add(r5, end_of_input_address(), current_input_offset());
+    __ add(r4, r3, r4);
+
+    // r3 - Address of start of capture.
+    // r4 - Address of end of capture
+    // r5 - Address of current input position.
+
+    Label loop;
+    __ bind(&loop);
+    __ lbz(r6, MemOperand(r3));
+    __ addi(r3, r3, Operand(char_size()));
+    __ lbz(r25, MemOperand(r5));
+    __ addi(r5, r5, Operand(char_size()));
+    __ cmp(r25, r6);
+    __ beq(&loop_check);
+
+    // Mismatch, try case-insensitive match (converting letters to lower-case).
+    __ ori(r6, r6, Operand(0x20));  // Convert capture character to lower-case.
+    __ ori(r25, r25, Operand(0x20));  // Also convert input character.
+    __ cmp(r25, r6);
+    __ bne(&fail);
+    __ subi(r6, r6, Operand('a'));
+    __ cmpli(r6, Operand('z' - 'a'));  // Is r6 a lowercase letter?
+    __ bgt(&fail);
+
+
+    __ bind(&loop_check);
+    __ cmp(r3, r4);
+    __ blt(&loop);
+    __ b(&success);
+
+    __ bind(&fail);
+    BranchOrBacktrack(al, on_no_match);
+
+    __ bind(&success);
+    // Compute new value of character position after the matched part.
+    __ sub(current_input_offset(), r5, end_of_input_address());
+  } else {
+    ASSERT(mode_ == UC16);
+    int argument_count = 4;
+    __ PrepareCallCFunction(argument_count, r5);
+
+    // r3 - offset of start of capture
+    // r4 - length of capture
+
+    // Put arguments into arguments registers.
+    // Parameters are
+    //   r3: Address byte_offset1 - Address captured substring's start.
+    //   r4: Address byte_offset2 - Address of current character position.
+    //   r5: size_t byte_length - length of capture in bytes(!)
+    //   r6: Isolate* isolate
+
+    // Address of start of capture.
+    __ add(r3, r3, end_of_input_address());
+    // Length of capture.
+    __ mr(r5, r4);
+    // Save length in callee-save register for use on return.
+    __ mr(r25, r4);
+    // Address of current input position.
+    __ add(r4, current_input_offset(), end_of_input_address());
+    // Isolate.
+    __ mov(r6, Operand(ExternalReference::isolate_address()));
+
+    {
+      AllowExternalCallThatCantCauseGC scope(masm_);
+      ExternalReference function =
+          ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
+      __ CallCFunction(function, argument_count);
+    }
+
+    // Check if function returned non-zero for success or zero for failure.
+    __ cmpi(r3, Operand::Zero());
+    BranchOrBacktrack(eq, on_no_match);
+    // On success, increment position by length of capture.
+    __ add(current_input_offset(), current_input_offset(), r25);
+  }
+
+  __ bind(&fallthrough);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckNotBackReference(
+    int start_reg,
+    Label* on_no_match) {
+  Label fallthrough;
+  Label success;
+
+  // Find length of back-referenced capture.
+  __ LoadP(r3, register_location(start_reg), r0);
+  __ LoadP(r4, register_location(start_reg + 1), r0);
+  __ sub(r4, r4, r3, LeaveOE, SetRC);  // Length to check.
+  // Succeed on empty capture (including no capture).
+  __ beq(&fallthrough, cr0);
+
+  // Check that there are enough characters left in the input.
+  __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
+  BranchOrBacktrack(gt, on_no_match, cr0);
+
+  // Compute pointers to match string and capture string
+  __ add(r3, r3, end_of_input_address());
+  __ add(r5, end_of_input_address(), current_input_offset());
+  __ add(r4, r4, r3);
+
+  Label loop;
+  __ bind(&loop);
+  if (mode_ == ASCII) {
+    __ lbz(r6, MemOperand(r3));
+    __ addi(r3, r3, Operand(char_size()));
+    __ lbz(r25, MemOperand(r5));
+    __ addi(r5, r5, Operand(char_size()));
+  } else {
+    ASSERT(mode_ == UC16);
+    __ lhz(r6, MemOperand(r3));
+    __ addi(r3, r3, Operand(char_size()));
+    __ lhz(r25, MemOperand(r5));
+    __ addi(r5, r5, Operand(char_size()));
+  }
+  __ cmp(r6, r25);
+  BranchOrBacktrack(ne, on_no_match);
+  __ cmp(r3, r4);
+  __ blt(&loop);
+
+  // Move current character position to position after match.
+  __ sub(current_input_offset(), r5, end_of_input_address());
+  __ bind(&fallthrough);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckNotCharacter(unsigned c,
+                                                Label* on_not_equal) {
+  __ Cmpli(current_character(), Operand(c), r0);
+  BranchOrBacktrack(ne, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckCharacterAfterAnd(uint32_t c,
+                                                     uint32_t mask,
+                                                     Label* on_equal) {
+  __ mov(r0, Operand(mask));
+  if (c == 0) {
+    __ and_(r3, current_character(), r0, SetRC);
+  } else {
+    __ and_(r3, current_character(), r0);
+    __ Cmpli(r3, Operand(c), r0, cr0);
+  }
+  BranchOrBacktrack(eq, on_equal, cr0);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckNotCharacterAfterAnd(unsigned c,
+                                                        unsigned mask,
+                                                        Label* on_not_equal) {
+  __ mov(r0, Operand(mask));
+  if (c == 0) {
+    __ and_(r3, current_character(), r0, SetRC);
+  } else {
+    __ and_(r3, current_character(), r0);
+    __ Cmpli(r3, Operand(c), r0, cr0);
+  }
+  BranchOrBacktrack(ne, on_not_equal, cr0);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckNotCharacterAfterMinusAnd(
+    uc16 c,
+    uc16 minus,
+    uc16 mask,
+    Label* on_not_equal) {
+  ASSERT(minus < String::kMaxUtf16CodeUnit);
+  __ subi(r3, current_character(), Operand(minus));
+  __ mov(r0, Operand(mask));
+  __ and_(r3, r3, r0);
+  __ Cmpli(r3, Operand(c), r0);
+  BranchOrBacktrack(ne, on_not_equal);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckCharacterInRange(
+    uc16 from,
+    uc16 to,
+    Label* on_in_range) {
+  __ mov(r0, Operand(from));
+  __ sub(r3, current_character(), r0);
+  __ Cmpli(r3, Operand(to - from), r0);
+  BranchOrBacktrack(le, on_in_range);  // Unsigned lower-or-same condition.
+}
+
+
+void RegExpMacroAssemblerPPC::CheckCharacterNotInRange(
+    uc16 from,
+    uc16 to,
+    Label* on_not_in_range) {
+  __ mov(r0, Operand(from));
+  __ sub(r3, current_character(), r0);
+  __ Cmpli(r3, Operand(to - from), r0);
+  BranchOrBacktrack(gt, on_not_in_range);  // Unsigned higher condition.
+}
+
+
+void RegExpMacroAssemblerPPC::CheckBitInTable(
+    Handle<ByteArray> table,
+    Label* on_bit_set) {
+  __ mov(r3, Operand(table));
+  if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
+    __ andi(r4, current_character(), Operand(kTableSize - 1));
+    __ addi(r4, r4, Operand(ByteArray::kHeaderSize - kHeapObjectTag));
+  } else {
+    __ addi(r4,
+            current_character(),
+            Operand(ByteArray::kHeaderSize - kHeapObjectTag));
+  }
+  __ lbzx(r3, MemOperand(r3, r4));
+  __ cmpi(r3, Operand::Zero());
+  BranchOrBacktrack(ne, on_bit_set);
+}
+
+
+bool RegExpMacroAssemblerPPC::CheckSpecialCharacterClass(uc16 type,
+                                                         Label* on_no_match) {
+  // Range checks (c in min..max) are generally implemented by an unsigned
+  // (c - min) <= (max - min) check
+  switch (type) {
+  case 's':
+    // Match space-characters
+    if (mode_ == ASCII) {
+      // ASCII space characters are '\t'..'\r' and ' '.
+      Label success;
+      __ cmpi(current_character(), Operand(' '));
+      __ beq(&success);
+      // Check range 0x09..0x0d
+      __ subi(r3, current_character(), Operand('\t'));
+      __ cmpli(r3, Operand('\r' - '\t'));
+      BranchOrBacktrack(gt, on_no_match);
+      __ bind(&success);
+      return true;
+    }
+    return false;
+  case 'S':
+    // Match non-space characters.
+    if (mode_ == ASCII) {
+      // ASCII space characters are '\t'..'\r' and ' '.
+      __ cmpi(current_character(), Operand(' '));
+      BranchOrBacktrack(eq, on_no_match);
+      __ subi(r3, current_character(), Operand('\t'));
+      __ cmpli(r3, Operand('\r' - '\t'));
+      BranchOrBacktrack(le, on_no_match);
+      return true;
+    }
+    return false;
+  case 'd':
+    // Match ASCII digits ('0'..'9')
+    __ subi(r3, current_character(), Operand('0'));
+    __ cmpli(current_character(), Operand('9' - '0'));
+    BranchOrBacktrack(gt, on_no_match);
+    return true;
+  case 'D':
+    // Match non ASCII-digits
+    __ subi(r3, current_character(), Operand('0'));
+    __ cmpli(r3, Operand('9' - '0'));
+    BranchOrBacktrack(le, on_no_match);
+    return true;
+  case '.': {
+    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
+    __ xori(r3, current_character(), Operand(0x01));
+    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
+    __ subi(r3, r3, Operand(0x0b));
+    __ cmpli(r3, Operand(0x0c - 0x0b));
+    BranchOrBacktrack(le, on_no_match);
+    if (mode_ == UC16) {
+      // Compare original value to 0x2028 and 0x2029, using the already
+      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
+      // 0x201d (0x2028 - 0x0b) or 0x201e.
+      __ subi(r3, r3, Operand(0x2028 - 0x0b));
+      __ cmpli(r3, Operand(1));
+      BranchOrBacktrack(le, on_no_match);
+    }
+    return true;
+  }
+  case 'n': {
+    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
+    __ xori(r3, current_character(), Operand(0x01));
+    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
+    __ subi(r3, r3, Operand(0x0b));
+    __ cmpli(r3, Operand(0x0c - 0x0b));
+    if (mode_ == ASCII) {
+      BranchOrBacktrack(gt, on_no_match);
+    } else {
+      Label done;
+      __ ble(&done);
+      // Compare original value to 0x2028 and 0x2029, using the already
+      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
+      // 0x201d (0x2028 - 0x0b) or 0x201e.
+      __ subi(r3, r3, Operand(0x2028 - 0x0b));
+      __ cmpli(r3, Operand(1));
+      BranchOrBacktrack(gt, on_no_match);
+      __ bind(&done);
+    }
+    return true;
+  }
+  case 'w': {
+    if (mode_ != ASCII) {
+      // Table is 128 entries, so all ASCII characters can be tested.
+      __ cmpi(current_character(), Operand('z'));
+      BranchOrBacktrack(gt, on_no_match);
+    }
+    ExternalReference map = ExternalReference::re_word_character_map();
+    __ mov(r3, Operand(map));
+    __ lbzx(r3, MemOperand(r3, current_character()));
+    __ cmpli(r3, Operand::Zero());
+    BranchOrBacktrack(eq, on_no_match);
+    return true;
+  }
+  case 'W': {
+    Label done;
+    if (mode_ != ASCII) {
+      // Table is 128 entries, so all ASCII characters can be tested.
+      __ cmpli(current_character(), Operand('z'));
+      __ bgt(&done);
+    }
+    ExternalReference map = ExternalReference::re_word_character_map();
+    __ mov(r3, Operand(map));
+    __ lbzx(r3, MemOperand(r3, current_character()));
+    __ cmpli(r3, Operand::Zero());
+    BranchOrBacktrack(ne, on_no_match);
+    if (mode_ != ASCII) {
+      __ bind(&done);
+    }
+    return true;
+  }
+  case '*':
+    // Match any character.
+    return true;
+  // No custom implementation (yet): s(UC16), S(UC16).
+  default:
+    return false;
+  }
+}
+
+
+void RegExpMacroAssemblerPPC::Fail() {
+  __ li(r3, Operand(FAILURE));
+  __ b(&exit_label_);
+}
+
+
+Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
+  Label return_r3;
+
+  if (masm_->has_exception()) {
+    // If the code gets corrupted due to long regular expressions and lack of
+    // space on trampolines, an internal exception flag is set. If this case
+    // is detected, we will jump into exit sequence right away.
+    __ bind_to(&entry_label_, internal_failure_label_.pos());
+  } else {
+    // Finalize code - write the entry point code now we know how many
+    // registers we need.
+
+    // Entry code:
+    __ bind(&entry_label_);
+
+    // Tell the system that we have a stack frame.  Because the type
+    // is MANUAL, no is generated.
+    FrameScope scope(masm_, StackFrame::MANUAL);
+
+    // Ensure register assigments are consistent with callee save mask
+    ASSERT(r25.bit() & kRegExpCalleeSaved);
+    ASSERT(code_pointer().bit() & kRegExpCalleeSaved);
+    ASSERT(current_input_offset().bit() & kRegExpCalleeSaved);
+    ASSERT(current_character().bit() & kRegExpCalleeSaved);
+    ASSERT(backtrack_stackpointer().bit() & kRegExpCalleeSaved);
+    ASSERT(end_of_input_address().bit() & kRegExpCalleeSaved);
+    ASSERT(frame_pointer().bit() & kRegExpCalleeSaved);
+
+    // Actually emit code to start a new stack frame.
+    // Push arguments
+    // Save callee-save registers.
+    // Start new stack frame.
+    // Store link register in existing stack-cell.
+    // Order here should correspond to order of offset constants in header file.
+    RegList registers_to_retain = kRegExpCalleeSaved;
+    RegList argument_registers = r3.bit() | r4.bit() | r5.bit() | r6.bit() |
+      r7.bit() | r8.bit() | r9.bit() | r10.bit();
+    __ mflr(r0);
+    __ push(r0);
+    __ MultiPush(argument_registers | registers_to_retain);
+    // Set frame pointer in space for it if this is not a direct call
+    // from generated code.
+    __ addi(frame_pointer(), sp, Operand(8 * kPointerSize));
+    __ li(r3, Operand::Zero());
+    __ push(r3);  // Make room for success counter and initialize it to 0.
+    __ push(r3);  // Make room for "position - 1" constant (value is irrelevant)
+    // Check if we have space on the stack for registers.
+    Label stack_limit_hit;
+    Label stack_ok;
+
+    ExternalReference stack_limit =
+      ExternalReference::address_of_stack_limit(masm_->isolate());
+    __ mov(r3, Operand(stack_limit));
+    __ LoadP(r3, MemOperand(r3));
+    __ sub(r3, sp, r3, LeaveOE, SetRC);
+    // Handle it if the stack pointer is already below the stack limit.
+    __ ble(&stack_limit_hit, cr0);
+    // Check if there is room for the variable number of registers above
+    // the stack limit.
+    __ Cmpli(r3, Operand(num_registers_ * kPointerSize), r0);
+    __ bge(&stack_ok);
+    // Exit with OutOfMemory exception. There is not enough space on the stack
+    // for our working registers.
+    __ li(r3, Operand(EXCEPTION));
+    __ b(&return_r3);
+
+    __ bind(&stack_limit_hit);
+    CallCheckStackGuardState(r3);
+    __ cmpi(r3, Operand::Zero());
+    // If returned value is non-zero, we exit with the returned value as result.
+    __ bne(&return_r3);
+
+    __ bind(&stack_ok);
+
+    // Allocate space on stack for registers.
+    __ Add(sp, sp, -num_registers_ * kPointerSize, r0);
+    // Load string end.
+    __ LoadP(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
+    // Load input start.
+    __ LoadP(r3, MemOperand(frame_pointer(), kInputStart));
+    // Find negative length (offset of start relative to end).
+    __ sub(current_input_offset(), r3, end_of_input_address());
+    // Set r3 to address of char before start of the input string
+    // (effectively string position -1).
+    __ LoadP(r4, MemOperand(frame_pointer(), kStartIndex));
+    __ subi(r3, current_input_offset(), Operand(char_size()));
+    if (mode_ == UC16) {
+      __ ShiftLeftImm(r0, r4, Operand(1));
+      __ sub(r3, r3, r0);
+    } else {
+      __ sub(r3, r3, r4);
+    }
+    // Store this value in a local variable, for use when clearing
+    // position registers.
+    __ StoreP(r3, MemOperand(frame_pointer(), kInputStartMinusOne));
+
+    // Initialize code pointer register
+    __ mov(code_pointer(), Operand(masm_->CodeObject()));
+
+    Label load_char_start_regexp, start_regexp;
+    // Load newline if index is at start, previous character otherwise.
+    __ cmpi(r4, Operand::Zero());
+    __ bne(&load_char_start_regexp);
+    __ li(current_character(), Operand('\n'));
+    __ b(&start_regexp);
+
+    // Global regexp restarts matching here.
+    __ bind(&load_char_start_regexp);
+    // Load previous char as initial value of current character register.
+    LoadCurrentCharacterUnchecked(-1, 1);
+    __ bind(&start_regexp);
+
+    // Initialize on-stack registers.
+    if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
+      // Fill saved registers with initial value = start offset - 1
+      if (num_saved_registers_ > 8) {
+        // One slot beyond address of register 0.
+        __ addi(r4, frame_pointer(), Operand(kRegisterZero + kPointerSize));
+        __ li(r5, Operand(num_saved_registers_));
+        __ mtctr(r5);
+        Label init_loop;
+        __ bind(&init_loop);
+        __ StorePU(r3, MemOperand(r4, -kPointerSize));
+        __ bdnz(&init_loop);
+      } else {
+        for (int i = 0; i < num_saved_registers_; i++) {
+          __ StoreP(r3, register_location(i), r0);
+        }
+      }
+    }
+
+    // Initialize backtrack stack pointer.
+    __ LoadP(backtrack_stackpointer(),
+             MemOperand(frame_pointer(), kStackHighEnd));
+
+    __ b(&start_label_);
+
+    // Exit code:
+    if (success_label_.is_linked()) {
+      // Save captures when successful.
+      __ bind(&success_label_);
+      if (num_saved_registers_ > 0) {
+        // copy captures to output
+        __ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
+        __ LoadP(r3, MemOperand(frame_pointer(), kRegisterOutput));
+        __ LoadP(r5, MemOperand(frame_pointer(), kStartIndex));
+        __ sub(r4, end_of_input_address(), r4);
+        // r4 is length of input in bytes.
+        if (mode_ == UC16) {
+          __ ShiftRightImm(r4, r4, Operand(1));
+        }
+        // r4 is length of input in characters.
+        __ add(r4, r4, r5);
+        // r4 is length of string in characters.
+
+        ASSERT_EQ(0, num_saved_registers_ % 2);
+        // Always an even number of capture registers. This allows us to
+        // unroll the loop once to add an operation between a load of a register
+        // and the following use of that register.
+        for (int i = 0; i < num_saved_registers_; i += 2) {
+          __ LoadP(r5, register_location(i), r0);
+          __ LoadP(r6, register_location(i + 1), r0);
+          if (i == 0 && global_with_zero_length_check()) {
+            // Keep capture start in r25 for the zero-length check later.
+            __ mr(r25, r5);
+          }
+          if (mode_ == UC16) {
+            __ ShiftRightArithImm(r5, r5, 1);
+            __ add(r5, r4, r5);
+            __ ShiftRightArithImm(r6, r6, 1);
+            __ add(r6, r4, r6);
+          } else {
+            __ add(r5, r4, r5);
+            __ add(r6, r4, r6);
+          }
+          __ stw(r5, MemOperand(r3));
+          __ addi(r3, r3, Operand(kIntSize));
+          __ stw(r6, MemOperand(r3));
+          __ addi(r3, r3, Operand(kIntSize));
+        }
+      }
+
+      if (global()) {
+        // Restart matching if the regular expression is flagged as global.
+        __ LoadP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
+        __ LoadP(r4, MemOperand(frame_pointer(), kNumOutputRegisters));
+        __ LoadP(r5, MemOperand(frame_pointer(), kRegisterOutput));
+        // Increment success counter.
+        __ addi(r3, r3, Operand(1));
+        __ StoreP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
+        // Capture results have been stored, so the number of remaining global
+        // output registers is reduced by the number of stored captures.
+        __ subi(r4, r4, Operand(num_saved_registers_));
+        // Check whether we have enough room for another set of capture results.
+        __ cmpi(r4, Operand(num_saved_registers_));
+        __ blt(&return_r3);
+
+        __ StoreP(r4, MemOperand(frame_pointer(), kNumOutputRegisters));
+        // Advance the location for output.
+        __ addi(r5, r5, Operand(num_saved_registers_ * kIntSize));
+        __ StoreP(r5, MemOperand(frame_pointer(), kRegisterOutput));
+
+        // Prepare r3 to initialize registers with its value in the next run.
+        __ LoadP(r3, MemOperand(frame_pointer(), kInputStartMinusOne));
+
+        if (global_with_zero_length_check()) {
+          // Special case for zero-length matches.
+          // r25: capture start index
+          __ cmp(current_input_offset(), r25);
+          // Not a zero-length match, restart.
+          __ bne(&load_char_start_regexp);
+          // Offset from the end is zero if we already reached the end.
+          __ cmpi(current_input_offset(), Operand::Zero());
+          __ beq(&exit_label_);
+          // Advance current position after a zero-length match.
+          __ addi(current_input_offset(),
+                  current_input_offset(),
+                  Operand((mode_ == UC16) ? 2 : 1));
+        }
+
+        __ b(&load_char_start_regexp);
+      } else {
+        __ li(r3, Operand(SUCCESS));
+      }
+    }
+
+    // Exit and return r3
+    __ bind(&exit_label_);
+    if (global()) {
+      __ LoadP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
+    }
+
+    __ bind(&return_r3);
+    // Skip sp past regexp registers and local variables..
+    __ mr(sp, frame_pointer());
+    // Restore registers r25..r31 and return (restoring lr to pc).
+    __ MultiPop(registers_to_retain);
+    __ pop(r0);
+    __ mtctr(r0);
+    __ bcr();
+
+    // Backtrack code (branch target for conditional backtracks).
+    if (backtrack_label_.is_linked()) {
+      __ bind(&backtrack_label_);
+      Backtrack();
+    }
+
+    Label exit_with_exception;
+
+    // Preempt-code
+    if (check_preempt_label_.is_linked()) {
+      SafeCallTarget(&check_preempt_label_);
+
+      CallCheckStackGuardState(r3);
+      __ cmpi(r3, Operand::Zero());
+      // If returning non-zero, we should end execution with the given
+      // result as return value.
+      __ bne(&return_r3);
+
+      // String might have moved: Reload end of string from frame.
+      __ LoadP(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
+      SafeReturn();
+    }
+
+    // Backtrack stack overflow code.
+    if (stack_overflow_label_.is_linked()) {
+      SafeCallTarget(&stack_overflow_label_);
+      // Reached if the backtrack-stack limit has been hit.
+      Label grow_failed;
+
+      // Call GrowStack(backtrack_stackpointer(), &stack_base)
+      static const int num_arguments = 3;
+      __ PrepareCallCFunction(num_arguments, r3);
+      __ mr(r3, backtrack_stackpointer());
+      __ addi(r4, frame_pointer(), Operand(kStackHighEnd));
+      __ mov(r5, Operand(ExternalReference::isolate_address()));
+      ExternalReference grow_stack =
+        ExternalReference::re_grow_stack(masm_->isolate());
+      __ CallCFunction(grow_stack, num_arguments);
+      // If return NULL, we have failed to grow the stack, and
+      // must exit with a stack-overflow exception.
+      __ cmpi(r3, Operand::Zero());
+      __ beq(&exit_with_exception);
+      // Otherwise use return value as new stack pointer.
+      __ mr(backtrack_stackpointer(), r3);
+      // Restore saved registers and continue.
+      SafeReturn();
+    }
+
+    if (exit_with_exception.is_linked()) {
+      // If any of the code above needed to exit with an exception.
+      __ bind(&exit_with_exception);
+      // Exit with Result EXCEPTION(-1) to signal thrown exception.
+      __ li(r3, Operand(EXCEPTION));
+      __ b(&return_r3);
+    }
+  }
+
+  CodeDesc code_desc;
+  masm_->GetCode(&code_desc);
+  Handle<Code> code = FACTORY->NewCode(code_desc,
+                                       Code::ComputeFlags(Code::REGEXP),
+                                       masm_->CodeObject());
+  PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
+  return Handle<HeapObject>::cast(code);
+}
+
+
+void RegExpMacroAssemblerPPC::GoTo(Label* to) {
+  BranchOrBacktrack(al, to);
+}
+
+
+void RegExpMacroAssemblerPPC::IfRegisterGE(int reg,
+                                           int comparand,
+                                           Label* if_ge) {
+  __ LoadP(r3, register_location(reg), r0);
+  __ Cmpi(r3, Operand(comparand), r0);
+  BranchOrBacktrack(ge, if_ge);
+}
+
+
+void RegExpMacroAssemblerPPC::IfRegisterLT(int reg,
+                                           int comparand,
+                                           Label* if_lt) {
+  __ LoadP(r3, register_location(reg), r0);
+  __ Cmpi(r3, Operand(comparand), r0);
+  BranchOrBacktrack(lt, if_lt);
+}
+
+
+void RegExpMacroAssemblerPPC::IfRegisterEqPos(int reg,
+                                              Label* if_eq) {
+  __ LoadP(r3, register_location(reg), r0);
+  __ cmp(r3, current_input_offset());
+  BranchOrBacktrack(eq, if_eq);
+}
+
+
+RegExpMacroAssembler::IrregexpImplementation
+    RegExpMacroAssemblerPPC::Implementation() {
+  return kPPCImplementation;
+}
+
+
+void RegExpMacroAssemblerPPC::LoadCurrentCharacter(int cp_offset,
+                                                   Label* on_end_of_input,
+                                                   bool check_bounds,
+                                                   int characters) {
+  ASSERT(cp_offset >= -1);      // ^ and \b can look behind one character.
+  ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
+  if (check_bounds) {
+    CheckPosition(cp_offset + characters - 1, on_end_of_input);
+  }
+  LoadCurrentCharacterUnchecked(cp_offset, characters);
+}
+
+
+void RegExpMacroAssemblerPPC::PopCurrentPosition() {
+  Pop(current_input_offset());
+}
+
+
+void RegExpMacroAssemblerPPC::PopRegister(int register_index) {
+  Pop(r3);
+  __ StoreP(r3, register_location(register_index), r0);
+}
+
+
+void RegExpMacroAssemblerPPC::PushBacktrack(Label* label) {
+  if (label->is_bound()) {
+    int target = label->pos();
+    __ mov(r3, Operand(target + Code::kHeaderSize - kHeapObjectTag));
+  } else {
+    Label after_constant;
+    __ b(&after_constant);
+    int offset = masm_->pc_offset();
+    int cp_offset = offset + Code::kHeaderSize - kHeapObjectTag;
+    __ emit(0);
+    masm_->label_at_put(label, offset);
+    __ bind(&after_constant);
+    __ LoadWord(r3, MemOperand(code_pointer(), cp_offset), r0);
+  }
+  Push(r3);
+  CheckStackLimit();
+}
+
+
+void RegExpMacroAssemblerPPC::PushCurrentPosition() {
+  Push(current_input_offset());
+}
+
+
+void RegExpMacroAssemblerPPC::PushRegister(int register_index,
+                                           StackCheckFlag check_stack_limit) {
+  __ LoadP(r3, register_location(register_index), r0);
+  Push(r3);
+  if (check_stack_limit) CheckStackLimit();
+}
+
+
+void RegExpMacroAssemblerPPC::ReadCurrentPositionFromRegister(int reg) {
+  __ LoadP(current_input_offset(), register_location(reg), r0);
+}
+
+
+void RegExpMacroAssemblerPPC::ReadStackPointerFromRegister(int reg) {
+  __ LoadP(backtrack_stackpointer(), register_location(reg), r0);
+  __ LoadP(r3, MemOperand(frame_pointer(), kStackHighEnd));
+  __ add(backtrack_stackpointer(), backtrack_stackpointer(), r3);
+}
+
+
+void RegExpMacroAssemblerPPC::SetCurrentPositionFromEnd(int by) {
+  Label after_position;
+  __ Cmpi(current_input_offset(), Operand(-by * char_size()), r0);
+  __ bge(&after_position);
+  __ mov(current_input_offset(), Operand(-by * char_size()));
+  // On RegExp code entry (where this operation is used), the character before
+  // the current position is expected to be already loaded.
+  // We have advanced the position, so it's safe to read backwards.
+  LoadCurrentCharacterUnchecked(-1, 1);
+  __ bind(&after_position);
+}
+
+
+void RegExpMacroAssemblerPPC::SetRegister(int register_index, int to) {
+  ASSERT(register_index >= num_saved_registers_);  // Reserved for positions!
+  __ mov(r3, Operand(to));
+  __ StoreP(r3, register_location(register_index), r0);
+}
+
+
+bool RegExpMacroAssemblerPPC::Succeed() {
+  __ b(&success_label_);
+  return global();
+}
+
+
+void RegExpMacroAssemblerPPC::WriteCurrentPositionToRegister(int reg,
+                                                             int cp_offset) {
+  if (cp_offset == 0) {
+    __ StoreP(current_input_offset(), register_location(reg), r0);
+  } else {
+    __ mov(r0, Operand(cp_offset * char_size()));
+    __ add(r3, current_input_offset(), r0);
+    __ StoreP(r3, register_location(reg), r0);
+  }
+}
+
+
+void RegExpMacroAssemblerPPC::ClearRegisters(int reg_from, int reg_to) {
+  ASSERT(reg_from <= reg_to);
+  __ LoadP(r3, MemOperand(frame_pointer(), kInputStartMinusOne));
+  for (int reg = reg_from; reg <= reg_to; reg++) {
+    __ StoreP(r3, register_location(reg), r0);
+  }
+}
+
+
+void RegExpMacroAssemblerPPC::WriteStackPointerToRegister(int reg) {
+  __ LoadP(r4, MemOperand(frame_pointer(), kStackHighEnd));
+  __ sub(r3, backtrack_stackpointer(), r4);
+  __ StoreP(r3, register_location(reg), r0);
+}
+
+
+// Private methods:
+
+void RegExpMacroAssemblerPPC::CallCheckStackGuardState(Register scratch) {
+  static const int num_arguments = 3;
+  __ PrepareCallCFunction(num_arguments, scratch);
+  // RegExp code frame pointer.
+  __ mr(r5, frame_pointer());
+  // Code* of self.
+  __ mov(r4, Operand(masm_->CodeObject()));
+  // r3 becomes return address pointer.
+  ExternalReference stack_guard_check =
+      ExternalReference::re_check_stack_guard_state(masm_->isolate());
+  CallCFunctionUsingStub(stack_guard_check, num_arguments);
+}
+
+
+// Helper function for reading a value out of a stack frame.
+template <typename T>
+static T& frame_entry(Address re_frame, int frame_offset) {
+  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
+}
+
+
+int RegExpMacroAssemblerPPC::CheckStackGuardState(Address* return_address,
+                                                  Code* re_code,
+                                                  Address re_frame) {
+  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
+  ASSERT(isolate == Isolate::Current());
+  if (isolate->stack_guard()->IsStackOverflow()) {
+    isolate->StackOverflow();
+    return EXCEPTION;
+  }
+
+  // If not real stack overflow the stack guard was used to interrupt
+  // execution for another purpose.
+
+  // If this is a direct call from JavaScript retry the RegExp forcing the call
+  // through the runtime system. Currently the direct call cannot handle a GC.
+  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
+    return RETRY;
+  }
+
+  // Prepare for possible GC.
+  HandleScope handles(isolate);
+  Handle<Code> code_handle(re_code);
+
+  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
+
+  // Current string.
+  bool is_ascii = subject->IsAsciiRepresentationUnderneath();
+
+  ASSERT(re_code->instruction_start() <= *return_address);
+  ASSERT(*return_address <=
+      re_code->instruction_start() + re_code->instruction_size());
+
+  MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
+
+  if (*code_handle != re_code) {  // Return address no longer valid
+    int delta = code_handle->address() - re_code->address();
+    // Overwrite the return address on the stack.
+    *return_address += delta;
+  }
+
+  if (result->IsException()) {
+    return EXCEPTION;
+  }
+
+  Handle<String> subject_tmp = subject;
+  int slice_offset = 0;
+
+  // Extract the underlying string and the slice offset.
+  if (StringShape(*subject_tmp).IsCons()) {
+    subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
+  } else if (StringShape(*subject_tmp).IsSliced()) {
+    SlicedString* slice = SlicedString::cast(*subject_tmp);
+    subject_tmp = Handle<String>(slice->parent());
+    slice_offset = slice->offset();
+  }
+
+  // String might have changed.
+  if (subject_tmp->IsAsciiRepresentation() != is_ascii) {
+    // If we changed between an ASCII and an UC16 string, the specialized
+    // code cannot be used, and we need to restart regexp matching from
+    // scratch (including, potentially, compiling a new version of the code).
+    return RETRY;
+  }
+
+  // Otherwise, the content of the string might have moved. It must still
+  // be a sequential or external string with the same content.
+  // Update the start and end pointers in the stack frame to the current
+  // location (whether it has actually moved or not).
+  ASSERT(StringShape(*subject_tmp).IsSequential() ||
+      StringShape(*subject_tmp).IsExternal());
+
+  // The original start address of the characters to match.
+  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
+
+  // Find the current start address of the same character at the current string
+  // position.
+  int start_index = frame_entry<intptr_t>(re_frame, kStartIndex);
+  const byte* new_address = StringCharacterPosition(*subject_tmp,
+                                                    start_index + slice_offset);
+
+  if (start_address != new_address) {
+    // If there is a difference, update the object pointer and start and end
+    // addresses in the RegExp stack frame to match the new value.
+    const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
+    int byte_length = static_cast<int>(end_address - start_address);
+    frame_entry<const String*>(re_frame, kInputString) = *subject;
+    frame_entry<const byte*>(re_frame, kInputStart) = new_address;
+    frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
+  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
+    // Subject string might have been a ConsString that underwent
+    // short-circuiting during GC. That will not change start_address but
+    // will change pointer inside the subject handle.
+    frame_entry<const String*>(re_frame, kInputString) = *subject;
+  }
+
+  return 0;
+}
+
+
+MemOperand RegExpMacroAssemblerPPC::register_location(int register_index) {
+  ASSERT(register_index < (1<<30));
+  if (num_registers_ <= register_index) {
+    num_registers_ = register_index + 1;
+  }
+  return MemOperand(frame_pointer(),
+                    kRegisterZero - register_index * kPointerSize);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckPosition(int cp_offset,
+                                            Label* on_outside_input) {
+  __ Cmpi(current_input_offset(), Operand(-cp_offset * char_size()), r0);
+  BranchOrBacktrack(ge, on_outside_input);
+}
+
+
+void RegExpMacroAssemblerPPC::BranchOrBacktrack(Condition condition,
+                                                Label* to,
+                                                CRegister cr) {
+  if (condition == al) {  // Unconditional.
+    if (to == NULL) {
+      Backtrack();
+      return;
+    }
+    __ b(to);
+    return;
+  }
+  if (to == NULL) {
+    __ b(condition, &backtrack_label_, cr);
+    return;
+  }
+  __ b(condition, to, cr);
+}
+
+
+void RegExpMacroAssemblerPPC::SafeCall(Label* to, Condition cond,
+                                       CRegister cr) {
+  __ b(cond, to, cr, SetLK);
+}
+
+
+void RegExpMacroAssemblerPPC::SafeReturn() {
+  __ pop(r0);
+  __ mov(ip, Operand(masm_->CodeObject()));
+  __ add(r0, r0, ip);
+  __ mtlr(r0);
+  __ blr();
+}
+
+
+void RegExpMacroAssemblerPPC::SafeCallTarget(Label* name) {
+  __ bind(name);
+  __ mflr(r0);
+  __ mov(ip, Operand(masm_->CodeObject()));
+  __ sub(r0, r0, ip);
+  __ push(r0);
+}
+
+
+void RegExpMacroAssemblerPPC::Push(Register source) {
+  ASSERT(!source.is(backtrack_stackpointer()));
+  __ StorePU(source, MemOperand(backtrack_stackpointer(), -kPointerSize));
+}
+
+
+void RegExpMacroAssemblerPPC::Pop(Register target) {
+  ASSERT(!target.is(backtrack_stackpointer()));
+  __ LoadP(target, MemOperand(backtrack_stackpointer()));
+  __ addi(backtrack_stackpointer(), backtrack_stackpointer(),
+          Operand(kPointerSize));
+}
+
+
+void RegExpMacroAssemblerPPC::CheckPreemption() {
+  // Check for preemption.
+  ExternalReference stack_limit =
+      ExternalReference::address_of_stack_limit(masm_->isolate());
+  __ mov(r3, Operand(stack_limit));
+  __ LoadP(r3, MemOperand(r3));
+  __ cmpl(sp, r3);
+  SafeCall(&check_preempt_label_, le);
+}
+
+
+void RegExpMacroAssemblerPPC::CheckStackLimit() {
+  ExternalReference stack_limit =
+      ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
+  __ mov(r3, Operand(stack_limit));
+  __ LoadP(r3, MemOperand(r3));
+  __ cmpl(backtrack_stackpointer(), r3);
+  SafeCall(&stack_overflow_label_, le);
+}
+
+
+void RegExpMacroAssemblerPPC::CallCFunctionUsingStub(
+    ExternalReference function,
+    int num_arguments) {
+  // Must pass all arguments in registers. The stub pushes on the stack.
+  ASSERT(num_arguments <= 8);
+  __ mov(code_pointer(), Operand(function));
+  RegExpCEntryStub stub;
+  __ CallStub(&stub);
+  if (OS::ActivationFrameAlignment() > kPointerSize) {
+    __ LoadP(sp, MemOperand(sp, 0));
+  } else {
+    __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize));
+  }
+  __ mov(code_pointer(), Operand(masm_->CodeObject()));
+}
+
+
+bool RegExpMacroAssemblerPPC::CanReadUnaligned() {
+  return CpuFeatures::IsSupported(UNALIGNED_ACCESSES) && !slow_safe();
+}
+
+
+void RegExpMacroAssemblerPPC::LoadCurrentCharacterUnchecked(int cp_offset,
+                                                            int characters) {
+  Register offset = current_input_offset();
+  if (cp_offset != 0) {
+    // r25 is not being used to store the capture start index at this point.
+    __ addi(r25, current_input_offset(), Operand(cp_offset * char_size()));
+    offset = r25;
+  }
+  // The lwz, stw, lhz, sth instructions can do unaligned accesses, if the CPU
+  // and the operating system running on the target allow it.
+  // We assume we don't want to do unaligned loads on PPC, so this function
+  // must only be used to load a single character at a time.
+
+  ASSERT(characters == 1);
+  __ add(current_character(), end_of_input_address(), offset);
+  if (mode_ == ASCII) {
+    __ lbz(current_character(), MemOperand(current_character()));
+  } else {
+    ASSERT(mode_ == UC16);
+    __ lhz(current_character(), MemOperand(current_character()));
+  }
+}
+
+
+void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
+  int stack_alignment = OS::ActivationFrameAlignment();
+  if (stack_alignment < kPointerSize) stack_alignment = kPointerSize;
+
+  // Stack is already aligned for call, so decrement by alignment
+  // to make room for storing the return address.
+  int extra_stack_slots = stack_alignment >> kPointerSizeLog2;
+
+  __ addi(r3, sp, Operand(-stack_alignment));
+  __ mflr(r0);
+  __ StoreP(r0, MemOperand(r3, 0));
+
+  // PPC LINUX ABI:
+  extra_stack_slots += kNumRequiredStackFrameSlots;
+  __ addi(sp, sp, Operand(-extra_stack_slots * kPointerSize));
+
+#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
+  // Native AIX/PPC64 Linux use a function descriptor.
+  __ LoadP(ToRegister(2), MemOperand(r26, kPointerSize));  // TOC
+  __ LoadP(ip, MemOperand(r26, 0));  // Instruction address
+  Register target = ip;
+#elif ABI_TOC_ADDRESSABILITY_VIA_IP
+  Register target = ip;
+  __ Move(target, r26);
+#else
+  Register target = r26;
+#endif
+
+  __ Call(target);
+
+  __ addi(sp, sp, Operand(extra_stack_slots * kPointerSize));
+
+  __ LoadP(r0, MemOperand(sp, -stack_alignment));
+  __ mtlr(r0);
+  __ blr();
+}
+
+#undef __
+
+#endif  // V8_INTERPRETED_REGEXP
+
+}}  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/regexp-macro-assembler-ppc.h b/src/ppc/regexp-macro-assembler-ppc.h
new file mode 100644
index 0000000..5dc158e
--- /dev/null
+++ b/src/ppc/regexp-macro-assembler-ppc.h
@@ -0,0 +1,270 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PPC_REGEXP_MACRO_ASSEMBLER_PPC_H_
+#define V8_PPC_REGEXP_MACRO_ASSEMBLER_PPC_H_
+
+#include "ppc/assembler-ppc.h"
+#include "ppc/assembler-ppc-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+#ifndef V8_INTERPRETED_REGEXP
+class RegExpMacroAssemblerPPC: public NativeRegExpMacroAssembler {
+ public:
+  RegExpMacroAssemblerPPC(Mode mode, int registers_to_save, Zone* zone);
+  virtual ~RegExpMacroAssemblerPPC();
+  virtual int stack_limit_slack();
+  virtual void AdvanceCurrentPosition(int by);
+  virtual void AdvanceRegister(int reg, int by);
+  virtual void Backtrack();
+  virtual void Bind(Label* label);
+  virtual void CheckAtStart(Label* on_at_start);
+  virtual void CheckCharacter(unsigned c, Label* on_equal);
+  virtual void CheckCharacterAfterAnd(unsigned c,
+                                      unsigned mask,
+                                      Label* on_equal);
+  virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
+  virtual void CheckCharacterLT(uc16 limit, Label* on_less);
+  virtual void CheckCharacters(Vector<const uc16> str,
+                               int cp_offset,
+                               Label* on_failure,
+                               bool check_end_of_string);
+  // A "greedy loop" is a loop that is both greedy and with a simple
+  // body. It has a particularly simple implementation.
+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
+  virtual void CheckNotAtStart(Label* on_not_at_start);
+  virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
+  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
+                                               Label* on_no_match);
+  virtual void CheckNotCharacter(unsigned c, Label* on_not_equal);
+  virtual void CheckNotCharacterAfterAnd(unsigned c,
+                                         unsigned mask,
+                                         Label* on_not_equal);
+  virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
+                                              uc16 minus,
+                                              uc16 mask,
+                                              Label* on_not_equal);
+  virtual void CheckCharacterInRange(uc16 from,
+                                     uc16 to,
+                                     Label* on_in_range);
+  virtual void CheckCharacterNotInRange(uc16 from,
+                                        uc16 to,
+                                        Label* on_not_in_range);
+  virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
+
+  // Checks whether the given offset from the current position is before
+  // the end of the string.
+  virtual void CheckPosition(int cp_offset, Label* on_outside_input);
+  virtual bool CheckSpecialCharacterClass(uc16 type,
+                                          Label* on_no_match);
+  virtual void Fail();
+  virtual Handle<HeapObject> GetCode(Handle<String> source);
+  virtual void GoTo(Label* label);
+  virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
+  virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
+  virtual void IfRegisterEqPos(int reg, Label* if_eq);
+  virtual IrregexpImplementation Implementation();
+  virtual void LoadCurrentCharacter(int cp_offset,
+                                    Label* on_end_of_input,
+                                    bool check_bounds = true,
+                                    int characters = 1);
+  virtual void PopCurrentPosition();
+  virtual void PopRegister(int register_index);
+  virtual void PushBacktrack(Label* label);
+  virtual void PushCurrentPosition();
+  virtual void PushRegister(int register_index,
+                            StackCheckFlag check_stack_limit);
+  virtual void ReadCurrentPositionFromRegister(int reg);
+  virtual void ReadStackPointerFromRegister(int reg);
+  virtual void SetCurrentPositionFromEnd(int by);
+  virtual void SetRegister(int register_index, int to);
+  virtual bool Succeed();
+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
+  virtual void ClearRegisters(int reg_from, int reg_to);
+  virtual void WriteStackPointerToRegister(int reg);
+  virtual bool CanReadUnaligned();
+
+  // Called from RegExp if the stack-guard is triggered.
+  // If the code object is relocated, the return address is fixed before
+  // returning.
+  static int CheckStackGuardState(Address* return_address,
+                                  Code* re_code,
+                                  Address re_frame);
+
+ private:
+  // Offsets from frame_pointer() of function parameters and stored registers.
+  static const int kFramePointer = 0;
+
+  // Above the frame pointer - Stored registers and stack passed parameters.
+  // Register 25..31.
+  static const int kStoredRegisters = kFramePointer;
+  // Return address (stored from link register, read into pc on return).
+  static const int kReturnAddress = kStoredRegisters + 7 * kPointerSize;
+  static const int kCallerFrame = kReturnAddress + kPointerSize;
+  // Stack parameters placed by caller.
+  static const int kSecondaryReturnAddress = kCallerFrame +
+    kStackFrameExtraParamSlot * kPointerSize;
+  static const int kIsolate = kSecondaryReturnAddress + kPointerSize;
+
+  // Below the frame pointer.
+  // Register parameters stored by setup code.
+  static const int kDirectCall = kFramePointer - kPointerSize;
+  static const int kStackHighEnd = kDirectCall - kPointerSize;
+  static const int kNumOutputRegisters = kStackHighEnd - kPointerSize;
+  static const int kRegisterOutput = kNumOutputRegisters - kPointerSize;
+  static const int kInputEnd = kRegisterOutput - kPointerSize;
+  static const int kInputStart = kInputEnd - kPointerSize;
+  static const int kStartIndex = kInputStart - kPointerSize;
+  static const int kInputString = kStartIndex - kPointerSize;
+  // When adding local variables remember to push space for them in
+  // the frame in GetCode.
+  static const int kSuccessfulCaptures = kInputString - kPointerSize;
+  static const int kInputStartMinusOne = kSuccessfulCaptures - kPointerSize;
+  // First register address. Following registers are below it on the stack.
+  static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
+
+  // Initial size of code buffer.
+  static const size_t kRegExpCodeSize = 1024;
+
+  // Load a number of characters at the given offset from the
+  // current position, into the current-character register.
+  void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
+
+  // Check whether preemption has been requested.
+  void CheckPreemption();
+
+  // Check whether we are exceeding the stack limit on the backtrack stack.
+  void CheckStackLimit();
+
+
+  // Generate a call to CheckStackGuardState.
+  void CallCheckStackGuardState(Register scratch);
+
+  // The ebp-relative location of a regexp register.
+  MemOperand register_location(int register_index);
+
+  // Register holding the current input position as negative offset from
+  // the end of the string.
+  inline Register current_input_offset() { return r27; }
+
+  // The register containing the current character after LoadCurrentCharacter.
+  inline Register current_character() { return r28; }
+
+  // Register holding address of the end of the input string.
+  inline Register end_of_input_address() { return r30; }
+
+  // Register holding the frame address. Local variables, parameters and
+  // regexp registers are addressed relative to this.
+  inline Register frame_pointer() { return fp; }
+
+  // The register containing the backtrack stack top. Provides a meaningful
+  // name to the register.
+  inline Register backtrack_stackpointer() { return r29; }
+
+  // Register holding pointer to the current code object.
+  inline Register code_pointer() { return r26; }
+
+  // Byte size of chars in the string to match (decided by the Mode argument)
+  inline int char_size() { return static_cast<int>(mode_); }
+
+  // Equivalent to a conditional branch to the label, unless the label
+  // is NULL, in which case it is a conditional Backtrack.
+  void BranchOrBacktrack(Condition condition, Label* to, CRegister cr = cr7);
+
+  // Call and return internally in the generated code in a way that
+  // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
+  inline void SafeCall(Label* to, Condition cond = al, CRegister cr = cr7);
+  inline void SafeReturn();
+  inline void SafeCallTarget(Label* name);
+
+  // Pushes the value of a register on the backtrack stack. Decrements the
+  // stack pointer by a word size and stores the register's value there.
+  inline void Push(Register source);
+
+  // Pops a value from the backtrack stack. Reads the word at the stack pointer
+  // and increments it by a word size.
+  inline void Pop(Register target);
+
+  // Calls a C function and cleans up the frame alignment done by
+  // by FrameAlign. The called function *is* allowed to trigger a garbage
+  // collection, but may not take more than four arguments (no arguments
+  // passed on the stack), and the first argument will be a pointer to the
+  // return address.
+  inline void CallCFunctionUsingStub(ExternalReference function,
+                                     int num_arguments);
+
+
+  MacroAssembler* masm_;
+
+  // Which mode to generate code for (ASCII or UC16).
+  Mode mode_;
+
+  // One greater than maximal register index actually used.
+  int num_registers_;
+
+  // Number of registers to output at the end (the saved registers
+  // are always 0..num_saved_registers_-1)
+  int num_saved_registers_;
+
+  // Manage a small pre-allocated pool for writing label targets
+  // to for pushing backtrack addresses.
+  int backtrack_constant_pool_offset_;
+  int backtrack_constant_pool_capacity_;
+
+  // Labels used internally.
+  Label entry_label_;
+  Label start_label_;
+  Label success_label_;
+  Label backtrack_label_;
+  Label exit_label_;
+  Label check_preempt_label_;
+  Label stack_overflow_label_;
+  Label internal_failure_label_;
+};
+
+// Set of non-volatile registers saved/restored by generated regexp code.
+const RegList kRegExpCalleeSaved =
+  1 <<  25 |
+  1 <<  26 |
+  1 <<  27 |
+  1 <<  28 |
+  1 <<  29 |
+  1 <<  30 |
+  1 <<  31;
+
+#endif  // V8_INTERPRETED_REGEXP
+
+
+}}  // namespace v8::internal
+
+#endif  // V8_PPC_REGEXP_MACRO_ASSEMBLER_PPC_H_
diff --git a/src/ppc/simulator-ppc.cc b/src/ppc/simulator-ppc.cc
new file mode 100644
index 0000000..8daaa57
--- /dev/null
+++ b/src/ppc/simulator-ppc.cc
@@ -0,0 +1,3479 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+#include <math.h>
+#include <cstdarg>
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "disasm.h"
+#include "assembler.h"
+#include "codegen.h"
+#include "ppc/constants-ppc.h"
+#include "ppc/simulator-ppc.h"
+#include "ppc/frames-ppc.h"
+
+#if defined(USE_SIMULATOR)
+
+// Only build the simulator if not compiling for real PPC hardware.
+namespace v8 {
+namespace internal {
+
+// This macro provides a platform independent use of sscanf. The reason for
+// SScanF not being implemented in a platform independent way through
+// ::v8::internal::OS in the same way as SNPrintF is that the
+// Windows C Run-Time Library does not provide vsscanf.
+#define SScanF sscanf  // NOLINT
+
+// The PPCDebugger class is used by the simulator while debugging simulated
+// PowerPC code.
+class PPCDebugger {
+ public:
+  explicit PPCDebugger(Simulator* sim) : sim_(sim) { }
+  ~PPCDebugger();
+
+  void Stop(Instruction* instr);
+  void Info(Instruction* instr);
+  void Debug();
+
+ private:
+  static const Instr kBreakpointInstr = (TWI | 0x1f * B21);
+  static const Instr kNopInstr = (ORI);  // ori, 0,0,0
+
+  Simulator* sim_;
+
+  intptr_t GetRegisterValue(int regnum);
+  double GetRegisterPairDoubleValue(int regnum);
+  double GetFPDoubleRegisterValue(int regnum);
+  bool GetValue(const char* desc, intptr_t* value);
+  bool GetFPDoubleValue(const char* desc, double* value);
+
+  // Set or delete a breakpoint. Returns true if successful.
+  bool SetBreakpoint(Instruction* break_pc);
+  bool DeleteBreakpoint(Instruction* break_pc);
+
+  // Undo and redo all breakpoints. This is needed to bracket disassembly and
+  // execution to skip past breakpoints when run from the debugger.
+  void UndoBreakpoints();
+  void RedoBreakpoints();
+};
+
+
+PPCDebugger::~PPCDebugger() {
+}
+
+
+
+#ifdef GENERATED_CODE_COVERAGE
+static FILE* coverage_log = NULL;
+
+
+static void InitializeCoverage() {
+  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
+  if (file_name != NULL) {
+    coverage_log = fopen(file_name, "aw+");
+  }
+}
+
+
+void PPCDebugger::Stop(Instruction* instr) {  // roohack need to fix for PPC
+  // Get the stop code.
+  uint32_t code = instr->SvcValue() & kStopCodeMask;
+  // Retrieve the encoded address, which comes just after this stop.
+  char** msg_address =
+    reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
+  char* msg = *msg_address;
+  ASSERT(msg != NULL);
+
+  // Update this stop description.
+  if (isWatchedStop(code) && !watched_stops[code].desc) {
+    watched_stops[code].desc = msg;
+  }
+
+  if (strlen(msg) > 0) {
+    if (coverage_log != NULL) {
+      fprintf(coverage_log, "%s\n", msg);
+      fflush(coverage_log);
+    }
+    // Overwrite the instruction and address with nops.
+    instr->SetInstructionBits(kNopInstr);
+    reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr);
+  }
+  sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize + kPointerSize);
+}
+
+#else  // ndef GENERATED_CODE_COVERAGE
+
+static void InitializeCoverage() {
+}
+
+
+void PPCDebugger::Stop(Instruction* instr) {
+  // Get the stop code.
+  // use of kStopCodeMask not right on PowerPC
+  uint32_t code = instr->SvcValue() & kStopCodeMask;
+  // Retrieve the encoded address, which comes just after this stop.
+  char* msg = *reinterpret_cast<char**>(sim_->get_pc()
+                                        + Instruction::kInstrSize);
+  // Update this stop description.
+  if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) {
+    sim_->watched_stops[code].desc = msg;
+  }
+  // Print the stop message and code if it is not the default code.
+  if (code != kMaxStopCode) {
+    PrintF("Simulator hit stop %u: %s\n", code, msg);
+  } else {
+    PrintF("Simulator hit %s\n", msg);
+  }
+  sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize + kPointerSize);
+  Debug();
+}
+#endif
+
+
+void PPCDebugger::Info(Instruction* instr) {
+  // Retrieve the encoded address immediately following the Info breakpoint.
+  char* msg = *reinterpret_cast<char**>(sim_->get_pc()
+                                        + Instruction::kInstrSize);
+  PrintF("Simulator info %s\n", msg);
+  sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize + kPointerSize);
+}
+
+
+intptr_t PPCDebugger::GetRegisterValue(int regnum) {
+  return sim_->get_register(regnum);
+}
+
+
+double PPCDebugger::GetRegisterPairDoubleValue(int regnum) {
+  return sim_->get_double_from_register_pair(regnum);
+}
+
+
+double PPCDebugger::GetFPDoubleRegisterValue(int regnum) {
+  return sim_->get_double_from_d_register(regnum);
+}
+
+bool PPCDebugger::GetValue(const char* desc, intptr_t* value) {
+  int regnum = Registers::Number(desc);
+  if (regnum != kNoRegister) {
+    *value = GetRegisterValue(regnum);
+    return true;
+  } else {
+    if (strncmp(desc, "0x", 2) == 0) {
+      return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
+    } else {
+      return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
+    }
+  }
+  return false;
+}
+
+bool PPCDebugger::GetFPDoubleValue(const char* desc, double* value) {
+  int regnum = FPRegisters::Number(desc);
+  if (regnum != kNoRegister) {
+    *value = sim_->get_double_from_d_register(regnum);
+    return true;
+  }
+  return false;
+}
+
+
+bool PPCDebugger::SetBreakpoint(Instruction* break_pc) {
+  // Check if a breakpoint can be set. If not return without any side-effects.
+  if (sim_->break_pc_ != NULL) {
+    return false;
+  }
+
+  // Set the breakpoint.
+  sim_->break_pc_ = break_pc;
+  sim_->break_instr_ = break_pc->InstructionBits();
+  // Not setting the breakpoint instruction in the code itself. It will be set
+  // when the debugger shell continues.
+  return true;
+}
+
+
+bool PPCDebugger::DeleteBreakpoint(Instruction* break_pc) {
+  if (sim_->break_pc_ != NULL) {
+    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
+  }
+
+  sim_->break_pc_ = NULL;
+  sim_->break_instr_ = 0;
+  return true;
+}
+
+
+void PPCDebugger::UndoBreakpoints() {
+  if (sim_->break_pc_ != NULL) {
+    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
+  }
+}
+
+
+void PPCDebugger::RedoBreakpoints() {
+  if (sim_->break_pc_ != NULL) {
+    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
+  }
+}
+
+
+void PPCDebugger::Debug() {
+  intptr_t last_pc = -1;
+  bool done = false;
+
+#define COMMAND_SIZE 63
+#define ARG_SIZE 255
+
+#define STR(a) #a
+#define XSTR(a) STR(a)
+
+  char cmd[COMMAND_SIZE + 1];
+  char arg1[ARG_SIZE + 1];
+  char arg2[ARG_SIZE + 1];
+  char* argv[3] = { cmd, arg1, arg2 };
+
+  // make sure to have a proper terminating character if reaching the limit
+  cmd[COMMAND_SIZE] = 0;
+  arg1[ARG_SIZE] = 0;
+  arg2[ARG_SIZE] = 0;
+
+  // Undo all set breakpoints while running in the debugger shell. This will
+  // make them invisible to all commands.
+  UndoBreakpoints();
+  // Disable tracing while simulating
+  bool trace=::v8::internal::FLAG_trace_sim;
+  ::v8::internal::FLAG_trace_sim = false;
+
+  while (!done && !sim_->has_bad_pc()) {
+    if (last_pc != sim_->get_pc()) {
+      disasm::NameConverter converter;
+      disasm::Disassembler dasm(converter);
+      // use a reasonably large buffer
+      v8::internal::EmbeddedVector<char, 256> buffer;
+      dasm.InstructionDecode(buffer,
+                             reinterpret_cast<byte*>(sim_->get_pc()));
+      PrintF("  0x%08" V8PRIxPTR "  %s\n", sim_->get_pc(), buffer.start());
+      last_pc = sim_->get_pc();
+    }
+    char* line = ReadLine("sim> ");
+    if (line == NULL) {
+      break;
+    } else {
+      char* last_input = sim_->last_debugger_input();
+      if (strcmp(line, "\n") == 0 && last_input != NULL) {
+        line = last_input;
+      } else {
+        // Ownership is transferred to sim_;
+        sim_->set_last_debugger_input(line);
+      }
+      // Use sscanf to parse the individual parts of the command line. At the
+      // moment no command expects more than two parameters.
+      int argc = SScanF(line,
+                        "%" XSTR(COMMAND_SIZE) "s "
+                        "%" XSTR(ARG_SIZE) "s "
+                        "%" XSTR(ARG_SIZE) "s",
+                        cmd, arg1, arg2);
+      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
+        intptr_t value;
+
+        // If at a breakpoint, proceed past it.
+        if ((reinterpret_cast<Instruction*>(sim_->get_pc()))->InstructionBits()
+             == 0x7d821008) {
+          sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
+        } else {
+          sim_->InstructionDecode(
+                  reinterpret_cast<Instruction*>(sim_->get_pc()));
+        }
+
+        if (argc == 2 && last_pc != sim_->get_pc() &&
+                            GetValue(arg1, &value)) {
+          for (int i = 1; i < value; i++) {
+            disasm::NameConverter converter;
+            disasm::Disassembler dasm(converter);
+            // use a reasonably large buffer
+            v8::internal::EmbeddedVector<char, 256> buffer;
+            dasm.InstructionDecode(buffer,
+                                   reinterpret_cast<byte*>(sim_->get_pc()));
+            PrintF("  0x%08" V8PRIxPTR "  %s\n", sim_->get_pc(),
+                   buffer.start());
+            sim_->InstructionDecode(
+                    reinterpret_cast<Instruction*>(sim_->get_pc()));
+          }
+        }
+      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
+        // If at a breakpoint, proceed past it.
+        if ((reinterpret_cast<Instruction*>(sim_->get_pc()))->InstructionBits()
+             == 0x7d821008) {
+          sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
+        } else {
+          // Execute the one instruction we broke at with breakpoints disabled.
+          sim_->InstructionDecode(
+                  reinterpret_cast<Instruction*>(sim_->get_pc()));
+        }
+        // Leave the debugger shell.
+        done = true;
+      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
+        if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
+          intptr_t value;
+          double dvalue;
+          if (strcmp(arg1, "all") == 0) {
+            for (int i = 0; i < kNumRegisters; i++) {
+              value = GetRegisterValue(i);
+              PrintF("    %3s: %08" V8PRIxPTR, Registers::Name(i), value);
+              if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
+                  i < 8 &&
+                  (i % 2) == 0) {
+                dvalue = GetRegisterPairDoubleValue(i);
+                PrintF(" (%f)\n", dvalue);
+              } else if (i != 0 && !((i+1) & 3)) {
+                PrintF("\n");
+              }
+            }
+            PrintF("  pc: %08" V8PRIxPTR "  lr: %08" V8PRIxPTR "  "
+                   "ctr: %08" V8PRIxPTR "  xer: %08x  cr: %08x\n",
+                   sim_->special_reg_pc_, sim_->special_reg_lr_,
+                   sim_->special_reg_ctr_, sim_->special_reg_xer_,
+                   sim_->condition_reg_);
+          } else if (strcmp(arg1, "alld") == 0) {
+            for (int i = 0; i < kNumRegisters; i++) {
+              value = GetRegisterValue(i);
+              PrintF("     %3s: %08" V8PRIxPTR
+                     " %11" V8PRIdPTR, Registers::Name(i), value, value);
+              if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
+                  i < 8 &&
+                  (i % 2) == 0) {
+                dvalue = GetRegisterPairDoubleValue(i);
+                PrintF(" (%f)\n", dvalue);
+              } else if (!((i+1) % 2)) {
+                PrintF("\n");
+              }
+            }
+            PrintF("   pc: %08" V8PRIxPTR "  lr: %08" V8PRIxPTR "  "
+                   "ctr: %08" V8PRIxPTR "  xer: %08x  cr: %08x\n",
+                   sim_->special_reg_pc_, sim_->special_reg_lr_,
+                   sim_->special_reg_ctr_, sim_->special_reg_xer_,
+                   sim_->condition_reg_);
+          } else if (strcmp(arg1, "allf") == 0) {
+            for (int i = 0; i < kNumFPDoubleRegisters; i++) {
+              dvalue = GetFPDoubleRegisterValue(i);
+              uint64_t as_words = BitCast<uint64_t>(dvalue);
+              PrintF("%3s: %f 0x%08x %08x\n",
+                     FPRegisters::Name(i),
+                     dvalue,
+                     static_cast<uint32_t>(as_words >> 32),
+                     static_cast<uint32_t>(as_words & 0xffffffff));
+            }
+          } else if (arg1[0] == 'r' &&
+                      (arg1[1] >= '0' && arg1[1] <= '9' &&
+                        (arg1[2] == '\0' ||
+                          (arg1[2] >= '0' && arg1[2] <= '9'
+                            && arg1[3] == '\0')))) {
+              int regnum = strtoul(&arg1[1], 0, 10);
+              if (regnum != kNoRegister) {
+                value = GetRegisterValue(regnum);
+                PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n",
+                       arg1, value, value);
+              } else {
+                PrintF("%s unrecognized\n", arg1);
+              }
+          } else {
+            if (GetValue(arg1, &value)) {
+              PrintF("%s: 0x%08" V8PRIxPTR " %" V8PRIdPTR "\n",
+                     arg1, value, value);
+            } else if (GetFPDoubleValue(arg1, &dvalue)) {
+              uint64_t as_words = BitCast<uint64_t>(dvalue);
+              PrintF("%s: %f 0x%08x %08x\n",
+                     arg1,
+                     dvalue,
+                     static_cast<uint32_t>(as_words >> 32),
+                     static_cast<uint32_t>(as_words & 0xffffffff));
+            } else {
+              PrintF("%s unrecognized\n", arg1);
+            }
+          }
+        } else {
+          PrintF("print <register>\n");
+        }
+      } else if ((strcmp(cmd, "po") == 0)
+                 || (strcmp(cmd, "printobject") == 0)) {
+        if (argc == 2) {
+          intptr_t value;
+          if (GetValue(arg1, &value)) {
+            Object* obj = reinterpret_cast<Object*>(value);
+            PrintF("%s: \n", arg1);
+#ifdef DEBUG
+            obj->PrintLn();
+#else
+            obj->ShortPrint();
+            PrintF("\n");
+#endif
+          } else {
+            PrintF("%s unrecognized\n", arg1);
+          }
+        } else {
+          PrintF("printobject <value>\n");
+        }
+      } else if (strcmp(cmd, "setpc") == 0) {
+        intptr_t value;
+
+        if (!GetValue(arg1, &value)) {
+          PrintF("%s unrecognized\n", arg1);
+          continue;
+        }
+        sim_->set_pc(value);
+      } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
+        intptr_t* cur = NULL;
+        intptr_t* end = NULL;
+        int next_arg = 1;
+
+        if (strcmp(cmd, "stack") == 0) {
+          cur = reinterpret_cast<intptr_t*>(sim_->get_register(Simulator::sp));
+        } else {  // "mem"
+          intptr_t value;
+          if (!GetValue(arg1, &value)) {
+            PrintF("%s unrecognized\n", arg1);
+            continue;
+          }
+          cur = reinterpret_cast<intptr_t*>(value);
+          next_arg++;
+        }
+
+        intptr_t words;  // likely inaccurate variable name for 64bit
+        if (argc == next_arg) {
+          words = 10;
+        } else if (argc == next_arg + 1) {
+          if (!GetValue(argv[next_arg], &words)) {
+            words = 10;
+          }
+        }
+        end = cur + words;
+
+        while (cur < end) {
+          PrintF("  0x%08" V8PRIxPTR ":  0x%08" V8PRIxPTR " %10" V8PRIdPTR,
+                 reinterpret_cast<intptr_t>(cur), *cur, *cur);
+          HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
+          int value = *cur;
+          Heap* current_heap = v8::internal::Isolate::Current()->heap();
+          if (current_heap->Contains(obj) || ((value & 1) == 0)) {
+            PrintF(" (");
+            if ((value & 1) == 0) {
+              PrintF("smi %d", value / 2);
+            } else {
+              obj->ShortPrint();
+            }
+            PrintF(")");
+          }
+          PrintF("\n");
+          cur++;
+        }
+      } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
+        disasm::NameConverter converter;
+        disasm::Disassembler dasm(converter);
+        // use a reasonably large buffer
+        v8::internal::EmbeddedVector<char, 256> buffer;
+
+        byte* prev = NULL;
+        byte* cur = NULL;
+        byte* end = NULL;
+
+        if (argc == 1) {
+          cur = reinterpret_cast<byte*>(sim_->get_pc());
+          end = cur + (10 * Instruction::kInstrSize);
+        } else if (argc == 2) {
+          int regnum = Registers::Number(arg1);
+          if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
+            // The argument is an address or a register name.
+            intptr_t value;
+            if (GetValue(arg1, &value)) {
+              cur = reinterpret_cast<byte*>(value);
+              // Disassemble 10 instructions at <arg1>.
+              end = cur + (10 * Instruction::kInstrSize);
+            }
+          } else {
+            // The argument is the number of instructions.
+            intptr_t value;
+            if (GetValue(arg1, &value)) {
+              cur = reinterpret_cast<byte*>(sim_->get_pc());
+              // Disassemble <arg1> instructions.
+              end = cur + (value * Instruction::kInstrSize);
+            }
+          }
+        } else {
+          intptr_t value1;
+          intptr_t value2;
+          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
+            cur = reinterpret_cast<byte*>(value1);
+            end = cur + (value2 * Instruction::kInstrSize);
+          }
+        }
+
+        while (cur < end) {
+          prev = cur;
+          cur += dasm.InstructionDecode(buffer, cur);
+          PrintF("  0x%08" V8PRIxPTR "  %s\n",
+                 reinterpret_cast<intptr_t>(prev), buffer.start());
+        }
+      } else if (strcmp(cmd, "gdb") == 0) {
+        PrintF("relinquishing control to gdb\n");
+        v8::internal::OS::DebugBreak();
+        PrintF("regaining control from gdb\n");
+      } else if (strcmp(cmd, "break") == 0) {
+        if (argc == 2) {
+          intptr_t value;
+          if (GetValue(arg1, &value)) {
+            if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
+              PrintF("setting breakpoint failed\n");
+            }
+          } else {
+            PrintF("%s unrecognized\n", arg1);
+          }
+        } else {
+          PrintF("break <address>\n");
+        }
+      } else if (strcmp(cmd, "del") == 0) {
+        if (!DeleteBreakpoint(NULL)) {
+          PrintF("deleting breakpoint failed\n");
+        }
+      } else if (strcmp(cmd, "cr") == 0) {
+        PrintF("Condition reg: %08x\n", sim_->condition_reg_);
+      } else if (strcmp(cmd, "lr") == 0) {
+        PrintF("Link reg: %08" V8PRIxPTR "\n", sim_->special_reg_lr_);
+      } else if (strcmp(cmd, "ctr") == 0) {
+        PrintF("Ctr reg: %08" V8PRIxPTR "\n", sim_->special_reg_ctr_);
+      } else if (strcmp(cmd, "xer") == 0) {
+        PrintF("XER: %08x\n", sim_->special_reg_xer_);
+      } else if (strcmp(cmd, "fpscr") == 0) {
+        PrintF("FPSCR: %08x\n", sim_->fp_condition_reg_);
+      } else if (strcmp(cmd, "stop") == 0) {
+        intptr_t value;
+        intptr_t stop_pc = sim_->get_pc() -
+                             (Instruction::kInstrSize + kPointerSize);
+        Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
+        Instruction* msg_address =
+          reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
+        if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
+          // Remove the current stop.
+          if (sim_->isStopInstruction(stop_instr)) {
+            stop_instr->SetInstructionBits(kNopInstr);
+            msg_address->SetInstructionBits(kNopInstr);
+          } else {
+            PrintF("Not at debugger stop.\n");
+          }
+        } else if (argc == 3) {
+          // Print information about all/the specified breakpoint(s).
+          if (strcmp(arg1, "info") == 0) {
+            if (strcmp(arg2, "all") == 0) {
+              PrintF("Stop information:\n");
+              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+                sim_->PrintStopInfo(i);
+              }
+            } else if (GetValue(arg2, &value)) {
+              sim_->PrintStopInfo(value);
+            } else {
+              PrintF("Unrecognized argument.\n");
+            }
+          } else if (strcmp(arg1, "enable") == 0) {
+            // Enable all/the specified breakpoint(s).
+            if (strcmp(arg2, "all") == 0) {
+              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+                sim_->EnableStop(i);
+              }
+            } else if (GetValue(arg2, &value)) {
+              sim_->EnableStop(value);
+            } else {
+              PrintF("Unrecognized argument.\n");
+            }
+          } else if (strcmp(arg1, "disable") == 0) {
+            // Disable all/the specified breakpoint(s).
+            if (strcmp(arg2, "all") == 0) {
+              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+                sim_->DisableStop(i);
+              }
+            } else if (GetValue(arg2, &value)) {
+              sim_->DisableStop(value);
+            } else {
+              PrintF("Unrecognized argument.\n");
+            }
+          }
+        } else {
+          PrintF("Wrong usage. Use help command for more information.\n");
+        }
+      } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
+        ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
+        PrintF("Trace of executed instructions is %s\n",
+               ::v8::internal::FLAG_trace_sim ? "on" : "off");
+      } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
+        PrintF("cont\n");
+        PrintF("  continue execution (alias 'c')\n");
+        PrintF("stepi [num instructions]\n");
+        PrintF("  step one/num instruction(s) (alias 'si')\n");
+        PrintF("print <register>\n");
+        PrintF("  print register content (alias 'p')\n");
+        PrintF("  use register name 'all' to display all integer registers\n");
+        PrintF("  use register name 'alld' to display integer registers "\
+               "with decimal values\n");
+        PrintF("  use register name 'rN' to display register number 'N'\n");
+        PrintF("  add argument 'fp' to print register pair double values\n");
+        PrintF("  use register name 'allf' to display floating-point "\
+               "registers\n");
+        PrintF("printobject <register>\n");
+        PrintF("  print an object from a register (alias 'po')\n");
+        PrintF("cr\n");
+        PrintF("  print condition register\n");
+        PrintF("lr\n");
+        PrintF("  print link register\n");
+        PrintF("ctr\n");
+        PrintF("  print ctr register\n");
+        PrintF("xer\n");
+        PrintF("  print XER\n");
+        PrintF("fpscr\n");
+        PrintF("  print FPSCR\n");
+        PrintF("stack [<num words>]\n");
+        PrintF("  dump stack content, default dump 10 words)\n");
+        PrintF("mem <address> [<num words>]\n");
+        PrintF("  dump memory content, default dump 10 words)\n");
+        PrintF("disasm [<instructions>]\n");
+        PrintF("disasm [<address/register>]\n");
+        PrintF("disasm [[<address/register>] <instructions>]\n");
+        PrintF("  disassemble code, default is 10 instructions\n");
+        PrintF("  from pc (alias 'di')\n");
+        PrintF("gdb\n");
+        PrintF("  enter gdb\n");
+        PrintF("break <address>\n");
+        PrintF("  set a break point on the address\n");
+        PrintF("del\n");
+        PrintF("  delete the breakpoint\n");
+        PrintF("trace (alias 't')\n");
+        PrintF("  toogle the tracing of all executed statements\n");
+        PrintF("stop feature:\n");
+        PrintF("  Description:\n");
+        PrintF("    Stops are debug instructions inserted by\n");
+        PrintF("    the Assembler::stop() function.\n");
+        PrintF("    When hitting a stop, the Simulator will\n");
+        PrintF("    stop and and give control to the PPCDebugger.\n");
+        PrintF("    The first %d stop codes are watched:\n",
+               Simulator::kNumOfWatchedStops);
+        PrintF("    - They can be enabled / disabled: the Simulator\n");
+        PrintF("      will / won't stop when hitting them.\n");
+        PrintF("    - The Simulator keeps track of how many times they \n");
+        PrintF("      are met. (See the info command.) Going over a\n");
+        PrintF("      disabled stop still increases its counter. \n");
+        PrintF("  Commands:\n");
+        PrintF("    stop info all/<code> : print infos about number <code>\n");
+        PrintF("      or all stop(s).\n");
+        PrintF("    stop enable/disable all/<code> : enables / disables\n");
+        PrintF("      all or number <code> stop(s)\n");
+        PrintF("    stop unstop\n");
+        PrintF("      ignore the stop instruction at the current location\n");
+        PrintF("      from now on\n");
+      } else {
+        PrintF("Unknown command: %s\n", cmd);
+      }
+    }
+  }
+
+  // Add all the breakpoints back to stop execution and enter the debugger
+  // shell when hit.
+  RedoBreakpoints();
+  // Restore tracing
+  ::v8::internal::FLAG_trace_sim = trace;
+
+#undef COMMAND_SIZE
+#undef ARG_SIZE
+
+#undef STR
+#undef XSTR
+}
+
+
+static bool ICacheMatch(void* one, void* two) {
+  ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
+  ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
+  return one == two;
+}
+
+
+static uint32_t ICacheHash(void* key) {
+  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
+}
+
+
+static bool AllOnOnePage(uintptr_t start, int size) {
+  intptr_t start_page = (start & ~CachePage::kPageMask);
+  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
+  return start_page == end_page;
+}
+
+
+void Simulator::set_last_debugger_input(char* input) {
+  DeleteArray(last_debugger_input_);
+  last_debugger_input_ = input;
+}
+
+
+void Simulator::FlushICache(v8::internal::HashMap* i_cache,
+                            void* start_addr,
+                            size_t size) {
+  intptr_t start = reinterpret_cast<intptr_t>(start_addr);
+  int intra_line = (start & CachePage::kLineMask);
+  start -= intra_line;
+  size += intra_line;
+  size = ((size - 1) | CachePage::kLineMask) + 1;
+  int offset = (start & CachePage::kPageMask);
+  while (!AllOnOnePage(start, size - 1)) {
+    int bytes_to_flush = CachePage::kPageSize - offset;
+    FlushOnePage(i_cache, start, bytes_to_flush);
+    start += bytes_to_flush;
+    size -= bytes_to_flush;
+    ASSERT_EQ(0, static_cast<int>(start & CachePage::kPageMask));
+    offset = 0;
+  }
+  if (size != 0) {
+    FlushOnePage(i_cache, start, size);
+  }
+}
+
+
+CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
+  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
+                                                        ICacheHash(page),
+                                                        true);
+  if (entry->value == NULL) {
+    CachePage* new_page = new CachePage();
+    entry->value = new_page;
+  }
+  return reinterpret_cast<CachePage*>(entry->value);
+}
+
+
+// Flush from start up to and not including start + size.
+void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
+                             intptr_t start,
+                             int size) {
+  ASSERT(size <= CachePage::kPageSize);
+  ASSERT(AllOnOnePage(start, size - 1));
+  ASSERT((start & CachePage::kLineMask) == 0);
+  ASSERT((size & CachePage::kLineMask) == 0);
+  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
+  int offset = (start & CachePage::kPageMask);
+  CachePage* cache_page = GetCachePage(i_cache, page);
+  char* valid_bytemap = cache_page->ValidityByte(offset);
+  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
+}
+
+
+void Simulator::CheckICache(v8::internal::HashMap* i_cache,
+                            Instruction* instr) {
+  intptr_t address = reinterpret_cast<intptr_t>(instr);
+  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
+  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
+  int offset = (address & CachePage::kPageMask);
+  CachePage* cache_page = GetCachePage(i_cache, page);
+  char* cache_valid_byte = cache_page->ValidityByte(offset);
+  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
+  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
+  if (cache_hit) {
+    // Check that the data in memory matches the contents of the I-cache.
+    CHECK(memcmp(reinterpret_cast<void*>(instr),
+                 cache_page->CachedData(offset),
+                 Instruction::kInstrSize) == 0);
+  } else {
+    // Cache miss.  Load memory into the cache.
+    memcpy(cached_line, line, CachePage::kLineLength);
+    *cache_valid_byte = CachePage::LINE_VALID;
+  }
+}
+
+
+void Simulator::Initialize(Isolate* isolate) {
+  if (isolate->simulator_initialized()) return;
+  isolate->set_simulator_initialized(true);
+  ::v8::internal::ExternalReference::set_redirector(isolate,
+                                                    &RedirectExternalReference);
+}
+
+
+Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
+  i_cache_ = isolate_->simulator_i_cache();
+  if (i_cache_ == NULL) {
+    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    isolate_->set_simulator_i_cache(i_cache_);
+  }
+  Initialize(isolate);
+  // Set up simulator support first. Some of this information is needed to
+  // setup the architecture state.
+  size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
+  stack_ = reinterpret_cast<char*>(malloc(stack_size));
+  pc_modified_ = false;
+  icount_ = 0;
+  break_pc_ = NULL;
+  break_instr_ = 0;
+
+  // Set up architecture state.
+  // All registers are initialized to zero to start with.
+  for (int i = 0; i < kNumGPRs; i++) {
+    registers_[i] = 0;
+  }
+  condition_reg_ = 0;  // PowerPC
+  fp_condition_reg_ = 0;  // PowerPC
+  special_reg_pc_ = 0;  // PowerPC
+  special_reg_lr_ = 0;  // PowerPC
+  special_reg_ctr_ = 0;  // PowerPC
+
+  // Initializing FP registers.
+  for (int i = 0; i < kNumFPRs; i++) {
+    fp_register[i] = 0.0;
+  }
+
+  // The sp is initialized to point to the bottom (high address) of the
+  // allocated stack area. To be safe in potential stack underflows we leave
+  // some buffer below.
+  registers_[sp] = reinterpret_cast<intptr_t>(stack_) + stack_size - 64;
+  InitializeCoverage();
+
+  last_debugger_input_ = NULL;
+}
+
+
+// When the generated code calls an external reference we need to catch that in
+// the simulator.  The external reference will be a function compiled for the
+// host architecture.  We need to call that function instead of trying to
+// execute it with the simulator.  We do that by redirecting the external
+// reference to a svc (Supervisor Call) instruction that is handled by
+// the simulator.  We write the original destination of the jump just at a known
+// offset from the svc instruction so the simulator knows what to call.
+class Redirection {
+ public:
+  Redirection(void* external_function, ExternalReference::Type type)
+      : external_function_(external_function),
+        swi_instruction_(rtCallRedirInstr | kCallRtRedirected),
+        type_(type),
+        next_(NULL) {
+    Isolate* isolate = Isolate::Current();
+    next_ = isolate->simulator_redirection();
+    Simulator::current(isolate)->
+        FlushICache(isolate->simulator_i_cache(),
+                    reinterpret_cast<void*>(&swi_instruction_),
+                    Instruction::kInstrSize);
+    isolate->set_simulator_redirection(this);
+  }
+
+  void* address_of_swi_instruction() {
+    return reinterpret_cast<void*>(&swi_instruction_);
+  }
+
+  void* external_function() { return external_function_; }
+  ExternalReference::Type type() { return type_; }
+
+  static Redirection* Get(void* external_function,
+                          ExternalReference::Type type) {
+    Isolate* isolate = Isolate::Current();
+    Redirection* current = isolate->simulator_redirection();
+    for (; current != NULL; current = current->next_) {
+      if (current->external_function_ == external_function) return current;
+    }
+    return new Redirection(external_function, type);
+  }
+
+  static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
+    char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
+    char* addr_of_redirection =
+        addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
+    return reinterpret_cast<Redirection*>(addr_of_redirection);
+  }
+
+ private:
+  void* external_function_;
+  uint32_t swi_instruction_;
+  ExternalReference::Type type_;
+  Redirection* next_;
+};
+
+
+void* Simulator::RedirectExternalReference(void* external_function,
+                                           ExternalReference::Type type) {
+  Redirection* redirection = Redirection::Get(external_function, type);
+  return redirection->address_of_swi_instruction();
+}
+
+
+// Get the active Simulator for the current thread.
+Simulator* Simulator::current(Isolate* isolate) {
+  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
+      isolate->FindOrAllocatePerThreadDataForThisThread();
+  ASSERT(isolate_data != NULL);
+
+  Simulator* sim = isolate_data->simulator();
+  if (sim == NULL) {
+    // TODO(146): delete the simulator object when a thread/isolate goes away.
+    sim = new Simulator(isolate);
+    isolate_data->set_simulator(sim);
+  }
+  return sim;
+}
+
+
+// Sets the register in the architecture state.
+void Simulator::set_register(int reg, intptr_t value) {
+  ASSERT((reg >= 0) && (reg < kNumGPRs));
+  registers_[reg] = value;
+}
+
+
+// Get the register from the architecture state.
+intptr_t Simulator::get_register(int reg) const {
+  ASSERT((reg >= 0) && (reg < kNumGPRs));
+  // Stupid code added to avoid bug in GCC.
+  // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
+  if (reg >= kNumGPRs) return 0;
+  // End stupid code.
+  return registers_[reg];
+}
+
+
+double Simulator::get_double_from_register_pair(int reg) {
+  ASSERT((reg >= 0) && (reg < kNumGPRs) && ((reg % 2) == 0));
+
+  double dm_val = 0.0;
+#ifndef V8_TARGET_ARCH_PPC64  // doesn't make sense in 64bit mode
+  // Read the bits from the unsigned integer register_[] array
+  // into the double precision floating point value and return it.
+  char buffer[sizeof(fp_register[0])];
+  memcpy(buffer, &registers_[reg], sizeof(registers_[0]));
+  memcpy(&dm_val, buffer, sizeof(registers_[0]));
+#endif
+  return(dm_val);
+}
+
+// Raw access to the PC register.
+void Simulator::set_pc(intptr_t value) {
+  pc_modified_ = true;
+  special_reg_pc_ = value;
+}
+
+
+bool Simulator::has_bad_pc() const {
+  return ((special_reg_pc_ == bad_lr) || (special_reg_pc_ == end_sim_pc));
+}
+
+
+// Raw access to the PC register without the special adjustment when reading.
+intptr_t Simulator::get_pc() const {
+  return special_reg_pc_;
+}
+
+// For use in calls that take two double values which are currently
+// in d1 and d2
+void Simulator::GetFpArgs(double* x, double* y) {
+  *x = get_double_from_d_register(1);
+  *y = get_double_from_d_register(2);
+}
+
+// For use in calls that take one double value (d1)
+void Simulator::GetFpArgs(double* x) {
+  *x = get_double_from_d_register(1);
+}
+
+
+// For use in calls that take one double value (d1) and one integer
+// value (r3).
+void Simulator::GetFpArgs(double* x, intptr_t* y) {
+  *x = get_double_from_d_register(1);
+  *y = registers_[3];
+}
+
+
+// The return value is in d1.
+void Simulator::SetFpResult(const double& result) {
+  set_d_register_from_double(1, result);
+}
+
+
+void Simulator::TrashCallerSaveRegisters() {
+  // We don't trash the registers with the return value.
+#if 0  // A good idea to trash volatile registers, needs to be done
+  registers_[2] = 0x50Bad4U;
+  registers_[3] = 0x50Bad4U;
+  registers_[12] = 0x50Bad4U;
+#endif
+}
+
+
+uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) {
+  uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
+  return *ptr;
+}
+
+int32_t Simulator::ReadW(intptr_t addr, Instruction* instr) {
+  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+  return *ptr;
+}
+
+
+void Simulator::WriteW(intptr_t addr, uint32_t value, Instruction* instr) {
+  uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
+  *ptr = value;
+  return;
+}
+
+void Simulator::WriteW(intptr_t addr, int32_t value, Instruction* instr) {
+  int32_t* ptr = reinterpret_cast<int32_t*>(addr);
+  *ptr = value;
+  return;
+}
+
+
+uint16_t Simulator::ReadHU(intptr_t addr, Instruction* instr) {
+  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+  return *ptr;
+}
+
+
+int16_t Simulator::ReadH(intptr_t addr, Instruction* instr) {
+  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+  return *ptr;
+}
+
+
+void Simulator::WriteH(intptr_t addr, uint16_t value, Instruction* instr) {
+  uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
+  *ptr = value;
+  return;
+}
+
+
+void Simulator::WriteH(intptr_t addr, int16_t value, Instruction* instr) {
+  int16_t* ptr = reinterpret_cast<int16_t*>(addr);
+  *ptr = value;
+  return;
+}
+
+
+uint8_t Simulator::ReadBU(intptr_t addr) {
+  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
+  return *ptr;
+}
+
+
+int8_t Simulator::ReadB(intptr_t addr) {
+  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
+  return *ptr;
+}
+
+
+void Simulator::WriteB(intptr_t addr, uint8_t value) {
+  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
+  *ptr = value;
+}
+
+
+void Simulator::WriteB(intptr_t addr, int8_t value) {
+  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
+  *ptr = value;
+}
+
+
+intptr_t* Simulator::ReadDW(intptr_t addr) {
+  intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
+  return ptr;
+}
+
+
+void Simulator::WriteDW(intptr_t addr, int64_t value) {
+  int64_t* ptr = reinterpret_cast<int64_t*>(addr);
+  *ptr = value;
+  return;
+}
+
+
+// Returns the limit of the stack area to enable checking for stack overflows.
+uintptr_t Simulator::StackLimit() const {
+  // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
+  // pushing values.
+  return reinterpret_cast<uintptr_t>(stack_) + 1024;
+}
+
+
+// Unsupported instructions use Format to print an error and stop execution.
+void Simulator::Format(Instruction* instr, const char* format) {
+  PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
+         reinterpret_cast<intptr_t>(instr), format);
+  UNIMPLEMENTED();
+}
+
+
+// Calculate C flag value for additions.
+bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
+  uint32_t uleft = static_cast<uint32_t>(left);
+  uint32_t uright = static_cast<uint32_t>(right);
+  uint32_t urest  = 0xffffffffU - uleft;
+
+  return (uright > urest) ||
+         (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
+}
+
+
+// Calculate C flag value for subtractions.
+bool Simulator::BorrowFrom(int32_t left, int32_t right) {
+  uint32_t uleft = static_cast<uint32_t>(left);
+  uint32_t uright = static_cast<uint32_t>(right);
+
+  return (uright > uleft);
+}
+
+
+// Calculate V flag value for additions and subtractions.
+bool Simulator::OverflowFrom(int32_t alu_out,
+                             int32_t left, int32_t right, bool addition) {
+  bool overflow;
+  if (addition) {
+               // operands have the same sign
+    overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
+               // and operands and result have different sign
+               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
+  } else {
+               // operands have different signs
+    overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
+               // and first operand and result have different signs
+               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
+  }
+  return overflow;
+}
+
+
+// Calls into the V8 runtime are based on this very simple interface.
+// Note: To be able to return two values from some calls the code in runtime.cc
+// uses the ObjectPair which is essentially two 32-bit values stuffed into a
+// 64-bit value. With the code below we assume that all runtime calls return
+// 64 bits of result. If they don't, the r4 result register contains a bogus
+// value, which is fine because it is caller-saved.
+typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0,
+                                        intptr_t arg1,
+                                        intptr_t arg2,
+                                        intptr_t arg3,
+                                        intptr_t arg4,
+                                        intptr_t arg5);
+typedef double (*SimulatorRuntimeFPCall)(double arg0,
+                                         double arg1);
+typedef int64_t (*SimulatorRuntimeFPCallX)(double arg0,
+                                         double arg1);
+typedef double (*SimulatorRuntimeFPCallY)(double arg0,
+                                         intptr_t arg1);
+
+// This signature supports direct call in to API function native callback
+// (refer to InvocationCallback in v8.h).
+typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(intptr_t arg0);
+
+// This signature supports direct call to accessor getter callback.
+typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(
+  intptr_t arg0,
+  intptr_t arg1);
+
+// Software interrupt instructions are used by the simulator to call into the
+// C-based V8 runtime.
+void Simulator::SoftwareInterrupt(Instruction* instr) {
+  int svc = instr->SvcValue();
+  switch (svc) {
+    case kCallRtRedirected: {
+      // Check if stack is aligned. Error if not aligned is reported below to
+      // include information on the function called.
+      bool stack_aligned =
+          (get_register(sp)
+           & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
+      Redirection* redirection = Redirection::FromSwiInstruction(instr);
+      intptr_t arg0 = get_register(r3);
+      intptr_t arg1 = get_register(r4);
+      intptr_t arg2 = get_register(r5);
+      intptr_t arg3 = get_register(r6);
+      intptr_t arg4 = get_register(r7);
+      intptr_t arg5 = get_register(r8);
+      bool fp_call =
+         (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
+         (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
+         (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
+         (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
+      // This is dodgy but it works because the C entry stubs are never moved.
+      // See comment in codegen-arm.cc and bug 1242173.
+      intptr_t saved_lr = special_reg_lr_;
+      intptr_t external =
+          reinterpret_cast<intptr_t>(redirection->external_function());
+      if (fp_call) {
+        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
+          SimulatorRuntimeFPCall target =
+              reinterpret_cast<SimulatorRuntimeFPCall>(external);
+          double dval0, dval1;
+          intptr_t ival;
+          switch (redirection->type()) {
+          case ExternalReference::BUILTIN_FP_FP_CALL:
+          case ExternalReference::BUILTIN_COMPARE_CALL:
+            GetFpArgs(&dval0, &dval1);
+            PrintF("Call to host function at %p with args %f, %f",
+                FUNCTION_ADDR(target), dval0, dval1);
+            break;
+          case ExternalReference::BUILTIN_FP_CALL:
+            GetFpArgs(&dval0);
+            PrintF("Call to host function at %p with arg %f",
+                FUNCTION_ADDR(target), dval0);
+            break;
+          case ExternalReference::BUILTIN_FP_INT_CALL:
+            GetFpArgs(&dval0, &ival);
+            PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
+                FUNCTION_ADDR(target), dval0, ival);
+            break;
+          default:
+            UNREACHABLE();
+            break;
+          }
+          if (!stack_aligned) {
+            PrintF(" with unaligned stack %08" V8PRIxPTR
+                   "\n", get_register(sp));
+          }
+          PrintF("\n");
+        }
+        CHECK(stack_aligned);
+        SimulatorRuntimeFPCall target =
+            reinterpret_cast<SimulatorRuntimeFPCall>(external);
+        SimulatorRuntimeFPCallX targetx =
+            reinterpret_cast<SimulatorRuntimeFPCallX>(external);
+        SimulatorRuntimeFPCallY targety =
+            reinterpret_cast<SimulatorRuntimeFPCallY>(external);
+        double dval0, dval1, result;
+        intptr_t ival;
+        int32_t lo_res, hi_res;
+        int64_t iresult;
+        switch (redirection->type()) {
+          case ExternalReference::BUILTIN_FP_FP_CALL:
+            GetFpArgs(&dval0, &dval1);
+            result = target(dval0, dval1);
+            if (::v8::internal::FLAG_trace_sim) {
+                PrintF("Returned %f\n", result);
+            }
+            SetFpResult(result);
+            break;
+          case ExternalReference::BUILTIN_COMPARE_CALL:
+            GetFpArgs(&dval0, &dval1);
+            iresult = targetx(dval0, dval1);
+            lo_res = static_cast<int32_t>(iresult);
+            hi_res = static_cast<int32_t>(iresult >> 32);
+            if (::v8::internal::FLAG_trace_sim) {
+                PrintF("Returned %08x\n", lo_res);
+            }
+#if __BYTE_ORDER == __BIG_ENDIAN
+            set_register(r3, hi_res);
+            set_register(r4, lo_res);
+#else
+            set_register(r3, lo_res);
+            set_register(r4, hi_res);
+#endif
+            break;
+          case ExternalReference::BUILTIN_FP_CALL:
+              GetFpArgs(&dval0, &dval1);
+            result = target(dval0, dval1);  // 2nd parm ignored
+            if (::v8::internal::FLAG_trace_sim) {
+                PrintF("Returned %f\n", result);
+            }
+            SetFpResult(result);
+            break;
+          case ExternalReference::BUILTIN_FP_INT_CALL:
+            GetFpArgs(&dval0, &ival);
+            result = targety(dval0, ival);
+            if (::v8::internal::FLAG_trace_sim) {
+                PrintF("Returned %f\n", result);
+            }
+            SetFpResult(result);
+            break;
+          default:
+            UNREACHABLE();
+            break;
+        }
+      } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
+        // See callers of MacroAssembler::CallApiFunctionAndReturn for
+        // explanation of register usage.
+        SimulatorRuntimeDirectApiCall target =
+            reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
+        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
+          PrintF("Call to host function at %p args %08" V8PRIxPTR,
+              FUNCTION_ADDR(target), arg0);
+          if (!stack_aligned) {
+            PrintF(" with unaligned stack %08" V8PRIxPTR
+                   "\n", get_register(sp));
+          }
+          PrintF("\n");
+        }
+        CHECK(stack_aligned);
+#if ABI_RETURNS_HANDLES_IN_REGS
+        intptr_t p0 = arg0;
+#else
+        intptr_t p0 = arg1;
+#endif
+        v8::Handle<v8::Value> result = target(p0);
+        if (::v8::internal::FLAG_trace_sim) {
+          PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
+        }
+#if ABI_RETURNS_HANDLES_IN_REGS
+        arg0 = (intptr_t)*result;
+#else
+        *(reinterpret_cast<intptr_t*>(arg0)) = (intptr_t) *result;
+#endif
+        set_register(r3, arg0);
+      } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
+        // See callers of MacroAssembler::CallApiFunctionAndReturn for
+        // explanation of register usage.
+        SimulatorRuntimeDirectGetterCall target =
+            reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
+        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
+          PrintF("Call to host function at %p args %08" V8PRIxPTR " %08"
+                 V8PRIxPTR,
+              FUNCTION_ADDR(target), arg0, arg1);
+          if (!stack_aligned) {
+            PrintF(" with unaligned stack %08" V8PRIxPTR
+                   "\n", get_register(sp));
+          }
+          PrintF("\n");
+        }
+        CHECK(stack_aligned);
+#if ABI_RETURNS_HANDLES_IN_REGS
+        intptr_t p0 = arg0;
+        intptr_t p1 = arg1;
+#else
+        intptr_t p0 = arg1;
+        intptr_t p1 = arg2;
+#endif
+#if !ABI_PASSES_HANDLES_IN_REGS
+        p0 = *(reinterpret_cast<intptr_t *>(p0));
+#endif
+        v8::Handle<v8::Value> result = target(p0, p1);
+        if (::v8::internal::FLAG_trace_sim) {
+          PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
+        }
+#if ABI_RETURNS_HANDLES_IN_REGS
+        arg0 = (intptr_t)*result;
+#else
+        *(reinterpret_cast<intptr_t*>(arg0)) = (intptr_t) *result;
+#endif
+        set_register(r3, arg0);
+      } else {
+        // builtin call.
+        ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
+        SimulatorRuntimeCall target =
+            reinterpret_cast<SimulatorRuntimeCall>(external);
+        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
+          PrintF(
+              "Call to host function at %p,\n"
+              "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
+              ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
+              FUNCTION_ADDR(target),
+              arg0,
+              arg1,
+              arg2,
+              arg3,
+              arg4,
+              arg5);
+          if (!stack_aligned) {
+            PrintF(" with unaligned stack %08" V8PRIxPTR
+                   "\n", get_register(sp));
+          }
+          PrintF("\n");
+        }
+        CHECK(stack_aligned);
+        int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
+#if V8_TARGET_ARCH_PPC64
+        if (::v8::internal::FLAG_trace_sim) {
+          PrintF("Returned %08" V8PRIxPTR "\n", result);
+        }
+        set_register(r3, result);
+#else
+        int32_t lo_res = static_cast<int32_t>(result);
+        int32_t hi_res = static_cast<int32_t>(result >> 32);
+        if (::v8::internal::FLAG_trace_sim) {
+          PrintF("Returned %08x\n", lo_res);
+        }
+#if __BYTE_ORDER == __BIG_ENDIAN
+        set_register(r3, hi_res);
+        set_register(r4, lo_res);
+#else
+        set_register(r3, lo_res);
+        set_register(r4, hi_res);
+#endif
+#endif
+      }
+      set_pc(saved_lr);
+      break;
+    }
+    case kBreakpoint: {
+      PPCDebugger dbg(this);
+      dbg.Debug();
+      break;
+    }
+    case kInfo: {
+       PPCDebugger dbg(this);
+       dbg.Info(instr);
+       break;
+     }
+    // stop uses all codes greater than 1 << 23.
+    default: {
+      if (svc >= (1 << 23)) {
+        uint32_t code = svc & kStopCodeMask;
+        if (isWatchedStop(code)) {
+          IncreaseStopCounter(code);
+        }
+        // Stop if it is enabled, otherwise go on jumping over the stop
+        // and the message address.
+        if (isEnabledStop(code)) {
+          PPCDebugger dbg(this);
+          dbg.Stop(instr);
+        } else {
+          set_pc(get_pc() + Instruction::kInstrSize + kPointerSize);
+        }
+      } else {
+        // This is not a valid svc code.
+        UNREACHABLE();
+        break;
+      }
+    }
+  }
+}
+
+
+// Stop helper functions.
+bool Simulator::isStopInstruction(Instruction* instr) {
+  return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
+}
+
+
+bool Simulator::isWatchedStop(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  return code < kNumOfWatchedStops;
+}
+
+
+bool Simulator::isEnabledStop(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  // Unwatched stops are always enabled.
+  return !isWatchedStop(code) ||
+    !(watched_stops[code].count & kStopDisabledBit);
+}
+
+
+void Simulator::EnableStop(uint32_t code) {
+  ASSERT(isWatchedStop(code));
+  if (!isEnabledStop(code)) {
+    watched_stops[code].count &= ~kStopDisabledBit;
+  }
+}
+
+
+void Simulator::DisableStop(uint32_t code) {
+  ASSERT(isWatchedStop(code));
+  if (isEnabledStop(code)) {
+    watched_stops[code].count |= kStopDisabledBit;
+  }
+}
+
+
+void Simulator::IncreaseStopCounter(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  ASSERT(isWatchedStop(code));
+  if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
+    PrintF("Stop counter for code %i has overflowed.\n"
+           "Enabling this code and reseting the counter to 0.\n", code);
+    watched_stops[code].count = 0;
+    EnableStop(code);
+  } else {
+    watched_stops[code].count++;
+  }
+}
+
+
+// Print a stop status.
+void Simulator::PrintStopInfo(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  if (!isWatchedStop(code)) {
+    PrintF("Stop not watched.");
+  } else {
+    const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
+    int32_t count = watched_stops[code].count & ~kStopDisabledBit;
+    // Don't print the state of unused breakpoints.
+    if (count != 0) {
+      if (watched_stops[code].desc) {
+        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
+               code, code, state, count, watched_stops[code].desc);
+      } else {
+        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
+               code, code, state, count);
+      }
+    }
+  }
+}
+
+
+void Simulator::SetCR0(intptr_t result, bool setSO) {
+  int bf = 0;
+  if (result <  0) { bf |= 0x80000000; }
+  if (result >  0) { bf |= 0x40000000; }
+  if (result == 0) { bf |= 0x20000000; }
+  if (setSO) { bf |= 0x10000000; }
+  condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
+}
+
+void Simulator::DecodeBranchConditional(Instruction* instr) {
+  int bo = instr->Bits(25, 21) << 21;
+  int offset = (instr->Bits(15, 2) << 18) >> 16;
+  int condition_bit = instr->Bits(20, 16);
+  int condition_mask = 0x80000000 >> condition_bit;
+  switch (bo) {
+    case DCBNZF:  // Decrement CTR; branch if CTR != 0 and condition false
+    case DCBEZF:  // Decrement CTR; branch if CTR == 0 and condition false
+      UNIMPLEMENTED();
+    case BF: {   // Branch if condition false
+      if (!(condition_reg_ & condition_mask)) {
+        if (instr->Bit(0) == 1) {  // LK flag set
+          special_reg_lr_ = get_pc() + 4;
+        }
+        set_pc(get_pc() + offset);
+      }
+      break;
+    }
+    case DCBNZT:  // Decrement CTR; branch if CTR != 0 and condition true
+    case DCBEZT:  // Decrement CTR; branch if CTR == 0 and condition true
+      UNIMPLEMENTED();
+    case BT: {   // Branch if condition true
+      if (condition_reg_ & condition_mask) {
+        if (instr->Bit(0) == 1) {  // LK flag set
+          special_reg_lr_ = get_pc() + 4;
+        }
+        set_pc(get_pc() + offset);
+      }
+      break;
+    }
+    case DCBNZ:  // Decrement CTR; branch if CTR != 0
+    case DCBEZ:  // Decrement CTR; branch if CTR == 0
+      special_reg_ctr_ -= 1;
+      if ((special_reg_ctr_ == 0) == (bo == DCBEZ)) {
+        if (instr->Bit(0) == 1) {  // LK flag set
+          special_reg_lr_ = get_pc() + 4;
+        }
+        set_pc(get_pc() + offset);
+      }
+      break;
+    case BA: {   // Branch always
+      if (instr->Bit(0) == 1) {  // LK flag set
+        special_reg_lr_ = get_pc() + 4;
+      }
+      set_pc(get_pc() + offset);
+      break;
+    }
+    default:
+      UNIMPLEMENTED();  // Invalid encoding
+  }
+}
+
+// Handle execution based on instruction types.
+void Simulator::DecodeExt1(Instruction* instr) {
+  switch (instr->Bits(10, 1) << 1) {
+    case MCRF:
+      UNIMPLEMENTED();  // Not used by V8.
+    case BCLRX: {
+        // need to check BO flag
+        int old_pc = get_pc();
+        set_pc(special_reg_lr_);
+        if (instr->Bit(0) == 1) {  // LK flag set
+          special_reg_lr_ = old_pc + 4;
+        }
+      break;
+    }
+    case BCCTRX: {
+        // need to check BO flag
+        int old_pc = get_pc();
+        set_pc(special_reg_ctr_);
+        if (instr->Bit(0) == 1) {  // LK flag set
+          special_reg_lr_ = old_pc + 4;
+        }
+      break;
+    }
+    case CRNOR:
+    case RFI:
+    case CRANDC:
+      UNIMPLEMENTED();
+    case ISYNC: {
+      // todo - simulate isync
+      break;
+    }
+    case CRXOR: {
+      int bt = instr->Bits(25, 21);
+      int ba = instr->Bits(20, 16);
+      int bb = instr->Bits(15, 11);
+      int ba_val = ((0x80000000 >> ba) & condition_reg_) == 0 ? 0 : 1;
+      int bb_val = ((0x80000000 >> bb) & condition_reg_) == 0 ? 0 : 1;
+      int bt_val = ba_val ^ bb_val;
+      bt_val = bt_val << (31-bt);  // shift bit to correct destination
+      condition_reg_ &= ~(0x80000000 >> bt);
+      condition_reg_ |= bt_val;
+      break;
+    }
+    case CRNAND:
+    case CRAND:
+    case CREQV:
+    case CRORC:
+    case CROR:
+    default: {
+      UNIMPLEMENTED();  // Not used by V8.
+    }
+  }
+}
+
+bool Simulator::DecodeExt2_10bit(Instruction *instr) {
+  bool found = true;
+
+  int opcode = instr->Bits(10, 1) << 1;
+  switch (opcode) {
+    case SRWX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      uint32_t rs_val = get_register(rs);
+      uintptr_t rb_val = get_register(rb);
+      intptr_t  result = rs_val >> (rb_val & 0x3f);
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case SRDX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      uintptr_t rs_val = get_register(rs);
+      uintptr_t rb_val = get_register(rb);
+      intptr_t  result = rs_val >> (rb_val & 0x7f);
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+#endif
+    case SRAW: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      int32_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      intptr_t result = rs_val >> (rb_val & 0x3f);
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case SRAD: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      intptr_t result = rs_val >> (rb_val & 0x7f);
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+#endif
+    case SRAWIX: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      int sh = instr->Bits(15, 11);
+      int32_t rs_val = get_register(rs);
+      intptr_t result = rs_val >> sh;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case EXTSW: {
+      const int shift = kBitsPerPointer - 32;
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t ra_val = (rs_val << shift) >> shift;
+      set_register(ra, ra_val);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(ra_val);
+      }
+      break;
+    }
+#endif
+    case EXTSH: {
+      const int shift = kBitsPerPointer - 16;
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t ra_val = (rs_val << shift) >> shift;
+      set_register(ra, ra_val);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(ra_val);
+      }
+      break;
+    }
+    case EXTSB: {
+      const int shift = kBitsPerPointer - 8;
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t ra_val = (rs_val << shift) >> shift;
+      set_register(ra, ra_val);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(ra_val);
+      }
+      break;
+    }
+    case LFSUX:
+    case LFSX: {
+      int frt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      int32_t val = ReadW(ra_val + rb_val, instr);
+      float *fptr = reinterpret_cast<float*>(&val);
+      set_d_register_from_double(frt, static_cast<double>(*fptr));
+      if (opcode == LFSUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case LFDUX:
+    case LFDX: {
+      int frt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      double *dptr = reinterpret_cast<double*>(ReadDW(ra_val + rb_val));
+      set_d_register_from_double(frt, *dptr);
+      if (opcode == LFDUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case STFSUX: {
+    case STFSX:
+      int frs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      float frs_val = static_cast<float>(get_double_from_d_register(frs));
+      int32_t *p=  reinterpret_cast<int32_t*>(&frs_val);
+      WriteW(ra_val + rb_val, *p, instr);
+      if (opcode == STFSUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case STFDUX: {
+    case STFDX:
+      int frs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      double frs_val = get_double_from_d_register(frs);
+      int64_t *p = reinterpret_cast<int64_t *>(&frs_val);
+      WriteDW(ra_val + rb_val, *p);
+      if (opcode == STFDUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case SYNC: {
+      // todo - simulate sync
+      break;
+    }
+    case ICBI: {
+      // todo - simulate icbi
+      break;
+    }
+    default: {
+      found = false;
+      break;
+    }
+  }
+
+  if (found)
+    return found;
+
+  found = true;
+  opcode = instr->Bits(10, 2) << 2;
+  switch (opcode) {
+    case SRADIX: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
+      intptr_t rs_val = get_register(rs);
+      intptr_t result = rs_val >> sh;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+    default: {
+      found = false;
+      break;
+    }
+  }
+
+  return found;
+}
+
+void Simulator::DecodeExt2_9bit(Instruction* instr) {
+  int opcode = instr->Bits(9, 1) << 1;
+  switch (opcode) {
+    case TW: {
+      // used for call redirection in simulation mode
+      SoftwareInterrupt(instr);
+      break;
+    }
+    case CMP: {
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      int cr = instr->Bits(25, 23);
+      int bf = 0;
+      if (ra_val < rb_val) { bf |= 0x80000000; }
+      if (ra_val > rb_val) { bf |= 0x40000000; }
+      if (ra_val == rb_val) { bf |= 0x20000000; }
+      int condition_mask = 0xF0000000 >> (cr*4);
+      int condition =  bf >> (cr*4);
+      condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
+      break;
+    }
+    case SUBFCX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      // int oe = instr->Bit(10);
+      uintptr_t ra_val = get_register(ra);
+      uintptr_t rb_val = get_register(rb);
+      uintptr_t alu_out = ~ra_val + rb_val + 1;
+      set_register(rt, alu_out);
+      // If the sign of rb and alu_out don't match, carry = 0
+      if ((alu_out ^ rb_val) & 0x80000000) {
+        special_reg_xer_ &= ~0xF0000000;
+      } else {
+        special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
+      }
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      // todo - handle OE bit
+      break;
+    }
+    case ADDCX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      // int oe = instr->Bit(10);
+      uintptr_t ra_val = get_register(ra);
+      uintptr_t rb_val = get_register(rb);
+      uintptr_t alu_out = ra_val + rb_val;
+      // Check overflow
+      if (~ra_val < rb_val) {
+        special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
+      } else {
+        special_reg_xer_ &= ~0xF0000000;
+      }
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(static_cast<intptr_t>(alu_out));
+      }
+      // todo - handle OE bit
+      break;
+    }
+    case MULHWX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
+      int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
+      int64_t alu_out = (int64_t)ra_val * (int64_t)rb_val;
+      alu_out >>= 32;
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(static_cast<intptr_t>(alu_out));
+      }
+      // todo - handle OE bit
+      break;
+    }
+    case NEGX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      intptr_t ra_val = get_register(ra);
+      intptr_t alu_out = 1 + ~ra_val;
+      set_register(rt, alu_out);
+      if (instr->Bit(10)) {  // OE bit set
+        if (ra_val == kMinInt) {
+            special_reg_xer_ |= 0xC0000000;  // set SO,OV
+        } else {
+            special_reg_xer_ &= ~0x40000000;  // clear OV
+        }
+      }
+      if (instr->Bit(0)) {  // RC bit set
+        bool setSO = (special_reg_xer_ & 0x80000000);
+        SetCR0(alu_out, setSO);
+      }
+      break;
+    }
+    case SLWX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      uint32_t rs_val = get_register(rs);
+      uintptr_t rb_val = get_register(rb);
+      uint32_t result = rs_val << (rb_val & 0x3f);
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case SLDX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      uintptr_t rs_val = get_register(rs);
+      uintptr_t rb_val = get_register(rb);
+      uintptr_t result = rs_val << (rb_val & 0x7f);
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+#endif
+    case CNTLZWX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      uintptr_t rs_val = get_register(rs);
+      uintptr_t count  = 0;
+      int      n      = 0;
+      uintptr_t bit    = 0x80000000;
+      for (; n < 32; n++) {
+          if (bit & rs_val)
+              break;
+          count++;
+          bit >>= 1;
+      }
+      set_register(ra, count);
+      if (instr->Bit(0)) {  // RC Bit set
+        int bf = 0;
+        if (count > 0)  { bf |= 0x40000000; }
+        if (count == 0) { bf |= 0x20000000; }
+        condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
+      }
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case CNTLZDX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      uintptr_t rs_val = get_register(rs);
+      uintptr_t count  = 0;
+      int      n      = 0;
+      uintptr_t bit    = 0x8000000000000000UL;
+      for (; n < 64; n++) {
+          if (bit & rs_val)
+              break;
+          count++;
+          bit >>= 1;
+      }
+      set_register(ra, count);
+      if (instr->Bit(0)) {  // RC Bit set
+        int bf = 0;
+        if (count > 0)  { bf |= 0x40000000; }
+        if (count == 0) { bf |= 0x20000000; }
+        condition_reg_ = (condition_reg_ & ~0xF0000000) | bf;
+      }
+      break;
+    }
+#endif
+    case ANDX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      intptr_t alu_out = rs_val & rb_val;
+      set_register(ra, alu_out);
+      if (instr->Bit(0)) {  // RC Bit set
+        SetCR0(alu_out);
+      }
+      break;
+    }
+    case ANDCX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      intptr_t alu_out = rs_val & ~rb_val;
+      set_register(ra, alu_out);
+      if (instr->Bit(0)) {  // RC Bit set
+        SetCR0(alu_out);
+      }
+      break;
+    }
+    case CMPL: {
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      uintptr_t ra_val = get_register(ra);
+      uintptr_t rb_val = get_register(rb);
+      int cr = instr->Bits(25, 23);
+      int bf = 0;
+      if (ra_val < rb_val) { bf |= 0x80000000; }
+      if (ra_val > rb_val) { bf |= 0x40000000; }
+      if (ra_val == rb_val) { bf |= 0x20000000; }
+      int condition_mask = 0xF0000000 >> (cr*4);
+      int condition =  bf >> (cr*4);
+      condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
+      break;
+    }
+    case SUBFX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      // int oe = instr->Bit(10);
+      intptr_t ra_val = get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      intptr_t alu_out = rb_val - ra_val;
+      // todo - figure out underflow
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC Bit set
+        SetCR0(alu_out);
+      }
+      // todo - handle OE bit
+      break;
+    }
+    case ADDZEX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      intptr_t ra_val = get_register(ra);
+      if (special_reg_xer_ & 0x20000000) {
+        ra_val += 1;
+      }
+      set_register(rt, ra_val);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(ra_val);
+      }
+      // todo - handle OE bit
+      break;
+    }
+    case NORX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      intptr_t alu_out = ~(rs_val | rb_val);
+      set_register(ra, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      break;
+    }
+    case MULLW: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      int32_t ra_val = (get_register(ra) & 0xFFFFFFFF);
+      int32_t rb_val = (get_register(rb) & 0xFFFFFFFF);
+      int32_t alu_out = ra_val * rb_val;
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      // todo - handle OE bit
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case MULLD: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      int64_t ra_val = get_register(ra);
+      int64_t rb_val = get_register(rb);
+      int64_t alu_out = ra_val * rb_val;
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      // todo - handle OE bit
+      break;
+    }
+#endif
+    case DIVW: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      int32_t ra_val = get_register(ra);
+      int32_t rb_val = get_register(rb);
+      // result is undefined if divisor is zero.
+      int32_t alu_out = rb_val ? ra_val / rb_val : -1;
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      // todo - handle OE bit
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case DIVD: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      int64_t ra_val = get_register(ra);
+      int64_t rb_val = get_register(rb);
+      // result is undefined if divisor is zero.
+      int64_t alu_out = rb_val ? ra_val / rb_val : -1;
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      // todo - handle OE bit
+      break;
+    }
+#endif
+    case ADDX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      // int oe = instr->Bit(10);
+      intptr_t ra_val = get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      intptr_t alu_out = ra_val + rb_val;
+      set_register(rt, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      // todo - handle OE bit
+      break;
+    }
+    case XORX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      intptr_t alu_out = rs_val ^ rb_val;
+      set_register(ra, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      break;
+    }
+    case ORX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      intptr_t alu_out = rs_val | rb_val;
+      set_register(ra, alu_out);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(alu_out);
+      }
+      break;
+    }
+    case MFSPR: {
+      int rt = instr->RTValue();
+      int spr = instr->Bits(20, 11);
+      if (spr != 256) {
+        UNIMPLEMENTED();  // Only LRLR supported
+      }
+      set_register(rt, special_reg_lr_);
+      break;
+    }
+    case MTSPR: {
+      int rt = instr->RTValue();
+      intptr_t rt_val = get_register(rt);
+      int spr = instr->Bits(20, 11);
+      if (spr == 256) {
+        special_reg_lr_ = rt_val;
+      } else if (spr == 288) {
+        special_reg_ctr_ = rt_val;
+      } else if (spr == 32) {
+        special_reg_xer_ = rt_val;
+      } else {
+        UNIMPLEMENTED();  // Only LR supported
+      }
+      break;
+    }
+    case MFCR: {
+      int rt = instr->RTValue();
+      set_register(rt, condition_reg_);
+      break;
+    }
+    case STWUX:
+    case STWX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int32_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      WriteW(ra_val+rb_val, rs_val, instr);
+      if (opcode == STWUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case STBUX:
+    case STBX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int8_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      WriteB(ra_val+rb_val, rs_val);
+      if (opcode == STBUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case STHUX:
+    case STHX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int16_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      WriteH(ra_val+rb_val, rs_val, instr);
+      if (opcode == STHUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case LWZX:
+    case LWZUX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      set_register(rt, ReadWU(ra_val+rb_val, instr));
+      if (opcode == LWZUX) {
+        ASSERT(ra != 0 && ra != rt);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+#if V8_TARGET_ARCH_PPC64
+    case LDX:
+    case LDUX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      intptr_t *result = ReadDW(ra_val+rb_val);
+      set_register(rt, *result);
+      if (opcode == LDUX) {
+        ASSERT(ra != 0 && ra != rt);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case STDX:
+    case STDUX: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rs_val = get_register(rs);
+      intptr_t rb_val = get_register(rb);
+      WriteDW(ra_val+rb_val, rs_val);
+      if (opcode == STDUX) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+#endif
+    case LBZX:
+    case LBZUX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      set_register(rt, ReadBU(ra_val+rb_val) & 0xFF);
+      if (opcode == LBZUX) {
+        ASSERT(ra != 0 && ra != rt);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case LHZX:
+    case LHZUX: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int rb = instr->RBValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      intptr_t rb_val = get_register(rb);
+      set_register(rt, ReadHU(ra_val+rb_val, instr) & 0xFFFF);
+      if (opcode == LHZUX) {
+        ASSERT(ra != 0 && ra != rt);
+        set_register(ra, ra_val+rb_val);
+      }
+      break;
+    }
+    case DCBF: {
+      // todo - simulate dcbf
+      break;
+    }
+    default: {
+      PrintF("Unimplemented: %08x\n", instr->InstructionBits());
+      UNIMPLEMENTED();  // Not used by V8.
+    }
+  }
+}
+
+void Simulator::DecodeExt2(Instruction* instr) {
+    // Check first the 10-1 bit versions
+    if (DecodeExt2_10bit(instr))
+        return;
+    // Now look at the lesser encodings
+    DecodeExt2_9bit(instr);
+}
+
+void Simulator::DecodeExt4(Instruction* instr) {
+  switch (instr->Bits(5, 1) << 1) {
+    case FDIV: {
+      int frt = instr->RTValue();
+      int fra = instr->RAValue();
+      int frb = instr->RBValue();
+      double fra_val = get_double_from_d_register(fra);
+      double frb_val = get_double_from_d_register(frb);
+      double frt_val = fra_val / frb_val;
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FSUB: {
+      int frt = instr->RTValue();
+      int fra = instr->RAValue();
+      int frb = instr->RBValue();
+      double fra_val = get_double_from_d_register(fra);
+      double frb_val = get_double_from_d_register(frb);
+      double frt_val = fra_val - frb_val;
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FADD: {
+      int frt = instr->RTValue();
+      int fra = instr->RAValue();
+      int frb = instr->RBValue();
+      double fra_val = get_double_from_d_register(fra);
+      double frb_val = get_double_from_d_register(frb);
+      double frt_val = fra_val + frb_val;
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FSQRT: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      double frt_val = sqrt(frb_val);
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FSEL: {
+      int frt = instr->RTValue();
+      int fra = instr->RAValue();
+      int frb = instr->RBValue();
+      int frc = instr->RCValue();
+      double fra_val = get_double_from_d_register(fra);
+      double frb_val = get_double_from_d_register(frb);
+      double frc_val = get_double_from_d_register(frc);
+      double frt_val = ((fra_val >= 0.0) ? frc_val : frb_val);
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FMUL: {
+      int frt = instr->RTValue();
+      int fra = instr->RAValue();
+      int frc = instr->RCValue();
+      double fra_val = get_double_from_d_register(fra);
+      double frc_val = get_double_from_d_register(frc);
+      double frt_val = fra_val * frc_val;
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+  }
+  int opcode = instr->Bits(10, 1) << 1;
+  switch (opcode) {
+    case FCMPU: {
+      int fra = instr->RAValue();
+      int frb = instr->RBValue();
+      double fra_val = get_double_from_d_register(fra);
+      double frb_val = get_double_from_d_register(frb);
+      int cr = instr->Bits(25, 23);
+      int bf = 0;
+      if (fra_val < frb_val) { bf |= 0x80000000; }
+      if (fra_val > frb_val) { bf |= 0x40000000; }
+      if (fra_val == frb_val) { bf |= 0x20000000; }
+      if (isunordered(fra_val, frb_val)) { bf |= 0x10000000; }
+      int condition_mask = 0xF0000000 >> (cr*4);
+      int condition =  bf >> (cr*4);
+      condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
+      return;
+    }
+    case FRSP: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      // frsp round 8-byte double-precision value to 8-byte
+      // single-precision value, ignore the round here
+      set_d_register_from_double(frt, frb_val);
+      if (instr->Bit(0)) {  // RC bit set
+        //  UNIMPLEMENTED();
+      }
+      return;
+    }
+    case FCFID: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double t_val = get_double_from_d_register(frb);
+      int64_t* frb_val_p = reinterpret_cast<int64_t*>(&t_val);
+      double frt_val = static_cast<double>(*frb_val_p);
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FCTID: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      int64_t frt_val;
+      int64_t one = 1;  // work-around gcc
+      int64_t kMinLongLong = (one << 63);
+      int64_t kMaxLongLong = kMinLongLong - 1;
+
+      if (frb_val > kMaxLongLong) {
+        frt_val = kMaxLongLong;
+      } else if (frb_val < kMinLongLong) {
+        frt_val = kMinLongLong;
+      } else {
+        switch (fp_condition_reg_ & kVFPRoundingModeMask) {
+          case kRoundToZero:
+            frt_val = (int64_t)frb_val;
+            break;
+          case kRoundToPlusInf:
+            frt_val = (int64_t)ceil(frb_val);
+            break;
+          case kRoundToMinusInf:
+            frt_val = (int64_t)floor(frb_val);
+            break;
+          default:
+            frt_val = (int64_t)frb_val;
+            UNIMPLEMENTED();  // Not used by V8.
+            break;
+        }
+      }
+      double *p = reinterpret_cast<double*>(&frt_val);
+      set_d_register_from_double(frt, *p);
+      return;
+    }
+    case FCTIDZ: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      int64_t frt_val;
+      int64_t one = 1;  // work-around gcc
+      int64_t kMinLongLong = (one << 63);
+      int64_t kMaxLongLong = kMinLongLong - 1;
+
+      if (frb_val > kMaxLongLong) {
+        frt_val = kMaxLongLong;
+      } else if (frb_val < kMinLongLong) {
+        frt_val = kMinLongLong;
+      } else {
+        frt_val = (int64_t)frb_val;
+      }
+      double *p = reinterpret_cast<double*>(&frt_val);
+      set_d_register_from_double(frt, *p);
+      return;
+    }
+    case FCTIW:
+    case FCTIWZ: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      int64_t frt_val;
+      if (frb_val > kMaxInt) {
+        frt_val = kMaxInt;
+      } else if (frb_val < kMinInt) {
+        frt_val = kMinInt;
+      } else {
+        if (opcode == FCTIWZ) {
+          frt_val = (int64_t)frb_val;
+        } else {
+          switch (fp_condition_reg_ & kVFPRoundingModeMask) {
+          case kRoundToZero:
+            frt_val = (int64_t)frb_val;
+            break;
+          case kRoundToPlusInf:
+            frt_val = (int64_t)ceil(frb_val);
+            break;
+          case kRoundToMinusInf:
+            frt_val = (int64_t)floor(frb_val);
+            break;
+          case kRoundToNearest:
+            frt_val = (int64_t)lround(frb_val);
+
+            // Round to even if exactly halfway.  (lround rounds up)
+            if (fabs(static_cast<double>(frt_val) - frb_val) == 0.5 &&
+                (frt_val % 2)) {
+                frt_val += ((frt_val > 0) ? -1 : 1);
+            }
+
+            break;
+          default:
+            ASSERT(false);
+            frt_val = (int64_t)frb_val;
+            break;
+          }
+        }
+      }
+      double *p = reinterpret_cast<double*>(&frt_val);
+      set_d_register_from_double(frt, *p);
+      return;
+    }
+    case FNEG: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      double frt_val = -frb_val;
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FMR: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      double frt_val = frb_val;
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case MTFSFI: {
+      int bf = instr->Bits(25, 23);
+      int imm = instr->Bits(15, 12);
+      int fp_condition_mask = 0xF0000000 >> (bf*4);
+      fp_condition_reg_ &= ~fp_condition_mask;
+      fp_condition_reg_ |= (imm << (28 - (bf*4)));
+      if (instr->Bit(0)) {  // RC bit set
+        condition_reg_ &= 0xF0FFFFFF;
+        condition_reg_ |= (imm << 23);
+      }
+      return;
+    }
+    case MTFSF: {
+      int frb = instr->RBValue();
+      double frb_dval = get_double_from_d_register(frb);
+      int64_t *p =  reinterpret_cast<int64_t*>(&frb_dval);
+      int32_t frb_ival = static_cast<int32_t>((*p) & 0xffffffff);
+      int l = instr->Bits(25, 25);
+      if (l == 1) {
+        fp_condition_reg_ = frb_ival;
+      } else {
+        UNIMPLEMENTED();
+      }
+      if (instr->Bit(0)) {  // RC bit set
+        UNIMPLEMENTED();
+        // int w = instr->Bits(16, 16);
+        // int flm = instr->Bits(24, 17);
+      }
+      return;
+    }
+    case MFFS: {
+      int frt = instr->RTValue();
+      int64_t lval = static_cast<int64_t>(fp_condition_reg_);
+      double* p = reinterpret_cast<double*>(&lval);
+      set_d_register_from_double(frt, *p);
+      return;
+    }
+    case FABS: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      double frt_val = abs(frb_val);
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+    case FRIM: {
+      int frt = instr->RTValue();
+      int frb = instr->RBValue();
+      double frb_val = get_double_from_d_register(frb);
+      int64_t floor_val = (int64_t)frb_val;
+      if (floor_val > frb_val)
+        floor_val--;
+      double frt_val = static_cast<double>(floor_val);
+      set_d_register_from_double(frt, frt_val);
+      return;
+    }
+  }
+  UNIMPLEMENTED();  // Not used by V8.
+}
+
+#if V8_TARGET_ARCH_PPC64
+void Simulator::DecodeExt5(Instruction* instr) {
+  switch (instr->Bits(4, 2) << 2) {
+    case RLDICL: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      uintptr_t rs_val = get_register(rs);
+      int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
+      int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
+      ASSERT(sh >=0 && sh <= 63);
+      ASSERT(mb >=0 && mb <= 63);
+      // rotate left
+      uintptr_t result = (rs_val << sh) | (rs_val >> (64-sh));
+      uintptr_t mask = 0xffffffffffffffff >> mb;
+      result &= mask;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      return;
+    }
+    case RLDICR: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      uintptr_t rs_val = get_register(rs);
+      int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
+      int me = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
+      ASSERT(sh >=0 && sh <= 63);
+      ASSERT(me >=0 && me <= 63);
+      // rotate left
+      uintptr_t result = (rs_val << sh) | (rs_val >> (64-sh));
+      uintptr_t mask = 0xffffffffffffffff << (63-me);
+      result &= mask;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      return;
+    }
+    case RLDIC: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      uintptr_t rs_val = get_register(rs);
+      int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
+      int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
+      ASSERT(sh >=0 && sh <= 63);
+      ASSERT(mb >=0 && mb <= 63);
+      // rotate left
+      uintptr_t result = (rs_val << sh) | (rs_val >> (64-sh));
+      uintptr_t mask = (0xffffffffffffffff >> mb) & (0xffffffffffffffff << sh);
+      result &= mask;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      return;
+    }
+    case RLDIMI: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      uintptr_t rs_val = get_register(rs);
+      intptr_t ra_val = get_register(ra);
+      int sh = (instr->Bits(15, 11) | (instr->Bit(1) << 5));
+      int mb = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
+      int me = 63 - sh;
+      // rotate left
+      uintptr_t result = (rs_val << sh) | (rs_val >> (64-sh));
+      uintptr_t mask = 0;
+      if (mb < me+1) {
+        uintptr_t bit = 0x8000000000000000 >> mb;
+        for (; mb <= me; mb++) {
+          mask |= bit;
+          bit >>= 1;
+        }
+      } else if (mb == me+1) {
+         mask = 0xffffffffffffffff;
+      } else {  // mb > me+1
+        uintptr_t bit = 0x8000000000000000 >> (me+1);  // needs to be tested
+        mask = 0xffffffffffffffff;
+        for (;me < mb;me++) {
+          mask ^= bit;
+          bit >>= 1;
+        }
+      }
+      result &= mask;
+      ra_val &= ~mask;
+      result |= ra_val;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      return;
+    }
+  }
+  UNIMPLEMENTED();  // Not used by V8.
+}
+#endif
+
+// Executes the current instruction.
+void Simulator::InstructionDecode(Instruction* instr) {
+  if (v8::internal::FLAG_check_icache) {
+    CheckICache(isolate_->simulator_i_cache(), instr);
+  }
+  pc_modified_ = false;
+  if (::v8::internal::FLAG_trace_sim) {
+    disasm::NameConverter converter;
+    disasm::Disassembler dasm(converter);
+    // use a reasonably large buffer
+    v8::internal::EmbeddedVector<char, 256> buffer;
+    dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
+    PrintF("%05d  %08" V8PRIxPTR "  %s\n", icount_,
+           reinterpret_cast<intptr_t>(instr), buffer.start());
+  }
+  int opcode = instr->OpcodeValue() << 26;
+  switch (opcode) {
+    case TWI: {
+      // used for call redirection in simulation mode
+      SoftwareInterrupt(instr);
+      break;
+    }
+    case SUBFIC: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      intptr_t ra_val = get_register(ra);
+      int32_t im_val = instr->Bits(15, 0);
+      im_val = SIGN_EXT_IMM16(im_val);
+      intptr_t alu_out = im_val - ra_val;
+      set_register(rt, alu_out);
+      // todo - handle RC bit
+      break;
+    }
+    case CMPLI: {
+      int ra = instr->RAValue();
+      uintptr_t ra_val = get_register(ra);
+      uint32_t im_val = instr->Bits(15, 0);
+      int cr = instr->Bits(25, 23);
+      int bf = 0;
+      if (ra_val < im_val) { bf |= 0x80000000; }
+      if (ra_val > im_val) { bf |= 0x40000000; }
+      if (ra_val == im_val) { bf |= 0x20000000; }
+      int condition_mask = 0xF0000000 >> (cr*4);
+      int condition =  bf >> (cr*4);
+      condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
+      break;
+    }
+    case CMPI: {
+      int ra = instr->RAValue();
+      intptr_t ra_val = get_register(ra);
+      int32_t im_val = instr->Bits(15, 0);
+      im_val = SIGN_EXT_IMM16(im_val);
+      int cr = instr->Bits(25, 23);
+      int bf = 0;
+      if (ra_val < im_val) { bf |= 0x80000000; }
+      if (ra_val > im_val) { bf |= 0x40000000; }
+      if (ra_val == im_val) { bf |= 0x20000000; }
+      int condition_mask = 0xF0000000 >> (cr*4);
+      int condition =  bf >> (cr*4);
+      condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
+      break;
+    }
+    case ADDIC: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      uintptr_t ra_val = get_register(ra);
+      uintptr_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      uintptr_t alu_out = ra_val + im_val;
+      // Check overflow
+      if (~ra_val < im_val) {
+        special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
+      } else {
+        special_reg_xer_ &= ~0xF0000000;
+      }
+      set_register(rt, alu_out);
+      break;
+    }
+    case ADDI: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int32_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      intptr_t alu_out;
+      if (ra == 0) {
+        alu_out = im_val;
+      } else {
+        intptr_t ra_val = get_register(ra);
+        alu_out = ra_val + im_val;
+      }
+      set_register(rt, alu_out);
+      // todo - handle RC bit
+      break;
+    }
+    case ADDIS: {
+      int rt = instr->RTValue();
+      int ra = instr->RAValue();
+      int32_t im_val = (instr->Bits(15, 0) << 16);
+      intptr_t alu_out;
+      if (ra == 0) {  // treat r0 as zero
+        alu_out = im_val;
+      } else {
+        intptr_t ra_val = get_register(ra);
+        alu_out = ra_val + im_val;
+      }
+      set_register(rt, alu_out);
+      break;
+    }
+    case BCX: {
+      DecodeBranchConditional(instr);
+      break;
+    }
+    case BX: {
+      int offset = (instr->Bits(25, 2) << 8) >> 6;
+      if (instr->Bit(0) == 1) {  // LK flag set
+        special_reg_lr_ = get_pc() + 4;
+      }
+      set_pc(get_pc() + offset);
+      // todo - AA flag
+      break;
+    }
+    case EXT1: {
+      DecodeExt1(instr);
+      break;
+    }
+    case RLWIMIX: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      uint32_t rs_val = get_register(rs);
+      int32_t ra_val = get_register(ra);
+      int sh = instr->Bits(15, 11);
+      int mb = instr->Bits(10, 6);
+      int me = instr->Bits(5, 1);
+      // rotate left
+      uint32_t result = (rs_val << sh) | (rs_val >> (32-sh));
+      int mask = 0;
+      if (mb < me+1) {
+        int bit = 0x80000000 >> mb;
+        for (; mb <= me; mb++) {
+          mask |= bit;
+          bit >>= 1;
+        }
+      } else if (mb == me+1) {
+         mask = 0xffffffff;
+      } else {  // mb > me+1
+        int bit = 0x80000000 >> (me+1);  // needs to be tested
+        mask = 0xffffffff;
+        for (;me < mb;me++) {
+          mask ^= bit;
+          bit >>= 1;
+        }
+      }
+      result &= mask;
+      ra_val &= ~mask;
+      result |= ra_val;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+    case RLWINMX: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      uint32_t rs_val = get_register(rs);
+      int sh = instr->Bits(15, 11);
+      int mb = instr->Bits(10, 6);
+      int me = instr->Bits(5, 1);
+      // rotate left
+      uint32_t result = (rs_val << sh) | (rs_val >> (32-sh));
+      int mask = 0;
+      if (mb < me+1) {
+        int bit = 0x80000000 >> mb;
+        for (; mb <= me; mb++) {
+          mask |= bit;
+          bit >>= 1;
+        }
+      } else if (mb == me+1) {
+         mask = 0xffffffff;
+      } else {  // mb > me+1
+        int bit = 0x80000000 >> (me+1);  // needs to be tested
+        mask = 0xffffffff;
+        for (;me < mb;me++) {
+          mask ^= bit;
+          bit >>= 1;
+        }
+      }
+      result &= mask;
+      set_register(ra, result);
+      if (instr->Bit(0)) {  // RC bit set
+        SetCR0(result);
+      }
+      break;
+    }
+    case ORI: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      intptr_t rs_val = get_register(rs);
+      uint32_t im_val = instr->Bits(15, 0);
+      intptr_t alu_out = rs_val | im_val;
+      set_register(ra, alu_out);
+      break;
+    }
+    case ORIS: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      intptr_t rs_val = get_register(rs);
+      uint32_t im_val = instr->Bits(15, 0);
+      intptr_t alu_out = rs_val | (im_val << 16);
+      set_register(ra, alu_out);
+      break;
+    }
+    case XORI: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      intptr_t rs_val = get_register(rs);
+      uint32_t im_val = instr->Bits(15, 0);
+      intptr_t alu_out = rs_val ^ im_val;
+      set_register(ra, alu_out);
+      // todo - set condition based SO bit
+      break;
+    }
+    case XORIS: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      intptr_t rs_val = get_register(rs);
+      uint32_t im_val = instr->Bits(15, 0);
+      intptr_t alu_out = rs_val ^ (im_val << 16);
+      set_register(ra, alu_out);
+      break;
+    }
+    case ANDIx: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      intptr_t rs_val = get_register(rs);
+      uint32_t im_val = instr->Bits(15, 0);
+      intptr_t alu_out = rs_val & im_val;
+      set_register(ra, alu_out);
+      SetCR0(alu_out);
+      break;
+    }
+    case ANDISx: {
+      int rs = instr->RSValue();
+      int ra = instr->RAValue();
+      intptr_t rs_val = get_register(rs);
+      uint32_t im_val = instr->Bits(15, 0);
+      intptr_t alu_out = rs_val & (im_val << 16);
+      set_register(ra, alu_out);
+      SetCR0(alu_out);
+      break;
+    }
+    case EXT2: {
+      DecodeExt2(instr);
+      break;
+    }
+
+    case LWZU:
+    case LWZ: {
+      int ra = instr->RAValue();
+      int rt = instr->RTValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      set_register(rt, ReadWU(ra_val+offset, instr));
+      if (opcode == LWZU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case LBZU:
+    case LBZ: {
+      int ra = instr->RAValue();
+      int rt = instr->RTValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      set_register(rt, ReadB(ra_val+offset) & 0xFF);
+      if (opcode == LBZU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case STWU:
+    case STW: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int32_t rs_val = get_register(rs);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      WriteW(ra_val+offset, rs_val, instr);
+      if (opcode == STWU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      // printf("r%d %08x -> %08x\n", rs, rs_val, offset); // 0xdead
+      break;
+    }
+
+    case STBU:
+    case STB: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int8_t rs_val = get_register(rs);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      WriteB(ra_val+offset, rs_val);
+      if (opcode == STBU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case LHZU:
+    case LHZ: {
+      int ra = instr->RAValue();
+      int rt = instr->RTValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      uintptr_t result = ReadHU(ra_val+offset, instr) & 0xffff;
+      set_register(rt, result);
+      if (opcode == LHZU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case LHA:
+    case LHAU: {
+      UNIMPLEMENTED();
+      break;
+    }
+
+    case STHU:
+    case STH: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int16_t rs_val = get_register(rs);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      WriteH(ra_val+offset, rs_val, instr);
+      if (opcode == STHU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case LMW:
+    case STMW: {
+      UNIMPLEMENTED();
+      break;
+    }
+
+    case LFSU:
+    case LFS: {
+     int frt = instr->RTValue();
+      int ra = instr->RAValue();
+      int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int32_t val = ReadW(ra_val + offset, instr);
+      float *fptr = reinterpret_cast<float*>(&val);
+      set_d_register_from_double(frt, static_cast<double>(*fptr));
+      if (opcode == LFSU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case LFDU:
+    case LFD: {
+      int frt = instr->RTValue();
+      int ra = instr->RAValue();
+      int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      double *dptr = reinterpret_cast<double*>(ReadDW(ra_val + offset));
+      set_d_register_from_double(frt, *dptr);
+      if (opcode == LFDU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case STFSU: {
+    case STFS:
+      int frs = instr->RSValue();
+      int ra = instr->RAValue();
+      int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      float frs_val = static_cast<float>(get_double_from_d_register(frs));
+      int32_t *p=  reinterpret_cast<int32_t*>(&frs_val);
+      WriteW(ra_val + offset, *p, instr);
+      if (opcode == STFSU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case STFDU:
+    case STFD: {
+      int frs = instr->RSValue();
+      int ra = instr->RAValue();
+      int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+      intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+      double frs_val = get_double_from_d_register(frs);
+      int64_t *p = reinterpret_cast<int64_t *>(&frs_val);
+      WriteDW(ra_val + offset, *p);
+      if (opcode == STFDU) {
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+
+    case EXT3:
+      UNIMPLEMENTED();
+    case EXT4: {
+      DecodeExt4(instr);
+      break;
+    }
+
+#if V8_TARGET_ARCH_PPC64
+    case EXT5: {
+      DecodeExt5(instr);
+      break;
+    }
+    case LD: {
+      int ra = instr->RAValue();
+      int rt = instr->RTValue();
+      int64_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
+      switch  (instr->Bits(1, 0)) {
+        case 0:  {  // ld
+          intptr_t *result = ReadDW(ra_val+offset);
+          set_register(rt, *result);
+          break;
+        }
+        case 1: {  // ldu
+          intptr_t *result = ReadDW(ra_val+offset);
+          set_register(rt, *result);
+          ASSERT(ra != 0);
+          set_register(ra, ra_val+offset);
+          break;
+        }
+        case 2: {  // lwa
+          intptr_t result = ReadW(ra_val+offset, instr);
+          set_register(rt, result);
+          break;
+        }
+      }
+      break;
+    }
+
+    case STD: {
+      int ra = instr->RAValue();
+      int rs = instr->RSValue();
+      int64_t ra_val = ra == 0 ? 0 : get_register(ra);
+      int64_t rs_val = get_register(rs);
+      int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
+      WriteDW(ra_val+offset, rs_val);
+      if (instr->Bit(0) == 1) {  // This is the STDU form
+        ASSERT(ra != 0);
+        set_register(ra, ra_val+offset);
+      }
+      break;
+    }
+#endif
+
+    case FAKE_OPCODE: {
+      if (instr->Bits(MARKER_SUBOPCODE_BIT, MARKER_SUBOPCODE_BIT) == 1) {
+        int marker_code = instr->Bits(STUB_MARKER_HIGH_BIT, 0);
+        ASSERT(marker_code < F_NEXT_AVAILABLE_STUB_MARKER);
+        PrintF("Hit stub-marker: %d (EMIT_STUB_MARKER)\n",
+               marker_code);
+      } else {
+        int fake_opcode = instr->Bits(FAKE_OPCODE_HIGH_BIT, 0);
+        if (fake_opcode == fBKPT) {
+          PPCDebugger dbg(this);
+          PrintF("Simulator hit BKPT.\n");
+          dbg.Debug();
+        } else {
+          ASSERT(fake_opcode < fLastFaker);
+          PrintF("Hit ARM opcode: %d(FAKE_OPCODE defined in constant-ppc.h)\n",
+                 fake_opcode);
+          UNIMPLEMENTED();
+        }
+      }
+      break;
+    }
+
+    default: {
+      UNIMPLEMENTED();
+      break;
+    }
+  }
+  if (!pc_modified_) {
+    set_pc(reinterpret_cast<intptr_t>(instr) + Instruction::kInstrSize);
+  }
+}
+
+
+void Simulator::Execute() {
+  // Get the PC to simulate. Cannot use the accessor here as we need the
+  // raw PC value and not the one used as input to arithmetic instructions.
+  intptr_t program_counter = get_pc();
+
+  if (::v8::internal::FLAG_stop_sim_at == 0) {
+    // Fast version of the dispatch loop without checking whether the simulator
+    // should be stopping at a particular executed instruction.
+    while (program_counter != end_sim_pc) {
+      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
+      icount_++;
+      InstructionDecode(instr);
+      program_counter = get_pc();
+    }
+  } else {
+    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
+    // we reach the particular instuction count.
+    while (program_counter != end_sim_pc) {
+      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
+      icount_++;
+      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
+        PPCDebugger dbg(this);
+        dbg.Debug();
+      } else {
+        InstructionDecode(instr);
+      }
+      program_counter = get_pc();
+    }
+  }
+}
+
+
+intptr_t Simulator::Call(byte* entry, int argument_count, ...) {
+  va_list parameters;
+  va_start(parameters, argument_count);
+  // Set up arguments
+
+  // First eight arguments passed in registers r3-r10.
+  int reg_arg_count   = (argument_count > 8) ? 8 : argument_count;
+  int stack_arg_count = argument_count - reg_arg_count;
+  for (int i = 0; i < reg_arg_count; i++) {
+      set_register(i + 3, va_arg(parameters, intptr_t));
+  }
+
+  // Remaining arguments passed on stack.
+  intptr_t original_stack = get_register(sp);
+  // Compute position of stack on entry to generated code.
+  intptr_t entry_stack = (original_stack -
+                          (kNumRequiredStackFrameSlots + stack_arg_count) *
+                          sizeof(intptr_t));
+  if (OS::ActivationFrameAlignment() != 0) {
+    entry_stack &= -OS::ActivationFrameAlignment();
+  }
+  // Store remaining arguments on stack, from low to high memory.
+  // +2 is a hack for the LR slot + old SP on PPC
+  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack) +
+    kStackFrameExtraParamSlot;
+  for (int i = 0; i < stack_arg_count; i++) {
+    stack_argument[i] = va_arg(parameters, intptr_t);
+  }
+  va_end(parameters);
+  set_register(sp, entry_stack);
+
+  // Prepare to execute the code at entry
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  // entry is the function descriptor
+  set_pc(*(reinterpret_cast<intptr_t *>(entry)));
+#else
+  // entry is the instruction address
+  set_pc(reinterpret_cast<intptr_t>(entry));
+#endif
+
+
+
+  // Put down marker for end of simulation. The simulator will stop simulation
+  // when the PC reaches this value. By saving the "end simulation" value into
+  // the LR the simulation stops when returning to this call point.
+  special_reg_lr_ = end_sim_pc;
+
+  // Remember the values of non-volatile registers.
+  intptr_t r2_val = get_register(r2);
+  intptr_t r13_val = get_register(r13);
+  intptr_t r14_val = get_register(r14);
+  intptr_t r15_val = get_register(r15);
+  intptr_t r16_val = get_register(r16);
+  intptr_t r17_val = get_register(r17);
+  intptr_t r18_val = get_register(r18);
+  intptr_t r19_val = get_register(r19);
+  intptr_t r20_val = get_register(r20);
+  intptr_t r21_val = get_register(r21);
+  intptr_t r22_val = get_register(r22);
+  intptr_t r23_val = get_register(r23);
+  intptr_t r24_val = get_register(r24);
+  intptr_t r25_val = get_register(r25);
+  intptr_t r26_val = get_register(r26);
+  intptr_t r27_val = get_register(r27);
+  intptr_t r28_val = get_register(r28);
+  intptr_t r29_val = get_register(r29);
+  intptr_t r30_val = get_register(r30);
+  intptr_t r31_val = get_register(fp);
+
+  // Set up the non-volatile registers with a known value. To be able to check
+  // that they are preserved properly across JS execution.
+  intptr_t callee_saved_value = icount_;
+  set_register(r2, callee_saved_value);
+  set_register(r13, callee_saved_value);
+  set_register(r14, callee_saved_value);
+  set_register(r15, callee_saved_value);
+  set_register(r16, callee_saved_value);
+  set_register(r17, callee_saved_value);
+  set_register(r18, callee_saved_value);
+  set_register(r19, callee_saved_value);
+  set_register(r20, callee_saved_value);
+  set_register(r21, callee_saved_value);
+  set_register(r22, callee_saved_value);
+  set_register(r23, callee_saved_value);
+  set_register(r24, callee_saved_value);
+  set_register(r25, callee_saved_value);
+  set_register(r26, callee_saved_value);
+  set_register(r27, callee_saved_value);
+  set_register(r28, callee_saved_value);
+  set_register(r29, callee_saved_value);
+  set_register(r30, callee_saved_value);
+  set_register(fp, callee_saved_value);
+
+  // Start the simulation
+  Execute();
+
+  // Check that the non-volatile registers have been preserved.
+  CHECK_EQ(callee_saved_value, get_register(r2));
+  CHECK_EQ(callee_saved_value, get_register(r13));
+  CHECK_EQ(callee_saved_value, get_register(r14));
+  CHECK_EQ(callee_saved_value, get_register(r15));
+  CHECK_EQ(callee_saved_value, get_register(r16));
+  CHECK_EQ(callee_saved_value, get_register(r17));
+  CHECK_EQ(callee_saved_value, get_register(r18));
+  CHECK_EQ(callee_saved_value, get_register(r19));
+  CHECK_EQ(callee_saved_value, get_register(r20));
+  CHECK_EQ(callee_saved_value, get_register(r21));
+  CHECK_EQ(callee_saved_value, get_register(r22));
+  CHECK_EQ(callee_saved_value, get_register(r23));
+  CHECK_EQ(callee_saved_value, get_register(r24));
+  CHECK_EQ(callee_saved_value, get_register(r25));
+  CHECK_EQ(callee_saved_value, get_register(r26));
+  CHECK_EQ(callee_saved_value, get_register(r27));
+  CHECK_EQ(callee_saved_value, get_register(r28));
+  CHECK_EQ(callee_saved_value, get_register(r29));
+  CHECK_EQ(callee_saved_value, get_register(r30));
+  CHECK_EQ(callee_saved_value, get_register(fp));
+
+  // Restore non-volatile registers with the original value.
+  set_register(r2, r2_val);
+  set_register(r13, r13_val);
+  set_register(r14, r14_val);
+  set_register(r15, r15_val);
+  set_register(r16, r16_val);
+  set_register(r17, r17_val);
+  set_register(r18, r18_val);
+  set_register(r19, r19_val);
+  set_register(r20, r20_val);
+  set_register(r21, r21_val);
+  set_register(r22, r22_val);
+  set_register(r23, r23_val);
+  set_register(r24, r24_val);
+  set_register(r25, r25_val);
+  set_register(r26, r26_val);
+  set_register(r27, r27_val);
+  set_register(r28, r28_val);
+  set_register(r29, r29_val);
+  set_register(r30, r30_val);
+  set_register(fp, r31_val);
+
+  // Pop stack passed arguments.
+  CHECK_EQ(entry_stack, get_register(sp));
+  set_register(sp, original_stack);
+
+  intptr_t result = get_register(r3);   // PowerPC
+  return result;
+}
+
+
+uintptr_t Simulator::PushAddress(uintptr_t address) {
+  uintptr_t new_sp = get_register(sp) - sizeof(uintptr_t);
+  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
+  *stack_slot = address;
+  set_register(sp, new_sp);
+  return new_sp;
+}
+
+
+uintptr_t Simulator::PopAddress() {
+  uintptr_t current_sp = get_register(sp);
+  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
+  uintptr_t address = *stack_slot;
+  set_register(sp, current_sp + sizeof(uintptr_t));
+  return address;
+}
+
+} }  // namespace v8::internal
+
+#endif  // USE_SIMULATOR
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/ppc/simulator-ppc.h b/src/ppc/simulator-ppc.h
new file mode 100644
index 0000000..bf748a95
--- /dev/null
+++ b/src/ppc/simulator-ppc.h
@@ -0,0 +1,410 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Declares a Simulator for PPC instructions if we are not generating a native
+// PPC binary. This Simulator allows us to run and debug PPC code generation on
+// regular desktop machines.
+// V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro,
+// which will start execution in the Simulator or forwards to the real entry
+// on a PPC HW platform.
+
+#ifndef V8_PPC_SIMULATOR_PPC_H_
+#define V8_PPC_SIMULATOR_PPC_H_
+
+#include "allocation.h"
+
+#if !defined(USE_SIMULATOR)
+// Running without a simulator on a native ppc platform.
+
+namespace v8 {
+namespace internal {
+
+// When running without a simulator we call the entry directly.
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
+  (entry(p0, p1, p2, p3, p4))
+
+typedef int (*ppc_regexp_matcher)(String*, int, const byte*, const byte*,
+                                  int*, int, Address, int, void*, Isolate*);
+
+
+// Call the generated regexp code directly. The code at the entry address
+// should act as a function matching the type ppc_regexp_matcher.
+// The ninth argument is a dummy that reserves the space used for
+// the return address added by the ExitFrame in native calls.
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
+  (FUNCTION_CAST<ppc_regexp_matcher>(entry)(                              \
+      p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
+
+#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
+  reinterpret_cast<TryCatch*>(try_catch_address)
+
+// The stack limit beyond which we will throw stack overflow errors in
+// generated code. Because generated code on ppc uses the C stack, we
+// just use the C stack limit.
+class SimulatorStack : public v8::internal::AllStatic {
+ public:
+  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
+                                            uintptr_t c_limit) {
+    USE(isolate);
+    return c_limit;
+  }
+
+  static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
+    return try_catch_address;
+  }
+
+  static inline void UnregisterCTryCatch() { }
+};
+
+} }  // namespace v8::internal
+
+#else  // !defined(USE_SIMULATOR)
+// Running with a simulator.
+
+#include "constants-ppc.h"
+#include "hashmap.h"
+#include "assembler.h"
+
+namespace v8 {
+namespace internal {
+
+class CachePage {
+ public:
+  static const int LINE_VALID = 0;
+  static const int LINE_INVALID = 1;
+
+  static const int kPageShift = 12;
+  static const int kPageSize = 1 << kPageShift;
+  static const int kPageMask = kPageSize - 1;
+  static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
+  static const int kLineLength = 1 << kLineShift;
+  static const int kLineMask = kLineLength - 1;
+
+  CachePage() {
+    memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
+  }
+
+  char* ValidityByte(int offset) {
+    return &validity_map_[offset >> kLineShift];
+  }
+
+  char* CachedData(int offset) {
+    return &data_[offset];
+  }
+
+ private:
+  char data_[kPageSize];   // The cached data.
+  static const int kValidityMapSize = kPageSize >> kLineShift;
+  char validity_map_[kValidityMapSize];  // One byte per line.
+};
+
+
+class Simulator {
+ public:
+  friend class PPCDebugger;
+  enum Register {
+    no_reg = -1,
+    r0 = 0, sp, r2, r3, r4, r5, r6, r7,
+    r8, r9, r10, r11, r12, r13, r14, r15,
+    r16, r17, r18, r19, r20, r21, r22, r23,
+    r24, r25, r26, r27, r28, r29, r30, fp,
+    kNumGPRs = 32,
+    d0 = 0, d1, d2, d3, d4, d5, d6, d7,
+    d8, d9, d10, d11, d12, d13, d14, d15,
+    d16, d17, d18, d19, d20, d21, d22, d23,
+    d24, d25, d26, d27, d28, d29, d30, d31,
+    kNumFPRs = 32
+  };
+
+  explicit Simulator(Isolate* isolate);
+  ~Simulator();
+
+  // The currently executing Simulator instance. Potentially there can be one
+  // for each native thread.
+  static Simulator* current(v8::internal::Isolate* isolate);
+
+  // Accessors for register state.
+  void set_register(int reg, intptr_t value);
+  intptr_t get_register(int reg) const;
+  double get_double_from_register_pair(int reg);
+  void set_d_register_from_double(int dreg, const double dbl) {
+    ASSERT(dreg >= 0 && dreg < kNumFPRs);
+    fp_register[dreg] = dbl;
+  }
+  double get_double_from_d_register(int dreg) {
+    return fp_register[dreg];
+  }
+
+  // Special case of set_register and get_register to access the raw PC value.
+  void set_pc(intptr_t value);
+  intptr_t get_pc() const;
+
+  // Accessor to the internal simulator stack area.
+  uintptr_t StackLimit() const;
+
+  // Executes PPC instructions until the PC reaches end_sim_pc.
+  void Execute();
+
+  // Call on program start.
+  static void Initialize(Isolate* isolate);
+
+  // V8 generally calls into generated JS code with 5 parameters and into
+  // generated RegExp code with 7 parameters. This is a convenience function,
+  // which sets up the simulator state and grabs the result on return.
+  intptr_t Call(byte* entry, int argument_count, ...);
+
+  // Push an address onto the JS stack.
+  uintptr_t PushAddress(uintptr_t address);
+
+  // Pop an address from the JS stack.
+  uintptr_t PopAddress();
+
+  // Debugger input.
+  void set_last_debugger_input(char* input);
+  char* last_debugger_input() { return last_debugger_input_; }
+
+  // ICache checking.
+  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
+                          size_t size);
+
+  // Returns true if pc register contains one of the 'special_values' defined
+  // below (bad_lr, end_sim_pc).
+  bool has_bad_pc() const;
+
+ private:
+  enum special_values {
+    // Known bad pc value to ensure that the simulator does not execute
+    // without being properly setup.
+    bad_lr = -1,
+    // A pc value used to signal the simulator to stop execution.  Generally
+    // the lr is set to this value on transition from native C code to
+    // simulated execution, so that the simulator can "return" to the native
+    // C code.
+    end_sim_pc = -2
+  };
+
+  // Unsupported instructions use Format to print an error and stop execution.
+  void Format(Instruction* instr, const char* format);
+
+  // Helper functions to set the conditional flags in the architecture state.
+  bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
+  bool BorrowFrom(int32_t left, int32_t right);
+  bool OverflowFrom(int32_t alu_out,
+                    int32_t left,
+                    int32_t right,
+                    bool addition);
+
+  // Helper functions to decode common "addressing" modes
+  int32_t GetShiftRm(Instruction* instr, bool* carry_out);
+  int32_t GetImm(Instruction* instr, bool* carry_out);
+  void ProcessPUW(Instruction* instr,
+                  int num_regs,
+                  int operand_size,
+                  intptr_t* start_address,
+                  intptr_t* end_address);
+  void HandleRList(Instruction* instr, bool load);
+  void HandleVList(Instruction* inst);
+  void SoftwareInterrupt(Instruction* instr);
+
+  // Stop helper functions.
+  inline bool isStopInstruction(Instruction* instr);
+  inline bool isWatchedStop(uint32_t bkpt_code);
+  inline bool isEnabledStop(uint32_t bkpt_code);
+  inline void EnableStop(uint32_t bkpt_code);
+  inline void DisableStop(uint32_t bkpt_code);
+  inline void IncreaseStopCounter(uint32_t bkpt_code);
+  void PrintStopInfo(uint32_t code);
+
+  // Read and write memory.
+  inline uint8_t ReadBU(intptr_t addr);
+  inline int8_t ReadB(intptr_t addr);
+  inline void WriteB(intptr_t addr, uint8_t value);
+  inline void WriteB(intptr_t addr, int8_t value);
+
+  inline uint16_t ReadHU(intptr_t addr, Instruction* instr);
+  inline int16_t ReadH(intptr_t addr, Instruction* instr);
+  // Note: Overloaded on the sign of the value.
+  inline void WriteH(intptr_t addr, uint16_t value, Instruction* instr);
+  inline void WriteH(intptr_t addr, int16_t value, Instruction* instr);
+
+  inline uint32_t ReadWU(intptr_t addr, Instruction* instr);
+  inline int32_t ReadW(intptr_t addr, Instruction* instr);
+  inline void WriteW(intptr_t addr, uint32_t value, Instruction* instr);
+  inline void WriteW(intptr_t addr, int32_t value, Instruction* instr);
+
+  intptr_t* ReadDW(intptr_t addr);
+  void WriteDW(intptr_t addr, int64_t value);
+
+  // PowerPC
+  void SetCR0(intptr_t result, bool setSO = false);
+  void DecodeBranchConditional(Instruction* instr);
+  void DecodeExt1(Instruction* instr);
+  bool DecodeExt2_10bit(Instruction* instr);
+  void DecodeExt2_9bit(Instruction* instr);
+  void DecodeExt2(Instruction* instr);
+  void DecodeExt4(Instruction* instr);
+#if V8_TARGET_ARCH_PPC64
+  void DecodeExt5(Instruction* instr);
+#endif
+
+  // Executes one instruction.
+  void InstructionDecode(Instruction* instr);
+
+  // ICache.
+  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
+                           int size);
+  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+
+  // Runtime call support.
+  static void* RedirectExternalReference(
+      void* external_function,
+      v8::internal::ExternalReference::Type type);
+
+  // For use in calls that take double value arguments.
+  void GetFpArgs(double* x, double* y);
+  void GetFpArgs(double* x);
+  void GetFpArgs(double* x, intptr_t* y);
+  void SetFpResult(const double& result);
+  void TrashCallerSaveRegisters();
+
+  template<class ReturnType, int register_size>
+      ReturnType GetFromFPRegister(int reg_index);
+
+  template<class InputType, int register_size>
+      void SetFPRegister(int reg_index, const InputType& value);
+
+  // Architecture state.
+  // Saturating instructions require a Q flag to indicate saturation.
+  // There is currently no way to read the CPSR directly, and thus read the Q
+  // flag, so this is left unimplemented.
+  intptr_t registers_[kNumGPRs];  // PowerPC
+  int32_t condition_reg_;  // PowerPC
+  int32_t fp_condition_reg_;  // PowerPC
+  intptr_t special_reg_lr_;  // PowerPC
+  intptr_t special_reg_pc_;  // PowerPC
+  intptr_t special_reg_ctr_;  // PowerPC
+  int32_t special_reg_xer_;  // PowerPC
+
+  double fp_register[kNumFPRs];
+
+  // Simulator support.
+  char* stack_;
+  bool pc_modified_;
+  int icount_;
+
+  // Debugger input.
+  char* last_debugger_input_;
+
+  // Icache simulation
+  v8::internal::HashMap* i_cache_;
+
+  // Registered breakpoints.
+  Instruction* break_pc_;
+  Instr break_instr_;
+
+  v8::internal::Isolate* isolate_;
+
+  // A stop is watched if its code is less than kNumOfWatchedStops.
+  // Only watched stops support enabling/disabling and the counter feature.
+  static const uint32_t kNumOfWatchedStops = 256;
+
+  // Breakpoint is disabled if bit 31 is set.
+  static const uint32_t kStopDisabledBit = 1 << 31;
+
+  // A stop is enabled, meaning the simulator will stop when meeting the
+  // instruction, if bit 31 of watched_stops[code].count is unset.
+  // The value watched_stops[code].count & ~(1 << 31) indicates how many times
+  // the breakpoint was hit or gone through.
+  struct StopCountAndDesc {
+    uint32_t count;
+    char* desc;
+  };
+  StopCountAndDesc watched_stops[kNumOfWatchedStops];
+};
+
+
+// When running with the simulator transition into simulated execution at this
+// point.
+#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
+  reinterpret_cast<Object*>(Simulator::current(Isolate::Current())->Call( \
+                              FUNCTION_ADDR(entry), 5,                  \
+                              (intptr_t)p0,                             \
+                              (intptr_t)p1,                             \
+                              (intptr_t)p2,                             \
+                              (intptr_t)p3,                             \
+                              (intptr_t)p4))
+
+#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \
+  Simulator::current(Isolate::Current())->Call(                         \
+    entry, 10,                                                          \
+    (intptr_t)p0,                                                       \
+    (intptr_t)p1,                                                       \
+    (intptr_t)p2,                                                       \
+    (intptr_t)p3,                                                       \
+    (intptr_t)p4,                                                       \
+    (intptr_t)p5,                                                       \
+    (intptr_t)p6,                                                       \
+    (intptr_t)p7,                                                       \
+    (intptr_t)NULL,                                                     \
+    (intptr_t)p8)
+
+#define TRY_CATCH_FROM_ADDRESS(try_catch_address)                              \
+  try_catch_address == NULL ?                                                  \
+      NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
+
+
+// The simulator has its own stack. Thus it has a different stack limit from
+// the C-based native code.  Setting the c_limit to indicate a very small
+// stack cause stack overflow errors, since the simulator ignores the input.
+// This is unlikely to be an issue in practice, though it might cause testing
+// trouble down the line.
+class SimulatorStack : public v8::internal::AllStatic {
+ public:
+  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
+                                            uintptr_t c_limit) {
+    return Simulator::current(isolate)->StackLimit();
+  }
+
+  static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
+    Simulator* sim = Simulator::current(Isolate::Current());
+    return sim->PushAddress(try_catch_address);
+  }
+
+  static inline void UnregisterCTryCatch() {
+    Simulator::current(Isolate::Current())->PopAddress();
+  }
+};
+
+} }  // namespace v8::internal
+
+#endif  // !defined(USE_SIMULATOR)
+#endif  // V8_PPC_SIMULATOR_PPC_H_
diff --git a/src/ppc/stub-cache-ppc.cc b/src/ppc/stub-cache-ppc.cc
new file mode 100644
index 0000000..cbf6ae8
--- /dev/null
+++ b/src/ppc/stub-cache-ppc.cc
@@ -0,0 +1,4466 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+//
+// Copyright IBM Corp. 2012, 2013. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#if defined(V8_TARGET_ARCH_PPC)
+
+#include "ic-inl.h"
+#include "codegen.h"
+#include "stub-cache.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm)
+
+static void ProbeTable(Isolate* isolate,
+                       MacroAssembler* masm,
+                       Code::Flags flags,
+                       StubCache::Table table,
+                       Register receiver,
+                       Register name,
+                       // Number of the cache entry, not scaled.
+                       Register offset,
+                       Register scratch,
+                       Register scratch2,
+                       Register offset_scratch) {
+  ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
+  ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
+  ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
+
+  uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address());
+  uintptr_t value_off_addr =
+                         reinterpret_cast<uintptr_t>(value_offset.address());
+  uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address());
+
+  // Check the relative positions of the address fields.
+  ASSERT(value_off_addr > key_off_addr);
+  ASSERT((value_off_addr - key_off_addr) % 4 == 0);
+  ASSERT((value_off_addr - key_off_addr) < (256 * 4));
+  ASSERT(map_off_addr > key_off_addr);
+  ASSERT((map_off_addr - key_off_addr) % 4 == 0);
+  ASSERT((map_off_addr - key_off_addr) < (256 * 4));
+
+  Label miss;
+  Register base_addr = scratch;
+  scratch = no_reg;
+
+  // Multiply by 3 because there are 3 fields per entry (name, code, map).
+  __ ShiftLeftImm(offset_scratch, offset, Operand(1));
+  __ add(offset_scratch, offset, offset_scratch);
+
+  // Calculate the base address of the entry.
+  __ mov(base_addr, Operand(key_offset));
+  __ ShiftLeftImm(scratch2, offset_scratch, Operand(kPointerSizeLog2));
+  __ add(base_addr, base_addr, scratch2);
+
+  // Check that the key in the entry matches the name.
+  __ LoadP(ip, MemOperand(base_addr, 0));
+  __ cmp(name, ip);
+  __ bne(&miss);
+
+  // Check the map matches.
+  __ LoadP(ip, MemOperand(base_addr, map_off_addr - key_off_addr));
+  __ LoadP(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ cmp(ip, scratch2);
+  __ bne(&miss);
+
+  // Get the code entry from the cache.
+  Register code = scratch2;
+  scratch2 = no_reg;
+  __ LoadP(code, MemOperand(base_addr, value_off_addr - key_off_addr));
+
+  // Check that the flags match what we're looking for.
+  Register flags_reg = base_addr;
+  base_addr = no_reg;
+  __ lwz(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
+
+  ASSERT(!r0.is(flags_reg));
+  __ li(r0, Operand(Code::kFlagsNotUsedInLookup));
+  __ andc(flags_reg, flags_reg, r0);
+  __ mov(r0, Operand(flags));
+  __ cmpl(flags_reg, r0);
+  __ bne(&miss);
+
+#ifdef DEBUG
+    if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
+      __ b(&miss);
+    } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
+      __ b(&miss);
+    }
+#endif
+
+  // Jump to the first instruction in the code stub.
+  __ addi(r0, code, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ mtctr(r0);
+  __ bcr();
+
+  // Miss: fall through.
+  __ bind(&miss);
+}
+
+
+// Helper function used to check that the dictionary doesn't contain
+// the property. This function may return false negatives, so miss_label
+// must always call a backup property check that is complete.
+// This function is safe to call if the receiver has fast properties.
+// Name must be a symbol and receiver must be a heap object.
+static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
+                                             Label* miss_label,
+                                             Register receiver,
+                                             Handle<String> name,
+                                             Register scratch0,
+                                             Register scratch1) {
+  ASSERT(name->IsSymbol());
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
+  __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
+
+  Label done;
+
+  const int kInterceptorOrAccessCheckNeededMask =
+      (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
+
+  // Bail out if the receiver has a named interceptor or requires access checks.
+  Register map = scratch1;
+  __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
+  __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
+  __ bne(miss_label, cr0);
+
+  // Check that receiver is a JSObject.
+  __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  __ cmpi(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
+  __ blt(miss_label);
+
+  // Load properties array.
+  Register properties = scratch0;
+  __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+  // Check that the properties array is a dictionary.
+  __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset));
+  Register tmp = properties;
+  __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
+  __ cmp(map, tmp);
+  __ bne(miss_label);
+
+  // Restore the temporarily used register.
+  __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+
+
+  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
+                                                     miss_label,
+                                                     &done,
+                                                     receiver,
+                                                     properties,
+                                                     name,
+                                                     scratch1);
+  __ bind(&done);
+  __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
+}
+
+
+void StubCache::GenerateProbe(MacroAssembler* masm,
+                              Code::Flags flags,
+                              Register receiver,
+                              Register name,
+                              Register scratch,
+                              Register extra,
+                              Register extra2,
+                              Register extra3) {
+  Isolate* isolate = masm->isolate();
+  Label miss;
+
+#if V8_TARGET_ARCH_PPC64
+  // Make sure that code is valid. The multiplying code relies on the
+  // entry size being 24.
+  ASSERT(sizeof(Entry) == 24);
+#else
+  // Make sure that code is valid. The multiplying code relies on the
+  // entry size being 12.
+  ASSERT(sizeof(Entry) == 12);
+#endif
+
+  // Make sure the flags does not name a specific type.
+  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
+
+  // Make sure that there are no register conflicts.
+  ASSERT(!scratch.is(receiver));
+  ASSERT(!scratch.is(name));
+  ASSERT(!extra.is(receiver));
+  ASSERT(!extra.is(name));
+  ASSERT(!extra.is(scratch));
+  ASSERT(!extra2.is(receiver));
+  ASSERT(!extra2.is(name));
+  ASSERT(!extra2.is(scratch));
+  ASSERT(!extra2.is(extra));
+
+  // Check scratch, extra and extra2 registers are valid.
+  ASSERT(!scratch.is(no_reg));
+  ASSERT(!extra.is(no_reg));
+  ASSERT(!extra2.is(no_reg));
+  ASSERT(!extra3.is(no_reg));
+
+  Counters* counters = masm->isolate()->counters();
+  __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
+                      extra2, extra3);
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, &miss);
+
+  // Get the map of the receiver and compute the hash.
+  __ lwz(scratch, FieldMemOperand(name, String::kHashFieldOffset));
+  __ LoadP(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ add(scratch, scratch, ip);
+#if V8_TARGET_ARCH_PPC64
+  // Use only the low 32 bits of the map pointer.
+  __ rldicl(scratch, scratch, 0, 32);
+#endif
+  uint32_t mask = kPrimaryTableSize - 1;
+  // We shift out the last two bits because they are not part of the hash and
+  // they are always 01 for maps.
+  __ ShiftRightImm(scratch, scratch, Operand(kHeapObjectTagSize));
+  // Mask down the eor argument to the minimum to keep the immediate
+  // encodable.
+  __ xori(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask));
+  // Prefer and_ to ubfx here because ubfx takes 2 cycles.
+  __ andi(scratch, scratch, Operand(mask));
+
+  // Probe the primary table.
+  ProbeTable(isolate,
+             masm,
+             flags,
+             kPrimary,
+             receiver,
+             name,
+             scratch,
+             extra,
+             extra2,
+             extra3);
+
+  // Primary miss: Compute hash for secondary probe.
+  __ ShiftRightImm(extra, name, Operand(kHeapObjectTagSize));
+  __ sub(scratch, scratch, extra);
+  uint32_t mask2 = kSecondaryTableSize - 1;
+  __ addi(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2));
+  __ andi(scratch, scratch, Operand(mask2));
+
+  // Probe the secondary table.
+  ProbeTable(isolate,
+             masm,
+             flags,
+             kSecondary,
+             receiver,
+             name,
+             scratch,
+             extra,
+             extra2,
+             extra3);
+
+  // Cache miss: Fall-through and let caller handle the miss by
+  // entering the runtime system.
+  __ bind(&miss);
+  __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
+                      extra2, extra3);
+}
+
+
+void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
+                                                       int index,
+                                                       Register prototype) {
+  // Load the global or builtins object from the current context.
+  __ LoadP(prototype,
+           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  // Load the native context from the global or builtins object.
+  __ LoadP(prototype,
+           FieldMemOperand(prototype, GlobalObject::kNativeContextOffset));
+  // Load the function from the native context.
+  __ LoadP(prototype, MemOperand(prototype, Context::SlotOffset(index)), r0);
+  // Load the initial map.  The global functions all have initial maps.
+  __ LoadP(prototype,
+           FieldMemOperand(prototype,
+                           JSFunction::kPrototypeOrInitialMapOffset));
+  // Load the prototype from the initial map.
+  __ LoadP(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
+}
+
+
+void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
+    MacroAssembler* masm,
+    int index,
+    Register prototype,
+    Label* miss) {
+  Isolate* isolate = masm->isolate();
+  // Check we're still in the same context.
+  __ LoadP(prototype,
+           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ Move(ip, isolate->global_object());
+  __ cmp(prototype, ip);
+  __ bne(miss);
+  // Get the global function with the given index.
+  Handle<JSFunction> function(
+      JSFunction::cast(isolate->native_context()->get(index)));
+  // Load its initial map. The global functions all have initial maps.
+  __ Move(prototype, Handle<Map>(function->initial_map()));
+  // Load the prototype from the initial map.
+  __ LoadP(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
+}
+
+
+// Load a fast property out of a holder object (src). In-object properties
+// are loaded directly otherwise the property is loaded from the properties
+// fixed array.
+void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
+                                            Register dst,
+                                            Register src,
+                                            Handle<JSObject> holder,
+                                            int index) {
+  // Adjust for the number of properties stored in the holder.
+  index -= holder->map()->inobject_properties();
+  if (index < 0) {
+    // Get the property straight out of the holder.
+    int offset = holder->map()->instance_size() + (index * kPointerSize);
+    __ LoadP(dst, FieldMemOperand(src, offset), r0);
+  } else {
+    // Calculate the offset into the properties array.
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
+    __ LoadP(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
+    __ LoadP(dst, FieldMemOperand(dst, offset), r0);
+  }
+}
+
+
+void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register scratch,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, miss_label);
+
+  // Check that the object is a JS array.
+  __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
+  __ bne(miss_label);
+
+  // Load length directly from the JS array.
+  __ LoadP(r3, FieldMemOperand(receiver, JSArray::kLengthOffset));
+  __ Ret();
+}
+
+
+// Generate code to check if an object is a string.  If the object is a
+// heap object, its map's instance type is left in the scratch1 register.
+// If this is not needed, scratch1 and scratch2 may be the same register.
+static void GenerateStringCheck(MacroAssembler* masm,
+                                Register receiver,
+                                Register scratch1,
+                                Register scratch2,
+                                Label* smi,
+                                Label* non_string_object) {
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, smi);
+
+  // Check that the object is a string.
+  __ LoadP(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ lbz(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ andi(scratch2, scratch1, Operand(kIsNotStringMask));
+  // The cast is to resolve the overload for the argument of 0x0.
+  __ cmpi(scratch2, Operand(static_cast<intptr_t>(kStringTag)));
+  __ bne(non_string_object);
+}
+
+
+// Generate code to load the length from a string object and return the length.
+// If the receiver object is not a string or a wrapped string object the
+// execution continues at the miss label. The register containing the
+// receiver is potentially clobbered.
+void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
+                                            Register receiver,
+                                            Register scratch1,
+                                            Register scratch2,
+                                            Label* miss,
+                                            bool support_wrappers) {
+  Label check_wrapper;
+
+  // Check if the object is a string leaving the instance type in the
+  // scratch1 register.
+  GenerateStringCheck(masm, receiver, scratch1, scratch2, miss,
+                      support_wrappers ? &check_wrapper : miss);
+
+  // Load length directly from the string.
+  __ LoadP(r3, FieldMemOperand(receiver, String::kLengthOffset));
+  __ Ret();
+
+  if (support_wrappers) {
+    // Check if the object is a JSValue wrapper.
+    __ bind(&check_wrapper);
+    __ cmpi(scratch1, Operand(JS_VALUE_TYPE));
+    __ bne(miss);
+
+    // Unwrap the value and check if the wrapped value is a string.
+    __ LoadP(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
+    GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
+    __ LoadP(r3, FieldMemOperand(scratch1, String::kLengthOffset));
+    __ Ret();
+  }
+}
+
+
+void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
+                                                 Register receiver,
+                                                 Register scratch1,
+                                                 Register scratch2,
+                                                 Label* miss_label) {
+  __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
+  __ mr(r3, scratch1);
+  __ Ret();
+}
+
+
+// Generate StoreField code, value is passed in r3 register.
+// When leaving generated code after success, the receiver_reg and name_reg
+// may be clobbered.  Upon branch to miss_label, the receiver and name
+// registers have their original values.
+void StubCompiler::GenerateStoreField(MacroAssembler* masm,
+                                      Handle<JSObject> object,
+                                      int index,
+                                      Handle<Map> transition,
+                                      Handle<String> name,
+                                      Register receiver_reg,
+                                      Register name_reg,
+                                      Register scratch1,
+                                      Register scratch2,
+                                      Label* miss_label) {
+  // r3 : value
+  Label exit;
+
+  LookupResult lookup(masm->isolate());
+  object->Lookup(*name, &lookup);
+  if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
+    // In sloppy mode, we could just return the value and be done. However, we
+    // might be in strict mode, where we have to throw. Since we cannot tell,
+    // go into slow case unconditionally.
+    __ b(miss_label);
+    return;
+  }
+
+  // Check that the map of the object hasn't changed.
+  CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
+                                             : REQUIRE_EXACT_MAP;
+  __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
+              DO_SMI_CHECK, mode);
+
+  // Perform global security token check if needed.
+  if (object->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
+  }
+
+  // Check that we are allowed to write this.
+  if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
+    JSObject* holder;
+    if (lookup.IsFound()) {
+      holder = lookup.holder();
+    } else {
+      // Find the top object.
+      holder = *object;
+      do {
+        holder = JSObject::cast(holder->GetPrototype());
+      } while (holder->GetPrototype()->IsJSObject());
+    }
+    // We need an extra register, push
+    __ push(name_reg);
+    Label miss_pop, done_check;
+    CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
+                    scratch1, scratch2, name, &miss_pop);
+    __ b(&done_check);
+    __ bind(&miss_pop);
+    __ pop(name_reg);
+    __ b(miss_label);
+    __ bind(&done_check);
+    __ pop(name_reg);
+  }
+
+  // Stub never generated for non-global objects that require access
+  // checks.
+  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
+
+  // Perform map transition for the receiver if necessary.
+  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
+    // The properties must be extended before we can store the value.
+    // We jump to a runtime call that extends the properties array.
+    __ push(receiver_reg);
+    __ mov(r5, Operand(transition));
+    __ Push(r5, r3);
+    __ TailCallExternalReference(
+        ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
+                          masm->isolate()),
+        3,
+        1);
+    return;
+  }
+
+  if (!transition.is_null()) {
+    // Update the map of the object.
+    __ mov(scratch1, Operand(transition));
+    __ StoreP(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset),
+              r0);
+
+    // Update the write barrier for the map field and pass the now unused
+    // name_reg as scratch register.
+    __ RecordWriteField(receiver_reg,
+                        HeapObject::kMapOffset,
+                        scratch1,
+                        name_reg,
+                        kLRHasNotBeenSaved,
+                        kDontSaveFPRegs,
+                        OMIT_REMEMBERED_SET,
+                        OMIT_SMI_CHECK);
+  }
+
+  // Adjust for the number of properties stored in the object. Even in the
+  // face of a transition we can use the old map here because the size of the
+  // object and the number of in-object properties is not going to change.
+  index -= object->map()->inobject_properties();
+
+  if (index < 0) {
+    // Set the property straight into the object.
+    int offset = object->map()->instance_size() + (index * kPointerSize);
+    __ StoreP(r3, FieldMemOperand(receiver_reg, offset), r0);
+
+    // Skip updating write barrier if storing a smi.
+    __ JumpIfSmi(r3, &exit);
+
+    // Update the write barrier for the array address.
+    // Pass the now unused name_reg as a scratch register.
+    __ mr(name_reg, r3);
+    __ RecordWriteField(receiver_reg,
+                        offset,
+                        name_reg,
+                        scratch1,
+                        kLRHasNotBeenSaved,
+                        kDontSaveFPRegs);
+  } else {
+    // Write to the properties array.
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
+    // Get the properties array
+    __ LoadP(scratch1,
+             FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
+    __ StoreP(r3, FieldMemOperand(scratch1, offset), r0);
+
+    // Skip updating write barrier if storing a smi.
+    __ JumpIfSmi(r3, &exit);
+
+    // Update the write barrier for the array address.
+    // Ok to clobber receiver_reg and name_reg, since we return.
+    __ mr(name_reg, r3);
+    __ RecordWriteField(scratch1,
+                        offset,
+                        name_reg,
+                        receiver_reg,
+                        kLRHasNotBeenSaved,
+                        kDontSaveFPRegs);
+  }
+
+  // Return the value (register r3).
+  __ bind(&exit);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
+  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
+  Handle<Code> code = (kind == Code::LOAD_IC)
+      ? masm->isolate()->builtins()->LoadIC_Miss()
+      : masm->isolate()->builtins()->KeyedLoadIC_Miss();
+  __ Jump(code, RelocInfo::CODE_TARGET);
+}
+
+
+static void GenerateCallFunction(MacroAssembler* masm,
+                                 Handle<Object> object,
+                                 const ParameterCount& arguments,
+                                 Label* miss,
+                                 Code::ExtraICState extra_ic_state) {
+  // ----------- S t a t e -------------
+  //  -- r3: receiver
+  //  -- r4: function to call
+  // -----------------------------------
+
+  // Check that the function really is a function.
+  __ JumpIfSmi(r4, miss);
+  __ CompareObjectType(r4, r6, r6, JS_FUNCTION_TYPE);
+  __ bne(miss);
+
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ LoadP(r6, FieldMemOperand(r3, GlobalObject::kGlobalReceiverOffset));
+    __ StoreP(r6, MemOperand(sp, arguments.immediate() * kPointerSize), r0);
+  }
+
+  // Invoke the function.
+  CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  __ InvokeFunction(r4, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}
+
+
+static void PushInterceptorArguments(MacroAssembler* masm,
+                                     Register receiver,
+                                     Register holder,
+                                     Register name,
+                                     Handle<JSObject> holder_obj) {
+  __ push(name);
+  Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
+  ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
+  Register scratch = name;
+  __ mov(scratch, Operand(interceptor));
+  __ push(scratch);
+  __ push(receiver);
+  __ push(holder);
+  __ LoadP(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset));
+  __ push(scratch);
+  __ mov(scratch, Operand(ExternalReference::isolate_address()));
+  __ push(scratch);
+}
+
+
+static void CompileCallLoadPropertyWithInterceptor(
+    MacroAssembler* masm,
+    Register receiver,
+    Register holder,
+    Register name,
+    Handle<JSObject> holder_obj) {
+  PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
+
+  ExternalReference ref =
+      ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
+                        masm->isolate());
+  __ li(r3, Operand(6));
+  __ mov(r4, Operand(ref));
+
+  CEntryStub stub(1);
+  __ CallStub(&stub);
+}
+
+
+static const int kFastApiCallArguments = 4;
+
+// Reserves space for the extra arguments to API function in the
+// caller's frame.
+//
+// These arguments are set by CheckPrototypes and GenerateFastApiDirectCall.
+static void ReserveSpaceForFastApiCall(MacroAssembler* masm,
+                                       Register scratch) {
+  __ LoadSmiLiteral(scratch, Smi::FromInt(0));
+  for (int i = 0; i < kFastApiCallArguments; i++) {
+    __ push(scratch);
+  }
+}
+
+
+// Undoes the effects of ReserveSpaceForFastApiCall.
+static void FreeSpaceForFastApiCall(MacroAssembler* masm) {
+  __ Drop(kFastApiCallArguments);
+}
+
+
+static void GenerateFastApiDirectCall(MacroAssembler* masm,
+                                      const CallOptimization& optimization,
+                                      int argc) {
+  // ----------- S t a t e -------------
+  //  -- sp[0]              : holder (set by CheckPrototypes)
+  //  -- sp[4]              : callee JS function
+  //  -- sp[8]              : call data
+  //  -- sp[12]             : isolate
+  //  -- sp[16]             : last JS argument
+  //  -- ...
+  //  -- sp[(argc + 3) * 4] : first JS argument
+  //  -- sp[(argc + 4) * 4] : receiver
+  // -----------------------------------
+  // Get the function and setup the context.
+  Handle<JSFunction> function = optimization.constant_function();
+  __ LoadHeapObject(r8, function);
+  __ LoadP(cp, FieldMemOperand(r8, JSFunction::kContextOffset));
+
+  // Pass the additional arguments.
+  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
+  Handle<Object> call_data(api_call_info->data());
+  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
+    __ Move(r3, api_call_info);
+    __ LoadP(r9, FieldMemOperand(r3, CallHandlerInfo::kDataOffset));
+  } else {
+    __ Move(r9, call_data);
+  }
+  __ mov(r10, Operand(ExternalReference::isolate_address()));
+  // Store JS function, call data and isolate.
+  __ StoreP(r8, MemOperand(sp, 1 * kPointerSize));
+  __ StoreP(r9, MemOperand(sp, 2 * kPointerSize));
+  __ StoreP(r10, MemOperand(sp, 3 * kPointerSize));
+
+  // Prepare arguments.
+  __ addi(r5, sp, Operand(3 * kPointerSize));
+
+#if !ABI_RETURNS_HANDLES_IN_REGS
+  bool alloc_return_buf = true;
+#else
+  bool alloc_return_buf = false;
+#endif
+
+  // Allocate the v8::Arguments structure in the arguments' space since
+  // it's not controlled by GC.
+  // PPC LINUX ABI:
+  //
+  // Create 5 or 6 extra slots on stack (depending on alloc_return_buf):
+  //    [0] space for DirectCEntryStub's LR save
+  //    [1] space for pointer-sized non-scalar return value (r3)
+  //    [2-5] v8:Arguments
+  //
+  // If alloc_return buf, we shift the arguments over a register
+  // (e.g. r3 -> r4) to allow for the return value buffer in implicit
+  // first arg.  CallApiFunctionAndReturn will setup r3.
+  int kApiStackSpace = 5 + (alloc_return_buf ? 1 : 0);
+  Register arg0 = alloc_return_buf ? r4 : r3;
+
+  FrameScope frame_scope(masm, StackFrame::MANUAL);
+  __ EnterExitFrame(false, kApiStackSpace);
+
+  // scalar and return
+
+  // arg0 = v8::Arguments&
+  // Arguments is after the return address.
+  __ addi(arg0, sp, Operand((kStackFrameExtraParamSlot +
+           (alloc_return_buf ? 2 : 1)) * kPointerSize));
+  // v8::Arguments::implicit_args_
+  __ StoreP(r5, MemOperand(arg0, 0 * kPointerSize));
+  // v8::Arguments::values_
+  __ addi(ip, r5, Operand(argc * kPointerSize));
+  __ StoreP(ip, MemOperand(arg0, 1 * kPointerSize));
+  // v8::Arguments::length_ = argc
+  __ li(ip, Operand(argc));
+  __ stw(ip, MemOperand(arg0, 2 * kPointerSize));
+  // v8::Arguments::is_construct_call = 0
+  __ li(ip, Operand::Zero());
+  __ StoreP(ip, MemOperand(arg0, 3 * kPointerSize));
+
+  const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
+  Address function_address = v8::ToCData<Address>(api_call_info->callback());
+  ApiFunction fun(function_address);
+  ExternalReference ref = ExternalReference(&fun,
+                                            ExternalReference::DIRECT_API_CALL,
+                                            masm->isolate());
+  AllowExternalCallThatCantCauseGC scope(masm);
+
+  __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
+}
+
+
+class CallInterceptorCompiler BASE_EMBEDDED {
+ public:
+  CallInterceptorCompiler(StubCompiler* stub_compiler,
+                          const ParameterCount& arguments,
+                          Register name,
+                          Code::ExtraICState extra_ic_state)
+      : stub_compiler_(stub_compiler),
+        arguments_(arguments),
+        name_(name),
+        extra_ic_state_(extra_ic_state) {}
+
+  void Compile(MacroAssembler* masm,
+               Handle<JSObject> object,
+               Handle<JSObject> holder,
+               Handle<String> name,
+               LookupResult* lookup,
+               Register receiver,
+               Register scratch1,
+               Register scratch2,
+               Register scratch3,
+               Label* miss) {
+    ASSERT(holder->HasNamedInterceptor());
+    ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
+
+    // Check that the receiver isn't a smi.
+    __ JumpIfSmi(receiver, miss);
+    CallOptimization optimization(lookup);
+    if (optimization.is_constant_call()) {
+      CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
+                       holder, lookup, name, optimization, miss);
+    } else {
+      CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
+                     name, holder, miss);
+    }
+  }
+
+ private:
+  void CompileCacheable(MacroAssembler* masm,
+                        Handle<JSObject> object,
+                        Register receiver,
+                        Register scratch1,
+                        Register scratch2,
+                        Register scratch3,
+                        Handle<JSObject> interceptor_holder,
+                        LookupResult* lookup,
+                        Handle<String> name,
+                        const CallOptimization& optimization,
+                        Label* miss_label) {
+    ASSERT(optimization.is_constant_call());
+    ASSERT(!lookup->holder()->IsGlobalObject());
+    Counters* counters = masm->isolate()->counters();
+    int depth1 = kInvalidProtoDepth;
+    int depth2 = kInvalidProtoDepth;
+    bool can_do_fast_api_call = false;
+    if (optimization.is_simple_api_call() &&
+        !lookup->holder()->IsGlobalObject()) {
+      depth1 = optimization.GetPrototypeDepthOfExpectedType(
+          object, interceptor_holder);
+      if (depth1 == kInvalidProtoDepth) {
+        depth2 = optimization.GetPrototypeDepthOfExpectedType(
+            interceptor_holder, Handle<JSObject>(lookup->holder()));
+      }
+      can_do_fast_api_call =
+          depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
+    }
+
+    __ IncrementCounter(counters->call_const_interceptor(), 1,
+                        scratch1, scratch2);
+
+    if (can_do_fast_api_call) {
+      __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1,
+                          scratch1, scratch2);
+      ReserveSpaceForFastApiCall(masm, scratch1);
+    }
+
+    // Check that the maps from receiver to interceptor's holder
+    // haven't changed and thus we can invoke interceptor.
+    Label miss_cleanup;
+    Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
+    Register holder =
+        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
+                                        scratch1, scratch2, scratch3,
+                                        name, depth1, miss);
+
+    // Invoke an interceptor and if it provides a value,
+    // branch to |regular_invoke|.
+    Label regular_invoke;
+    LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
+                        &regular_invoke);
+
+    // Interceptor returned nothing for this property.  Try to use cached
+    // constant function.
+
+    // Check that the maps from interceptor's holder to constant function's
+    // holder haven't changed and thus we can use cached constant function.
+    if (*interceptor_holder != lookup->holder()) {
+      stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
+                                      Handle<JSObject>(lookup->holder()),
+                                      scratch1, scratch2, scratch3,
+                                      name, depth2, miss);
+    } else {
+      // CheckPrototypes has a side effect of fetching a 'holder'
+      // for API (object which is instanceof for the signature).  It's
+      // safe to omit it here, as if present, it should be fetched
+      // by the previous CheckPrototypes.
+      ASSERT(depth2 == kInvalidProtoDepth);
+    }
+
+    // Invoke function.
+    if (can_do_fast_api_call) {
+      GenerateFastApiDirectCall(masm, optimization, arguments_.immediate());
+    } else {
+      CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
+          ? CALL_AS_FUNCTION
+          : CALL_AS_METHOD;
+      __ InvokeFunction(optimization.constant_function(), arguments_,
+                        JUMP_FUNCTION, NullCallWrapper(), call_kind);
+    }
+
+    // Deferred code for fast API call case---clean preallocated space.
+    if (can_do_fast_api_call) {
+      __ bind(&miss_cleanup);
+      FreeSpaceForFastApiCall(masm);
+      __ b(miss_label);
+    }
+
+    // Invoke a regular function.
+    __ bind(&regular_invoke);
+    if (can_do_fast_api_call) {
+      FreeSpaceForFastApiCall(masm);
+    }
+  }
+
+  void CompileRegular(MacroAssembler* masm,
+                      Handle<JSObject> object,
+                      Register receiver,
+                      Register scratch1,
+                      Register scratch2,
+                      Register scratch3,
+                      Handle<String> name,
+                      Handle<JSObject> interceptor_holder,
+                      Label* miss_label) {
+    Register holder =
+        stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
+                                        scratch1, scratch2, scratch3,
+                                        name, miss_label);
+
+    // Call a runtime function to load the interceptor property.
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    // Save the name_ register across the call.
+    __ push(name_);
+    PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
+    __ CallExternalReference(
+        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
+                          masm->isolate()),
+        6);
+    // Restore the name_ register.
+    __ pop(name_);
+    // Leave the internal frame.
+  }
+
+  void LoadWithInterceptor(MacroAssembler* masm,
+                           Register receiver,
+                           Register holder,
+                           Handle<JSObject> holder_obj,
+                           Register scratch,
+                           Label* interceptor_succeeded) {
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      __ Push(holder, name_);
+      CompileCallLoadPropertyWithInterceptor(masm,
+                                             receiver,
+                                             holder,
+                                             name_,
+                                             holder_obj);
+      __ pop(name_);  // Restore the name.
+      __ pop(receiver);  // Restore the holder.
+    }
+    // If interceptor returns no-result sentinel, call the constant function.
+    __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
+    __ cmp(r3, scratch);
+    __ bne(interceptor_succeeded);
+  }
+
+  StubCompiler* stub_compiler_;
+  const ParameterCount& arguments_;
+  Register name_;
+  Code::ExtraICState extra_ic_state_;
+};
+
+
+// Generate code to check that a global property cell is empty. Create
+// the property cell at compilation time if no cell exists for the
+// property.
+static void GenerateCheckPropertyCell(MacroAssembler* masm,
+                                      Handle<GlobalObject> global,
+                                      Handle<String> name,
+                                      Register scratch,
+                                      Label* miss) {
+  Handle<JSGlobalPropertyCell> cell =
+      GlobalObject::EnsurePropertyCell(global, name);
+  ASSERT(cell->value()->IsTheHole());
+  __ mov(scratch, Operand(cell));
+  __ LoadP(scratch,
+           FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
+  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  __ cmp(scratch, ip);
+  __ bne(miss);
+}
+
+
+// Calls GenerateCheckPropertyCell for each global object in the prototype chain
+// from object to (but not including) holder.
+static void GenerateCheckPropertyCells(MacroAssembler* masm,
+                                       Handle<JSObject> object,
+                                       Handle<JSObject> holder,
+                                       Handle<String> name,
+                                       Register scratch,
+                                       Label* miss) {
+  Handle<JSObject> current = object;
+  while (!current.is_identical_to(holder)) {
+    if (current->IsGlobalObject()) {
+      GenerateCheckPropertyCell(masm,
+                                Handle<GlobalObject>::cast(current),
+                                name,
+                                scratch,
+                                miss);
+    }
+    current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
+  }
+}
+
+#undef __
+#define __ ACCESS_MASM(masm())
+
+
+Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
+                                       Register object_reg,
+                                       Handle<JSObject> holder,
+                                       Register holder_reg,
+                                       Register scratch1,
+                                       Register scratch2,
+                                       Handle<String> name,
+                                       int save_at_depth,
+                                       Label* miss) {
+  // Make sure there's no overlap between holder and object registers.
+  ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
+  ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
+         && !scratch2.is(scratch1));
+
+  // Keep track of the current object in register reg.
+  Register reg = object_reg;
+  int depth = 0;
+
+  if (save_at_depth == depth) {
+    __ StoreP(reg, MemOperand(sp));
+  }
+
+  // Check the maps in the prototype chain.
+  // Traverse the prototype chain from the object and do map checks.
+  Handle<JSObject> current = object;
+  while (!current.is_identical_to(holder)) {
+    ++depth;
+
+    // Only global objects and objects that do not require access
+    // checks are allowed in stubs.
+    ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
+
+    Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
+    if (!current->HasFastProperties() &&
+        !current->IsJSGlobalObject() &&
+        !current->IsJSGlobalProxy()) {
+      if (!name->IsSymbol()) {
+        name = factory()->LookupSymbol(name);
+      }
+      ASSERT(current->property_dictionary()->FindEntry(*name) ==
+             StringDictionary::kNotFound);
+
+      GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
+                                       scratch1, scratch2);
+
+      __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+      reg = holder_reg;  // From now on the object will be in holder_reg.
+      __ LoadP(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
+    } else {
+      Handle<Map> current_map(current->map());
+      __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK,
+                  ALLOW_ELEMENT_TRANSITION_MAPS);
+
+      // Check access rights to the global object.  This has to happen after
+      // the map check so that we know that the object is actually a global
+      // object.
+      if (current->IsJSGlobalProxy()) {
+        __ CheckAccessGlobalProxy(reg, scratch2, miss);
+      }
+      reg = holder_reg;  // From now on the object will be in holder_reg.
+
+      if (heap()->InNewSpace(*prototype)) {
+        // The prototype is in new space; we cannot store a reference to it
+        // in the code.  Load it from the map.
+        __ LoadP(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
+      } else {
+        // The prototype is in old space; load it directly.
+        __ mov(reg, Operand(prototype));
+      }
+    }
+
+    if (save_at_depth == depth) {
+      __ StoreP(reg, MemOperand(sp));
+    }
+
+    // Go to the next object in the prototype chain.
+    current = prototype;
+  }
+
+  // Log the check depth.
+  LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
+
+  // Check the holder map.
+  __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss,
+              DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+
+  // Perform security check for access to the global object.
+  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
+  if (holder->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(reg, scratch1, miss);
+  }
+
+  // If we've skipped any global objects, it's not enough to verify that
+  // their maps haven't changed.  We also need to check that the property
+  // cell for the property is still empty.
+  GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
+
+  // Return the register containing the holder.
+  return reg;
+}
+
+
+void StubCompiler::GenerateLoadField(Handle<JSObject> object,
+                                     Handle<JSObject> holder,
+                                     Register receiver,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     Register scratch3,
+                                     int index,
+                                     Handle<String> name,
+                                     Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, miss);
+
+  // Check that the maps haven't changed.
+  Register reg = CheckPrototypes(
+      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
+  GenerateFastPropertyLoad(masm(), r3, reg, holder, index);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
+                                        Handle<JSObject> holder,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Register scratch3,
+                                        Handle<JSFunction> value,
+                                        Handle<String> name,
+                                        Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, miss);
+
+  // Check that the maps haven't changed.
+  CheckPrototypes(
+      object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
+
+  // Return the constant value.
+  __ LoadHeapObject(r3, value);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateDictionaryLoadCallback(Register receiver,
+                                                  Register name_reg,
+                                                  Register scratch1,
+                                                  Register scratch2,
+                                                  Register scratch3,
+                                                  Handle<AccessorInfo> callback,
+                                                  Handle<String> name,
+                                                  Label* miss) {
+  ASSERT(!receiver.is(scratch1));
+  ASSERT(!receiver.is(scratch2));
+  ASSERT(!receiver.is(scratch3));
+
+  // Load the properties dictionary.
+  Register dictionary = scratch1;
+  __ LoadP(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+
+  // Probe the dictionary.
+  Label probe_done;
+  StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
+                                                     miss,
+                                                     &probe_done,
+                                                     dictionary,
+                                                     name_reg,
+                                                     scratch2,
+                                                     scratch3);
+  __ bind(&probe_done);
+
+  // If probing finds an entry in the dictionary, scratch3 contains the
+  // pointer into the dictionary. Check that the value is the callback.
+  Register pointer = scratch3;
+  const int kElementsStartOffset = StringDictionary::kHeaderSize +
+      StringDictionary::kElementsStartIndex * kPointerSize;
+  const int kValueOffset = kElementsStartOffset + kPointerSize;
+  __ LoadP(scratch2, FieldMemOperand(pointer, kValueOffset));
+  __ mov(scratch3, Operand(callback));
+  __ cmp(scratch2, scratch3);
+  __ bne(miss);
+}
+
+
+void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
+                                        Handle<JSObject> holder,
+                                        Register receiver,
+                                        Register name_reg,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Register scratch3,
+                                        Register scratch4,
+                                        Handle<AccessorInfo> callback,
+                                        Handle<String> name,
+                                        Label* miss) {
+#if !ABI_RETURNS_HANDLES_IN_REGS
+  bool alloc_return_buf = true;
+#else
+  bool alloc_return_buf = false;
+#endif
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, miss);
+
+  // Check that the maps haven't changed.
+  Register reg = CheckPrototypes(object, receiver, holder, scratch1,
+                                 scratch2, scratch3, name, miss);
+
+  if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
+    GenerateDictionaryLoadCallback(
+        reg, name_reg, scratch2, scratch3, scratch4, callback, name, miss);
+  }
+
+  // Build AccessorInfo::args_ list on the stack and push property name below
+  // the exit frame to make GC aware of them and store pointers to them.
+  __ push(receiver);
+  __ mr(scratch2, sp);  // ip = AccessorInfo::args_
+  if (heap()->InNewSpace(callback->data())) {
+    __ Move(scratch3, callback);
+    __ LoadP(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
+  } else {
+    __ Move(scratch3, Handle<Object>(callback->data()));
+  }
+  __ Push(reg, scratch3);
+  __ mov(scratch3, Operand(ExternalReference::isolate_address()));
+  __ Push(scratch3, name_reg);
+
+  // If ABI passes Handles (pointer-sized struct) in a register:
+  //
+  // Create 2 or 3 extra slots on stack (depending on alloc_return_buf):
+  //    [0] space for DirectCEntryStub's LR save
+  //    [1] space for pointer-sized non-scalar return value (r3)
+  //    [2] AccessorInfo
+  //
+  // Otherwise:
+  //
+  // Create 3 or 4 extra slots on stack (depending on alloc_return_buf):
+  //    [0] space for DirectCEntryStub's LR save
+  //    [1] (optional) space for pointer-sized non-scalar return value (r3)
+  //    [2] copy of Handle (first arg)
+  //    [3] AccessorInfo
+  //
+  // If alloc_return_buf, we shift the arguments over a register
+  // (e.g. r3 -> r4) to allow for the return value buffer in implicit
+  // first arg.  CallApiFunctionAndReturn will setup r3.
+#if ABI_PASSES_HANDLES_IN_REGS
+  const int kAccessorInfoSlot = kStackFrameExtraParamSlot +
+                                  (alloc_return_buf ? 2 : 1);
+#else
+  const int kAccessorInfoSlot = kStackFrameExtraParamSlot +
+                                  (alloc_return_buf ? 3 : 2);
+  int kArg0Slot = kStackFrameExtraParamSlot + (alloc_return_buf ? 2 : 1);
+#endif
+  const int kApiStackSpace = (alloc_return_buf ? 4 : 3);
+  Register arg0 = (alloc_return_buf ? r4 : r3);
+  Register arg1 = (alloc_return_buf ? r5 : r4);
+
+  __ mr(arg1, scratch2);  // Saved in case scratch2 == arg0.
+  __ mr(arg0, sp);  // arg0 = Handle<String>
+
+  FrameScope frame_scope(masm(), StackFrame::MANUAL);
+  __ EnterExitFrame(false, kApiStackSpace);
+
+#if !ABI_PASSES_HANDLES_IN_REGS
+  // pass 1st arg by reference
+  __ StoreP(arg0, MemOperand(sp, kArg0Slot * kPointerSize));
+  __ addi(arg0, sp, Operand(kArg0Slot * kPointerSize));
+#endif
+
+  // Create AccessorInfo instance on the stack above the exit frame with
+  // ip (internal::Object** args_) as the data.
+  __ StoreP(arg1, MemOperand(sp, kAccessorInfoSlot * kPointerSize));
+  // arg1 = AccessorInfo&
+  __ addi(arg1, sp, Operand(kAccessorInfoSlot * kPointerSize));
+
+  const int kStackUnwindSpace = 5;
+  Address getter_address = v8::ToCData<Address>(callback->getter());
+  ApiFunction fun(getter_address);
+  ExternalReference ref =
+      ExternalReference(&fun,
+                        ExternalReference::DIRECT_GETTER_CALL,
+                        masm()->isolate());
+  __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
+                                           Handle<JSObject> interceptor_holder,
+                                           LookupResult* lookup,
+                                           Register receiver,
+                                           Register name_reg,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Register scratch3,
+                                           Handle<String> name,
+                                           Label* miss) {
+  ASSERT(interceptor_holder->HasNamedInterceptor());
+  ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, miss);
+
+  // So far the most popular follow ups for interceptor loads are FIELD
+  // and CALLBACKS, so inline only them, other cases may be added
+  // later.
+  bool compile_followup_inline = false;
+  if (lookup->IsFound() && lookup->IsCacheable()) {
+    if (lookup->IsField()) {
+      compile_followup_inline = true;
+    } else if (lookup->type() == CALLBACKS &&
+               lookup->GetCallbackObject()->IsAccessorInfo()) {
+      AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
+      compile_followup_inline = callback->getter() != NULL &&
+          callback->IsCompatibleReceiver(*object);
+    }
+  }
+
+  if (compile_followup_inline) {
+    // Compile the interceptor call, followed by inline code to load the
+    // property from further up the prototype chain if the call fails.
+    // Check that the maps haven't changed.
+    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
+                                          scratch1, scratch2, scratch3,
+                                          name, miss);
+    ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
+
+    // Preserve the receiver register explicitly whenever it is different from
+    // the holder and it is needed should the interceptor return without any
+    // result. The CALLBACKS case needs the receiver to be passed into C++ code,
+    // the FIELD case might cause a miss during the prototype check.
+    bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder();
+    bool must_preserve_receiver_reg = !receiver.is(holder_reg) &&
+        (lookup->type() == CALLBACKS || must_perfrom_prototype_check);
+
+    // Save necessary data before invoking an interceptor.
+    // Requires a frame to make GC aware of pushed pointers.
+    {
+      FrameScope frame_scope(masm(), StackFrame::INTERNAL);
+      if (must_preserve_receiver_reg) {
+        __ Push(receiver, holder_reg, name_reg);
+      } else {
+        __ Push(holder_reg, name_reg);
+      }
+      // Invoke an interceptor.  Note: map checks from receiver to
+      // interceptor's holder has been compiled before (see a caller
+      // of this method.)
+      CompileCallLoadPropertyWithInterceptor(masm(),
+                                             receiver,
+                                             holder_reg,
+                                             name_reg,
+                                             interceptor_holder);
+      // Check if interceptor provided a value for property.  If it's
+      // the case, return immediately.
+      Label interceptor_failed;
+      __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
+      __ cmp(r3, scratch1);
+      __ beq(&interceptor_failed);
+      frame_scope.GenerateLeaveFrame();
+      __ Ret();
+
+      __ bind(&interceptor_failed);
+      __ pop(name_reg);
+      __ pop(holder_reg);
+      if (must_preserve_receiver_reg) {
+        __ pop(receiver);
+      }
+      // Leave the internal frame.
+    }
+    // Check that the maps from interceptor's holder to lookup's holder
+    // haven't changed.  And load lookup's holder into |holder| register.
+    if (must_perfrom_prototype_check) {
+      holder_reg = CheckPrototypes(interceptor_holder,
+                                   holder_reg,
+                                   Handle<JSObject>(lookup->holder()),
+                                   scratch1,
+                                   scratch2,
+                                   scratch3,
+                                   name,
+                                   miss);
+    }
+
+    if (lookup->IsField()) {
+      // We found FIELD property in prototype chain of interceptor's holder.
+      // Retrieve a field from field's holder.
+      GenerateFastPropertyLoad(masm(), r3, holder_reg,
+                               Handle<JSObject>(lookup->holder()),
+                               lookup->GetFieldIndex());
+      __ Ret();
+    } else {
+      // We found CALLBACKS property in prototype chain of interceptor's
+      // holder.
+      ASSERT(lookup->type() == CALLBACKS);
+      Handle<AccessorInfo> callback(
+          AccessorInfo::cast(lookup->GetCallbackObject()));
+      ASSERT(callback->getter() != NULL);
+
+      // Tail call to runtime.
+      // Important invariant in CALLBACKS case: the code above must be
+      // structured to never clobber |receiver| register.
+      __ Move(scratch2, callback);
+      // holder_reg is either receiver or scratch1.
+      if (!receiver.is(holder_reg)) {
+        ASSERT(scratch1.is(holder_reg));
+        __ Push(receiver, holder_reg);
+      } else {
+        __ push(receiver);
+        __ push(holder_reg);
+      }
+      __ LoadP(scratch3,
+               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
+      __ mov(scratch1, Operand(ExternalReference::isolate_address()));
+      __ Push(scratch3, scratch1, scratch2, name_reg);
+
+      ExternalReference ref =
+          ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
+                            masm()->isolate());
+      __ TailCallExternalReference(ref, 6, 1);
+    }
+  } else {  // !compile_followup_inline
+    // Call the runtime system to load the interceptor.
+    // Check that the maps haven't changed.
+    Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
+                                          scratch1, scratch2, scratch3,
+                                          name, miss);
+    PushInterceptorArguments(masm(), receiver, holder_reg,
+                             name_reg, interceptor_holder);
+
+    ExternalReference ref =
+        ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad),
+                          masm()->isolate());
+    __ TailCallExternalReference(ref, 6, 1);
+  }
+}
+
+
+void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
+  if (kind_ == Code::KEYED_CALL_IC) {
+    __ Cmpi(r5, Operand(name), r0);
+    __ bne(miss);
+  }
+}
+
+
+void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
+                                                   Handle<JSObject> holder,
+                                                   Handle<String> name,
+                                                   Label* miss) {
+  ASSERT(holder->IsGlobalObject());
+
+  // Get the number of arguments.
+  const int argc = arguments().immediate();
+
+  // Get the receiver from the stack.
+  __ LoadP(r3, MemOperand(sp, argc * kPointerSize), r0);
+
+  // Check that the maps haven't changed.
+  __ JumpIfSmi(r3, miss);
+  CheckPrototypes(object, r3, holder, r6, r4, r7, name, miss);
+}
+
+
+void CallStubCompiler::GenerateLoadFunctionFromCell(
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Label* miss) {
+  // Get the value from the cell.
+  __ mov(r6, Operand(cell));
+  __ LoadP(r4, FieldMemOperand(r6, JSGlobalPropertyCell::kValueOffset));
+
+  // Check that the cell contains the same function.
+  if (heap()->InNewSpace(*function)) {
+    // We can't embed a pointer to a function in new space so we have
+    // to verify that the shared function info is unchanged. This has
+    // the nice side effect that multiple closures based on the same
+    // function can all use this call IC. Before we load through the
+    // function, we have to verify that it still is a function.
+    __ JumpIfSmi(r4, miss);
+    __ CompareObjectType(r4, r6, r6, JS_FUNCTION_TYPE);
+    __ bne(miss);
+
+    // Check the shared function info. Make sure it hasn't changed.
+    __ Move(r6, Handle<SharedFunctionInfo>(function->shared()));
+    __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+    __ cmp(r7, r6);
+  } else {
+    __ mov(r6, Operand(function));
+    __ cmp(r4, r6);
+  }
+  __ bne(miss);
+}
+
+
+void CallStubCompiler::GenerateMissBranch() {
+  Handle<Code> code =
+      isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
+                                               kind_,
+                                               extra_state_);
+  __ Jump(code, RelocInfo::CODE_TARGET);
+}
+
+
+Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
+                                                Handle<JSObject> holder,
+                                                int index,
+                                                Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  GenerateNameCheck(name, &miss);
+
+  const int argc = arguments().immediate();
+
+  // Get the receiver of the function from the stack into r3.
+  __ LoadP(r3, MemOperand(sp, argc * kPointerSize), r0);
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(r3, &miss);
+
+  // Do the right check and compute the holder register.
+  Register reg = CheckPrototypes(object, r3, holder, r4, r6, r7, name, &miss);
+  GenerateFastPropertyLoad(masm(), r4, reg, holder, index);
+
+  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(Code::FIELD, name);
+}
+
+
+Handle<Code> CallStubCompiler::CompileArrayPushCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  // If object is not an array, bail out to regular call.
+  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
+
+  Label miss;
+  GenerateNameCheck(name, &miss);
+
+  Register receiver = r4;
+  // Get the receiver from the stack
+  const int argc = arguments().immediate();
+  __ LoadP(receiver, MemOperand(sp, argc * kPointerSize), r0);
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, &miss);
+
+  // Check that the maps haven't changed.
+  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r6, r3, r7,
+                  name, &miss);
+
+  if (argc == 0) {
+    // Nothing to do, just return the length.
+    __ LoadP(r3, FieldMemOperand(receiver, JSArray::kLengthOffset));
+    __ Drop(argc + 1);
+    __ Ret();
+  } else {
+    Label call_builtin;
+
+    if (argc == 1) {  // Otherwise fall through to call the builtin.
+      Label attempt_to_grow_elements;
+
+      Register elements = r9;
+      Register end_elements = r8;
+      // Get the elements array of the object.
+      __ LoadP(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
+
+      // Check that the elements are in fast mode and writable.
+      __ CheckMap(elements,
+                  r3,
+                  Heap::kFixedArrayMapRootIndex,
+                  &call_builtin,
+                  DONT_DO_SMI_CHECK);
+
+
+      // Get the array's length into r3 and calculate new length.
+      __ LoadP(r3, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ AddSmiLiteral(r3, r3, Smi::FromInt(argc), r0);
+
+      // Get the elements' length.
+      __ LoadP(r7, FieldMemOperand(elements, FixedArray::kLengthOffset));
+
+      // Check if we could survive without allocation.
+      __ cmp(r3, r7);
+      __ bgt(&attempt_to_grow_elements);
+
+      // Check if value is a smi.
+      Label with_write_barrier;
+      __ LoadP(r7, MemOperand(sp, (argc - 1) * kPointerSize), r0);
+      __ JumpIfNotSmi(r7, &with_write_barrier);
+
+      // Save new length.
+      __ StoreP(r3, FieldMemOperand(receiver, JSArray::kLengthOffset), r0);
+
+      // Store the value.
+      // We may need a register containing the address end_elements below,
+      // so write back the value in end_elements.
+      __ SmiToPtrArrayOffset(end_elements, r3);
+      __ add(end_elements, elements, end_elements);
+      const int kEndElementsOffset =
+          FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
+      __ Add(end_elements, end_elements, kEndElementsOffset, r0);
+      __ StoreP(r7, MemOperand(end_elements));
+
+      // Check for a smi.
+      __ Drop(argc + 1);
+      __ Ret();
+
+      __ bind(&with_write_barrier);
+
+      __ LoadP(r6, FieldMemOperand(receiver, HeapObject::kMapOffset));
+
+      if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
+        Label fast_object, not_fast_object;
+        __ CheckFastObjectElements(r6, r10, &not_fast_object);
+        __ b(&fast_object);
+        // In case of fast smi-only, convert to fast object, otherwise bail out.
+        __ bind(&not_fast_object);
+        __ CheckFastSmiElements(r6, r10, &call_builtin);
+        // r4: receiver
+        // r6: map
+        Label try_holey_map;
+        __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
+                                               FAST_ELEMENTS,
+                                               r6,
+                                               r10,
+                                               &try_holey_map);
+        __ mr(r5, receiver);
+        ElementsTransitionGenerator::
+            GenerateMapChangeElementsTransition(masm());
+        __ b(&fast_object);
+
+        __ bind(&try_holey_map);
+        __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
+                                               FAST_HOLEY_ELEMENTS,
+                                               r6,
+                                               r10,
+                                               &call_builtin);
+        __ mr(r5, receiver);
+        ElementsTransitionGenerator::
+            GenerateMapChangeElementsTransition(masm());
+        __ bind(&fast_object);
+      } else {
+        __ CheckFastObjectElements(r6, r6, &call_builtin);
+      }
+
+      // Save new length.
+      __ StoreP(r3, FieldMemOperand(receiver, JSArray::kLengthOffset), r0);
+
+      // Store the value.
+      // We may need a register containing the address end_elements below,
+      // so write back the value in end_elements.
+      __ SmiToPtrArrayOffset(end_elements, r3);
+      __ add(end_elements, elements, end_elements);
+      __ Add(end_elements, end_elements, kEndElementsOffset, r0);
+      __ StoreP(r7, MemOperand(end_elements));
+
+      __ RecordWrite(elements,
+                     end_elements,
+                     r7,
+                     kLRHasNotBeenSaved,
+                     kDontSaveFPRegs,
+                     EMIT_REMEMBERED_SET,
+                     OMIT_SMI_CHECK);
+      __ Drop(argc + 1);
+      __ Ret();
+
+      __ bind(&attempt_to_grow_elements);
+      // r3: array's length + 1.
+      // r7: elements' length.
+
+      if (!FLAG_inline_new) {
+        __ b(&call_builtin);
+      }
+
+      __ LoadP(r5, MemOperand(sp, (argc - 1) * kPointerSize), r0);
+      // Growing elements that are SMI-only requires special handling in case
+      // the new element is non-Smi. For now, delegate to the builtin.
+      Label no_fast_elements_check;
+      __ JumpIfSmi(r5, &no_fast_elements_check);
+      __ LoadP(r10, FieldMemOperand(receiver, HeapObject::kMapOffset));
+      __ CheckFastObjectElements(r10, r10, &call_builtin);
+      __ bind(&no_fast_elements_check);
+
+      Isolate* isolate = masm()->isolate();
+      ExternalReference new_space_allocation_top =
+          ExternalReference::new_space_allocation_top_address(isolate);
+      ExternalReference new_space_allocation_limit =
+          ExternalReference::new_space_allocation_limit_address(isolate);
+
+      const int kAllocationDelta = 4;
+      // Load top and check if it is the end of elements.
+      __ SmiToPtrArrayOffset(end_elements, r3);
+      __ add(end_elements, elements, end_elements);
+      __ Add(end_elements, end_elements, kEndElementsOffset, r0);
+      __ mov(r10, Operand(new_space_allocation_top));
+      __ LoadP(r6, MemOperand(r10));
+      __ cmp(end_elements, r6);
+      __ bne(&call_builtin);
+
+      __ mov(r22, Operand(new_space_allocation_limit));
+      __ LoadP(r22, MemOperand(r22));
+      __ addi(r6, r6, Operand(kAllocationDelta * kPointerSize));
+      __ cmpl(r6, r22);
+      __ bgt(&call_builtin);
+
+      // We fit and could grow elements.
+      // Update new_space_allocation_top.
+      __ StoreP(r6, MemOperand(r10));
+      // Push the argument.
+      __ StoreP(r5, MemOperand(end_elements));
+      // Fill the rest with holes.
+      __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
+      for (int i = 1; i < kAllocationDelta; i++) {
+        __ StoreP(r6, MemOperand(end_elements, i * kPointerSize), r0);
+      }
+
+      // Update elements' and array's sizes.
+      __ StoreP(r3, FieldMemOperand(receiver, JSArray::kLengthOffset), r0);
+      __ AddSmiLiteral(r7, r7, Smi::FromInt(kAllocationDelta), r0);
+      __ StoreP(r7, FieldMemOperand(elements, FixedArray::kLengthOffset), r0);
+
+      // Elements are in new space, so write barrier is not required.
+      __ Drop(argc + 1);
+      __ Ret();
+    }
+    __ bind(&call_builtin);
+    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
+                                                   masm()->isolate()),
+                                 argc + 1,
+                                 1);
+  }
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
+Handle<Code> CallStubCompiler::CompileArrayPopCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  // If object is not an array, bail out to regular call.
+  if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
+
+  Label miss, return_undefined, call_builtin;
+  Register receiver = r4;
+  Register elements = r6;
+  GenerateNameCheck(name, &miss);
+
+  // Get the receiver from the stack
+  const int argc = arguments().immediate();
+  __ LoadP(receiver, MemOperand(sp, argc * kPointerSize), r0);
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(receiver, &miss);
+
+  // Check that the maps haven't changed.
+  CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements,
+                  r7, r3, name, &miss);
+
+  // Get the elements array of the object.
+  __ LoadP(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
+
+  // Check that the elements are in fast mode and writable.
+  __ CheckMap(elements,
+              r3,
+              Heap::kFixedArrayMapRootIndex,
+              &call_builtin,
+              DONT_DO_SMI_CHECK);
+
+  // Get the array's length into r7 and calculate new length.
+  __ LoadP(r7, FieldMemOperand(receiver, JSArray::kLengthOffset));
+  __ SubSmiLiteral(r7, r7, Smi::FromInt(1), r0);
+  __ cmpi(r7, Operand::Zero());
+  __ blt(&return_undefined);
+
+  // Get the last element.
+  __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
+  // We can't address the last element in one operation. Compute the more
+  // expensive shift first, and use an offset later on.
+  __ SmiToPtrArrayOffset(r3, r7);
+  __ add(elements, elements, r3);
+  __ LoadP(r3, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  __ cmp(r3, r9);
+  __ beq(&call_builtin);
+
+  // Set the array's length.
+  __ StoreP(r7, FieldMemOperand(receiver, JSArray::kLengthOffset), r0);
+
+  // Fill with the hole.
+  __ StoreP(r9, FieldMemOperand(elements, FixedArray::kHeaderSize), r0);
+  __ Drop(argc + 1);
+  __ Ret();
+
+  __ bind(&return_undefined);
+  __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+  __ Drop(argc + 1);
+  __ Ret();
+
+  __ bind(&call_builtin);
+  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop,
+                                                 masm()->isolate()),
+                               argc + 1,
+                               1);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
+Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5                     : function name
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  // If object is not a string, bail out to regular call.
+  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
+
+  const int argc = arguments().immediate();
+  Label miss;
+  Label name_miss;
+  Label index_out_of_range;
+  Label* index_out_of_range_label = &index_out_of_range;
+
+  if (kind_ == Code::CALL_IC &&
+      (CallICBase::StringStubState::decode(extra_state_) ==
+       DEFAULT_STRING_STUB)) {
+    index_out_of_range_label = &miss;
+  }
+  GenerateNameCheck(name, &name_miss);
+
+  // Check that the maps starting from the prototype haven't changed.
+  GenerateDirectLoadGlobalFunctionPrototype(masm(),
+                                            Context::STRING_FUNCTION_INDEX,
+                                            r3,
+                                            &miss);
+  ASSERT(!object.is_identical_to(holder));
+  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
+                  r3, holder, r4, r6, r7, name, &miss);
+
+  Register receiver = r4;
+  Register index = r7;
+  Register result = r3;
+  __ LoadP(receiver, MemOperand(sp, argc * kPointerSize), r0);
+  if (argc > 0) {
+    __ LoadP(index, MemOperand(sp, (argc - 1) * kPointerSize), r0);
+  } else {
+    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
+  }
+
+  StringCharCodeAtGenerator generator(receiver,
+                                      index,
+                                      result,
+                                      &miss,  // When not a string.
+                                      &miss,  // When not a number.
+                                      index_out_of_range_label,
+                                      STRING_INDEX_IS_NUMBER);
+  generator.GenerateFast(masm());
+  __ Drop(argc + 1);
+  __ Ret();
+
+  StubRuntimeCallHelper call_helper;
+  generator.GenerateSlow(masm(), call_helper);
+
+  if (index_out_of_range.is_linked()) {
+    __ bind(&index_out_of_range);
+    __ LoadRoot(r3, Heap::kNanValueRootIndex);
+    __ Drop(argc + 1);
+    __ Ret();
+  }
+
+  __ bind(&miss);
+  // Restore function name in r5.
+  __ Move(r5, name);
+  __ bind(&name_miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
+Handle<Code> CallStubCompiler::CompileStringCharAtCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5                     : function name
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  // If object is not a string, bail out to regular call.
+  if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
+
+  const int argc = arguments().immediate();
+  Label miss;
+  Label name_miss;
+  Label index_out_of_range;
+  Label* index_out_of_range_label = &index_out_of_range;
+  if (kind_ == Code::CALL_IC &&
+      (CallICBase::StringStubState::decode(extra_state_) ==
+       DEFAULT_STRING_STUB)) {
+    index_out_of_range_label = &miss;
+  }
+  GenerateNameCheck(name, &name_miss);
+
+  // Check that the maps starting from the prototype haven't changed.
+  GenerateDirectLoadGlobalFunctionPrototype(masm(),
+                                            Context::STRING_FUNCTION_INDEX,
+                                            r3,
+                                            &miss);
+  ASSERT(!object.is_identical_to(holder));
+  CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
+                  r3, holder, r4, r6, r7, name, &miss);
+
+  Register receiver = r3;
+  Register index = r7;
+  Register scratch = r6;
+  Register result = r3;
+  __ LoadP(receiver, MemOperand(sp, argc * kPointerSize), r0);
+  if (argc > 0) {
+    __ LoadP(index, MemOperand(sp, (argc - 1) * kPointerSize), r0);
+  } else {
+    __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
+  }
+
+  StringCharAtGenerator generator(receiver,
+                                  index,
+                                  scratch,
+                                  result,
+                                  &miss,  // When not a string.
+                                  &miss,  // When not a number.
+                                  index_out_of_range_label,
+                                  STRING_INDEX_IS_NUMBER);
+  generator.GenerateFast(masm());
+  __ Drop(argc + 1);
+  __ Ret();
+
+  StubRuntimeCallHelper call_helper;
+  generator.GenerateSlow(masm(), call_helper);
+
+  if (index_out_of_range.is_linked()) {
+    __ bind(&index_out_of_range);
+    __ LoadRoot(r3, Heap::kEmptyStringRootIndex);
+    __ Drop(argc + 1);
+    __ Ret();
+  }
+
+  __ bind(&miss);
+  // Restore function name in r5.
+  __ Move(r5, name);
+  __ bind(&name_miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
+Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5                     : function name
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  const int argc = arguments().immediate();
+
+  // If the object is not a JSObject or we got an unexpected number of
+  // arguments, bail out to the regular call.
+  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
+
+  Label miss;
+  GenerateNameCheck(name, &miss);
+
+  if (cell.is_null()) {
+    __ LoadP(r4, MemOperand(sp, 1 * kPointerSize));
+
+    STATIC_ASSERT(kSmiTag == 0);
+    __ JumpIfSmi(r4, &miss);
+
+    CheckPrototypes(Handle<JSObject>::cast(object), r4, holder, r3, r6, r7,
+                    name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  // Load the char code argument.
+  Register code = r4;
+  __ LoadP(code, MemOperand(sp, 0 * kPointerSize));
+
+  // Check the code is a smi.
+  Label slow;
+  STATIC_ASSERT(kSmiTag == 0);
+  __ JumpIfNotSmi(code, &slow);
+
+  // Convert the smi code to uint16.
+  __ LoadSmiLiteral(r0, Smi::FromInt(0xffff));
+  __ and_(code, code, r0);
+
+  StringCharFromCodeGenerator generator(code, r3);
+  generator.GenerateFast(masm());
+  __ Drop(argc + 1);
+  __ Ret();
+
+  StubRuntimeCallHelper call_helper;
+  generator.GenerateSlow(masm(), call_helper);
+
+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
+  __ bind(&slow);
+  __ InvokeFunction(
+      function,  arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
+
+  __ bind(&miss);
+  // r5: function name.
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+}
+
+
+Handle<Code> CallStubCompiler::CompileMathFloorCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5                     : function name
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  const int argc = arguments().immediate();
+  // If the object is not a JSObject or we got an unexpected number of
+  // arguments, bail out to the regular call.
+  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
+
+  Label miss, slow, not_smi, positive, drop_arg_return;
+  GenerateNameCheck(name, &miss);
+
+  if (cell.is_null()) {
+    __ LoadP(r4, MemOperand(sp, 1 * kPointerSize));
+    STATIC_ASSERT(kSmiTag == 0);
+    __ JumpIfSmi(r4, &miss);
+    CheckPrototypes(Handle<JSObject>::cast(object), r4, holder, r3, r6, r7,
+                    name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  // Load the (only) argument into r3.
+  __ LoadP(r3, MemOperand(sp, 0 * kPointerSize));
+
+  // If the argument is a smi, just return.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ andi(r0, r3, Operand(kSmiTagMask));
+  __ bne(&not_smi, cr0);
+  __ Drop(argc + 1);
+  __ Ret();
+  __ bind(&not_smi);
+
+  __ CheckMap(r3, r4, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
+
+  // Load the HeapNumber value.
+  __ lfd(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
+
+  // Round to integer minus
+  if (CpuFeatures::IsSupported(FPU)) {
+    // The frim instruction is only supported on POWER5
+    // and higher
+    __ frim(d1, d1);
+#if V8_TARGET_ARCH_PPC64
+    __ fctidz(d1, d1);
+#else
+    __ fctiwz(d1, d1);
+#endif
+  } else {
+    // This sequence is more portable (avoids frim)
+    // This should be evaluated to determine if frim provides any
+    // perf benefit or if we can simply use the compatible sequence
+    // always
+    __ SetRoundingMode(kRoundToMinusInf);
+#if V8_TARGET_ARCH_PPC64
+    __ fctid(d1, d1);
+#else
+    __ fctiw(d1, d1);
+#endif
+    __ ResetRoundingMode();
+  }
+  // Convert the argument to an integer.
+  __ stfdu(d1, MemOperand(sp, -8));
+#if V8_TARGET_ARCH_PPC64
+  __ ld(r3, MemOperand(sp, 0));
+#else
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ lwz(r3, MemOperand(sp, 0));
+#else
+  __ lwz(r3, MemOperand(sp, 4));
+#endif
+#endif
+  __ addi(sp, sp, Operand(8));
+
+  // if resulting conversion is negative, invert for bit tests
+  __ TestSignBit(r3, r0);
+  __ mr(r0, r3);
+  __ beq(&positive, cr0);
+  __ neg(r0, r3);
+  __ bind(&positive);
+
+  // if any of the high bits are set, fail to generic
+  __ JumpIfNotUnsignedSmiCandidate(r0, r0, &slow);
+
+  // Tag the result.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ SmiTag(r3);
+
+  // Check for -0
+  __ cmpi(r3, Operand::Zero());
+  __ bne(&drop_arg_return);
+
+  __ LoadP(r4, MemOperand(sp, 0 * kPointerSize));
+  __ lwz(r4, FieldMemOperand(r4, HeapNumber::kExponentOffset));
+  __ TestSignBit32(r4, r0);
+  __ beq(&drop_arg_return, cr0);
+  // If our HeapNumber is negative it was -0, so load its address and return.
+  __ LoadP(r3, MemOperand(sp));
+
+  __ bind(&drop_arg_return);
+  __ Drop(argc + 1);
+  __ Ret();
+
+  __ bind(&slow);
+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
+  __ InvokeFunction(
+      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
+
+  __ bind(&miss);
+  // r5: function name.
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+}
+
+
+Handle<Code> CallStubCompiler::CompileMathAbsCall(
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5                     : function name
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  const int argc = arguments().immediate();
+  // If the object is not a JSObject or we got an unexpected number of
+  // arguments, bail out to the regular call.
+  if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
+
+  Label miss;
+  GenerateNameCheck(name, &miss);
+  if (cell.is_null()) {
+    __ LoadP(r4, MemOperand(sp, 1 * kPointerSize));
+    STATIC_ASSERT(kSmiTag == 0);
+    __ JumpIfSmi(r4, &miss);
+    CheckPrototypes(Handle<JSObject>::cast(object), r4, holder, r3, r6, r7,
+                    name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  // Load the (only) argument into r3.
+  __ LoadP(r3, MemOperand(sp, 0 * kPointerSize));
+
+  // Check if the argument is a smi.
+  Label not_smi;
+  STATIC_ASSERT(kSmiTag == 0);
+  __ JumpIfNotSmi(r3, &not_smi);
+
+  // Do bitwise not or do nothing depending on the sign of the
+  // argument.
+  __ ShiftRightArithImm(r0, r3, kBitsPerPointer - 1);
+  __ xor_(r4, r3, r0);
+
+  // Add 1 or do nothing depending on the sign of the argument.
+  __ sub(r3, r4, r0, LeaveOE, SetRC);
+
+  // If the result is still negative, go to the slow case.
+  // This only happens for the most negative smi.
+  Label slow;
+  __ blt(&slow, cr0);
+
+  // Smi case done.
+  __ Drop(argc + 1);
+  __ Ret();
+
+  // Check if the argument is a heap number and load its exponent and
+  // sign.
+  __ bind(&not_smi);
+  __ CheckMap(r3, r4, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
+  __ lwz(r4, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+
+  // Check the sign of the argument. If the argument is positive,
+  // just return it.
+  Label negative_sign;
+  __ andis(r0, r4, Operand(HeapNumber::kSignMask >> 16));
+  __ bne(&negative_sign, cr0);
+  __ Drop(argc + 1);
+  __ Ret();
+
+  // If the argument is negative, clear the sign, and return a new
+  // number.
+  __ bind(&negative_sign);
+  STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
+  __ xoris(r4, r4, Operand(HeapNumber::kSignMask >> 16));
+  __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
+  __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(r3, r7, r8, r9, &slow);
+  __ stw(r4, FieldMemOperand(r3, HeapNumber::kExponentOffset));
+  __ stw(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
+  __ Drop(argc + 1);
+  __ Ret();
+
+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
+  __ bind(&slow);
+  __ InvokeFunction(
+      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
+
+  __ bind(&miss);
+  // r5: function name.
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+}
+
+
+Handle<Code> CallStubCompiler::CompileFastApiCall(
+    const CallOptimization& optimization,
+    Handle<Object> object,
+    Handle<JSObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  Counters* counters = isolate()->counters();
+
+  ASSERT(optimization.is_simple_api_call());
+  // Bail out if object is a global object as we don't want to
+  // repatch it to global receiver.
+  if (object->IsGlobalObject()) return Handle<Code>::null();
+  if (!cell.is_null()) return Handle<Code>::null();
+  if (!object->IsJSObject()) return Handle<Code>::null();
+  int depth = optimization.GetPrototypeDepthOfExpectedType(
+      Handle<JSObject>::cast(object), holder);
+  if (depth == kInvalidProtoDepth) return Handle<Code>::null();
+
+  Label miss, miss_before_stack_reserved;
+  GenerateNameCheck(name, &miss_before_stack_reserved);
+
+  // Get the receiver from the stack.
+  const int argc = arguments().immediate();
+  __ LoadP(r4, MemOperand(sp, argc * kPointerSize), r0);
+
+  // Check that the receiver isn't a smi.
+  __ JumpIfSmi(r4, &miss_before_stack_reserved);
+
+  __ IncrementCounter(counters->call_const(), 1, r3, r6);
+  __ IncrementCounter(counters->call_const_fast_api(), 1, r3, r6);
+
+  ReserveSpaceForFastApiCall(masm(), r3);
+
+  // Check that the maps haven't changed and find a Holder as a side effect.
+  CheckPrototypes(Handle<JSObject>::cast(object), r4, holder, r3, r6, r7, name,
+                  depth, &miss);
+
+  GenerateFastApiDirectCall(masm(), optimization, argc);
+
+  __ bind(&miss);
+  FreeSpaceForFastApiCall(masm());
+
+  __ bind(&miss_before_stack_reserved);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
+Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
+                                                   Handle<JSObject> holder,
+                                                   Handle<JSFunction> function,
+                                                   Handle<String> name,
+                                                   CheckType check) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  if (HasCustomCallGenerator(function)) {
+    Handle<Code> code = CompileCustomCall(object, holder,
+                                          Handle<JSGlobalPropertyCell>::null(),
+                                          function, name);
+    // A null handle means bail out to the regular compiler code below.
+    if (!code.is_null()) return code;
+  }
+
+  Label miss;
+  GenerateNameCheck(name, &miss);
+
+  // Get the receiver from the stack
+  const int argc = arguments().immediate();
+  __ LoadP(r4, MemOperand(sp, argc * kPointerSize), r0);
+
+  // Check that the receiver isn't a smi.
+  if (check != NUMBER_CHECK) {
+    __ JumpIfSmi(r4, &miss);
+  }
+
+  // Make sure that it's okay not to patch the on stack receiver
+  // unless we're doing a receiver map check.
+  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
+  switch (check) {
+    case RECEIVER_MAP_CHECK:
+      __ IncrementCounter(masm()->isolate()->counters()->call_const(),
+                          1, r3, r6);
+
+      // Check that the maps haven't changed.
+      CheckPrototypes(Handle<JSObject>::cast(object), r4, holder, r3, r6, r7,
+                      name, &miss);
+
+      // Patch the receiver on the stack with the global proxy if
+      // necessary.
+      if (object->IsGlobalObject()) {
+        __ LoadP(r6, FieldMemOperand(r4, GlobalObject::kGlobalReceiverOffset));
+        __ StoreP(r6, MemOperand(sp, argc * kPointerSize));
+      }
+      break;
+
+    case STRING_CHECK:
+      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
+        // Check that the object is a two-byte string or a symbol.
+        __ CompareObjectType(r4, r6, r6, FIRST_NONSTRING_TYPE);
+        __ bge(&miss);
+        // Check that the maps starting from the prototype haven't changed.
+        GenerateDirectLoadGlobalFunctionPrototype(
+            masm(), Context::STRING_FUNCTION_INDEX, r3, &miss);
+        CheckPrototypes(
+            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
+            r3, holder, r6, r4, r7, name, &miss);
+      } else {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
+        __ b(&miss);
+      }
+      break;
+
+    case NUMBER_CHECK:
+      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
+        Label fast;
+        // Check that the object is a smi or a heap number.
+        __ JumpIfSmi(r4, &fast);
+        __ CompareObjectType(r4, r3, r3, HEAP_NUMBER_TYPE);
+        __ bne(&miss);
+        __ bind(&fast);
+        // Check that the maps starting from the prototype haven't changed.
+        GenerateDirectLoadGlobalFunctionPrototype(
+            masm(), Context::NUMBER_FUNCTION_INDEX, r3, &miss);
+        CheckPrototypes(
+            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
+            r3, holder, r6, r4, r7, name, &miss);
+      } else {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
+        __ b(&miss);
+      }
+      break;
+
+    case BOOLEAN_CHECK:
+      if (function->IsBuiltin() || !function->shared()->is_classic_mode()) {
+        Label fast;
+        // Check that the object is a boolean.
+        __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+        __ cmp(r4, ip);
+        __ beq(&fast);
+        __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+        __ cmp(r4, ip);
+        __ bne(&miss);
+        __ bind(&fast);
+        // Check that the maps starting from the prototype haven't changed.
+        GenerateDirectLoadGlobalFunctionPrototype(
+            masm(), Context::BOOLEAN_FUNCTION_INDEX, r3, &miss);
+        CheckPrototypes(
+            Handle<JSObject>(JSObject::cast(object->GetPrototype())),
+            r3, holder, r6, r4, r7, name, &miss);
+      } else {
+        // Calling non-strict non-builtins with a value as the receiver
+        // requires boxing.
+        __ b(&miss);
+      }
+      break;
+  }
+
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  __ InvokeFunction(
+      function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(function);
+}
+
+
+Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
+                                                      Handle<JSObject> holder,
+                                                      Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+  GenerateNameCheck(name, &miss);
+
+  // Get the number of arguments.
+  const int argc = arguments().immediate();
+  LookupResult lookup(isolate());
+  LookupPostInterceptor(holder, name, &lookup);
+
+  // Get the receiver from the stack.
+  __ LoadP(r4, MemOperand(sp, argc * kPointerSize), r0);
+
+  CallInterceptorCompiler compiler(this, arguments(), r5, extra_state_);
+  compiler.Compile(masm(), object, holder, name, &lookup, r4, r6, r7, r3,
+                   &miss);
+
+  // Move returned value, the function to call, to r4.
+  __ mr(r4, r3);
+  // Restore receiver.
+  __ LoadP(r3, MemOperand(sp, argc * kPointerSize), r0);
+
+  GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(Code::INTERCEPTOR, name);
+}
+
+
+Handle<Code> CallStubCompiler::CompileCallGlobal(
+    Handle<JSObject> object,
+    Handle<GlobalObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<JSFunction> function,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  if (HasCustomCallGenerator(function)) {
+    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
+    // A null handle means bail out to the regular compiler code below.
+    if (!code.is_null()) return code;
+  }
+
+  Label miss;
+  GenerateNameCheck(name, &miss);
+
+  // Get the number of arguments.
+  const int argc = arguments().immediate();
+  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  GenerateLoadFunctionFromCell(cell, function, &miss);
+
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ LoadP(r6, FieldMemOperand(r3, GlobalObject::kGlobalReceiverOffset));
+    __ StoreP(r6, MemOperand(sp, argc * kPointerSize), r0);
+  }
+
+  // Set up the context (function already in r4).
+  __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
+
+  // Jump to the cached code (tail call).
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->call_global_inline(), 1, r6, r7);
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+      ? CALL_AS_FUNCTION
+      : CALL_AS_METHOD;
+  // We call indirectly through the code field in the function to
+  // allow recompilation to take effect without changing any of the
+  // call sites.
+  __ LoadP(r6, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
+  __ InvokeCode(r6, expected, arguments(), JUMP_FUNCTION,
+                NullCallWrapper(), call_kind);
+
+  // Handle call cache miss.
+  __ bind(&miss);
+  __ IncrementCounter(counters->call_global_inline_miss(), 1, r4, r6);
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(Code::NORMAL, name);
+}
+
+
+Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
+                                                  int index,
+                                                  Handle<Map> transition,
+                                                  Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  GenerateStoreField(masm(),
+                     object,
+                     index,
+                     transition,
+                     name,
+                     r4, r5, r6, r7,
+                     &miss);
+  __ bind(&miss);
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(transition.is_null()
+                 ? Code::FIELD
+                 : Code::MAP_TRANSITION, name);
+}
+
+
+Handle<Code> StoreStubCompiler::CompileStoreCallback(
+    Handle<String> name,
+    Handle<JSObject> receiver,
+    Handle<JSObject> holder,
+    Handle<AccessorInfo> callback) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+  // Check that the maps haven't changed.
+  __ JumpIfSmi(r4, &miss);
+  CheckPrototypes(receiver, r4, holder, r6, r7, r8, name, &miss);
+
+  // Stub never generated for non-global objects that require access checks.
+  ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
+
+  __ push(r4);  // receiver
+  __ mov(ip, Operand(callback));  // callback info
+  __ Push(ip, r5, r3);
+
+  // Do tail-call to the runtime system.
+  ExternalReference store_callback_property =
+      ExternalReference(IC_Utility(IC::kStoreCallbackProperty),
+                        masm()->isolate());
+  __ TailCallExternalReference(store_callback_property, 4, 1);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+#undef __
+#define __ ACCESS_MASM(masm)
+
+
+void StoreStubCompiler::GenerateStoreViaSetter(
+    MacroAssembler* masm,
+    Handle<JSFunction> setter) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+    // Save value register, so we can restore it later.
+    __ push(r3);
+
+    if (!setter.is_null()) {
+      // Call the JavaScript setter with receiver and value on the stack.
+      __ Push(r4, r3);
+      ParameterCount actual(1);
+      __ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
+                        CALL_AS_METHOD);
+    } else {
+      // If we generate a global code snippet for deoptimization only, remember
+      // the place to continue after deoptimization.
+      masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
+    }
+
+    // We have to return the passed value, not the return value of the setter.
+    __ pop(r3);
+
+    // Restore context register.
+    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  }
+  __ Ret();
+}
+
+
+#undef __
+#define __ ACCESS_MASM(masm())
+
+
+Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
+    Handle<String> name,
+    Handle<JSObject> receiver,
+    Handle<JSObject> holder,
+    Handle<JSFunction> setter) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the maps haven't changed.
+  __ JumpIfSmi(r4, &miss);
+  CheckPrototypes(receiver, r4, holder, r6, r7, r8, name, &miss);
+
+  GenerateStoreViaSetter(masm(), setter);
+
+  __ bind(&miss);
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
+    Handle<JSObject> receiver,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the map of the object hasn't changed.
+  __ CheckMap(r4, r6, Handle<Map>(receiver->map()), &miss,
+              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+
+  // Perform global security token check if needed.
+  if (receiver->IsJSGlobalProxy()) {
+    __ CheckAccessGlobalProxy(r4, r6, &miss);
+  }
+
+  // Stub is never generated for non-global objects that require access
+  // checks.
+  ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+
+  __ Push(r4, r5, r3);  // Receiver, name, value.
+
+  __ LoadSmiLiteral(r3, Smi::FromInt(strict_mode_));
+  __ push(r3);  // strict mode
+
+  // Do tail-call to the runtime system.
+  ExternalReference store_ic_property =
+      ExternalReference(IC_Utility(IC::kStoreInterceptorProperty),
+                        masm()->isolate());
+  __ TailCallExternalReference(store_ic_property, 4, 1);
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(Code::INTERCEPTOR, name);
+}
+
+
+Handle<Code> StoreStubCompiler::CompileStoreGlobal(
+    Handle<GlobalObject> object,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the map of the global has not changed.
+  __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset));
+  __ mov(r7, Operand(Handle<Map>(object->map())));
+  __ cmp(r6, r7);
+  __ bne(&miss);
+
+  // Check that the value in the cell is not the hole. If it is, this
+  // cell could have been deleted and reintroducing the global needs
+  // to update the property details in the property dictionary of the
+  // global object. We bail out to the runtime system to do that.
+  __ mov(r7, Operand(cell));
+  __ LoadRoot(r8, Heap::kTheHoleValueRootIndex);
+  __ LoadP(r9, FieldMemOperand(r7, JSGlobalPropertyCell::kValueOffset));
+  __ cmp(r8, r9);
+  __ beq(&miss);
+
+  // Store the value in the cell.
+  __ StoreP(r3, FieldMemOperand(r7, JSGlobalPropertyCell::kValueOffset), r0);
+  // Cells are always rescanned, so no write barrier here.
+
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->named_store_global_inline(), 1, r7, r6);
+  __ Ret();
+
+  // Handle store cache miss.
+  __ bind(&miss);
+  __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r7, r6);
+  Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(Code::NORMAL, name);
+}
+
+
+Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
+                                                      Handle<JSObject> object,
+                                                      Handle<JSObject> last) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that receiver is not a smi.
+  __ JumpIfSmi(r3, &miss);
+
+  // Check the maps of the full prototype chain.
+  CheckPrototypes(object, r3, last, r6, r4, r7, name, &miss);
+
+  // If the last object in the prototype chain is a global object,
+  // check that the global property cell is empty.
+  if (last->IsGlobalObject()) {
+    GenerateCheckPropertyCell(
+        masm(), Handle<GlobalObject>::cast(last), name, r4, &miss);
+  }
+
+  // Return undefined if maps of the full prototype chain are still the
+  // same and no global property with this name contains a value.
+  __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
+  __ Ret();
+
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::NONEXISTENT, factory()->empty_string());
+}
+
+
+Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
+                                                Handle<JSObject> holder,
+                                                int index,
+                                                Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  GenerateLoadField(object, holder, r3, r6, r4, r7, index, name, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::FIELD, name);
+}
+
+
+Handle<Code> LoadStubCompiler::CompileLoadCallback(
+    Handle<String> name,
+    Handle<JSObject> object,
+    Handle<JSObject> holder,
+    Handle<AccessorInfo> callback) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+  GenerateLoadCallback(object, holder, r3, r5, r6, r4, r7, r8, callback, name,
+                       &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+#undef __
+#define __ ACCESS_MASM(masm)
+
+
+void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
+                                             Handle<JSFunction> getter) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+
+    if (!getter.is_null()) {
+      // Call the JavaScript getter with the receiver on the stack.
+      __ push(r3);
+      ParameterCount actual(0);
+      __ InvokeFunction(getter, actual, CALL_FUNCTION, NullCallWrapper(),
+                        CALL_AS_METHOD);
+    } else {
+      // If we generate a global code snippet for deoptimization only, remember
+      // the place to continue after deoptimization.
+      masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
+    }
+
+    // Restore context register.
+    __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  }
+  __ Ret();
+}
+
+
+#undef __
+#define __ ACCESS_MASM(masm())
+
+
+Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
+    Handle<String> name,
+    Handle<JSObject> receiver,
+    Handle<JSObject> holder,
+    Handle<JSFunction> getter) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the maps haven't changed.
+  __ JumpIfSmi(r3, &miss);
+  CheckPrototypes(receiver, r3, holder, r6, r7, r4, name, &miss);
+
+  GenerateLoadViaGetter(masm(), getter);
+
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
+                                                   Handle<JSObject> holder,
+                                                   Handle<JSFunction> value,
+                                                   Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  GenerateLoadConstant(object, holder, r3, r6, r4, r7, value, name, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::CONSTANT_FUNCTION, name);
+}
+
+
+Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object,
+                                                      Handle<JSObject> holder,
+                                                      Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  LookupResult lookup(isolate());
+  LookupPostInterceptor(holder, name, &lookup);
+  GenerateLoadInterceptor(object, holder, &lookup, r3, r5, r6, r4, r7, name,
+                          &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::INTERCEPTOR, name);
+}
+
+
+Handle<Code> LoadStubCompiler::CompileLoadGlobal(
+    Handle<JSObject> object,
+    Handle<GlobalObject> holder,
+    Handle<JSGlobalPropertyCell> cell,
+    Handle<String> name,
+    bool is_dont_delete) {
+  // ----------- S t a t e -------------
+  //  -- r3    : receiver
+  //  -- r5    : name
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  // Check that the map of the global has not changed.
+  __ JumpIfSmi(r3, &miss);
+  CheckPrototypes(object, r3, holder, r6, r7, r4, name, &miss);
+
+  // Get the value from the cell.
+  __ mov(r6, Operand(cell));
+  __ LoadP(r7, FieldMemOperand(r6, JSGlobalPropertyCell::kValueOffset));
+
+  // Check for deleted property if property can actually be deleted.
+  if (!is_dont_delete) {
+    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+    __ cmp(r7, ip);
+    __ beq(&miss);
+  }
+
+  __ mr(r3, r7);
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->named_load_global_stub(), 1, r4, r6);
+  __ Ret();
+
+  __ bind(&miss);
+  __ IncrementCounter(counters->named_load_global_stub_miss(), 1, r4, r6);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::NORMAL, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
+                                                     Handle<JSObject> receiver,
+                                                     Handle<JSObject> holder,
+                                                     int index) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one.
+  __ Cmpi(r3, Operand(name), r0);
+  __ bne(&miss);
+
+  GenerateLoadField(receiver, holder, r4, r5, r6, r7, index, name, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(Code::FIELD, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
+    Handle<String> name,
+    Handle<JSObject> receiver,
+    Handle<JSObject> holder,
+    Handle<AccessorInfo> callback) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one.
+  __ Cmpi(r3, Operand(name), r0);
+  __ bne(&miss);
+
+  GenerateLoadCallback(receiver, holder, r4, r3, r5, r6, r7, r8, callback, name,
+                       &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
+    Handle<String> name,
+    Handle<JSObject> receiver,
+    Handle<JSObject> holder,
+    Handle<JSFunction> value) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one.
+  __ mov(r5, Operand(name));
+  __ cmp(r3, r5);
+  __ bne(&miss);
+
+  GenerateLoadConstant(receiver, holder, r4, r5, r6, r7, value, name, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(Code::CONSTANT_FUNCTION, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
+    Handle<JSObject> receiver,
+    Handle<JSObject> holder,
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one.
+  __ Cmpi(r3, Operand(name), r0);
+  __ bne(&miss);
+
+  LookupResult lookup(isolate());
+  LookupPostInterceptor(holder, name, &lookup);
+  GenerateLoadInterceptor(receiver, holder, &lookup, r4, r3, r5, r6, r7, name,
+                          &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(Code::INTERCEPTOR, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+
+  // Check the key is the cached one.
+  __ Cmpi(r3, Operand(name), r0);
+  __ bne(&miss);
+
+  GenerateLoadArrayLength(masm(), r4, r5, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_string_length(), 1, r5, r6);
+
+  // Check the key is the cached one.
+  __ Cmpi(r3, Operand(name), r0);
+  __ bne(&miss);
+
+  GenerateLoadStringLength(masm(), r4, r5, r6, &miss, true);
+  __ bind(&miss);
+  __ DecrementCounter(counters->keyed_load_string_length(), 1, r5, r6);
+
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
+    Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_load_function_prototype(), 1, r5, r6);
+
+  // Check the name hasn't changed.
+  __ Cmpi(r3, Operand(name), r0);
+  __ bne(&miss);
+
+  GenerateLoadFunctionPrototype(masm(), r4, r5, r6, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r5, r6);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(Code::CALLBACKS, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
+    Handle<Map> receiver_map) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  ElementsKind elements_kind = receiver_map->elements_kind();
+  Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
+
+  __ DispatchMap(r4, r5, receiver_map, stub, DO_SMI_CHECK);
+
+  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(Code::NORMAL, factory()->empty_string());
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
+    MapHandleList* receiver_maps,
+    CodeHandleList* handler_ics) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss;
+  __ JumpIfSmi(r4, &miss);
+
+  int receiver_count = receiver_maps->length();
+  __ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+  for (int current = 0; current < receiver_count; ++current) {
+    Label no_match;
+    __ mov(ip, Operand(receiver_maps->at(current)));
+    __ cmp(r5, ip);
+    __ bne(&no_match);
+    __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, al);
+    __ bind(&no_match);
+  }
+
+  __ bind(&miss);
+  Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
+  __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
+
+  // Return the generated code.
+  return GetCode(Code::NORMAL, factory()->empty_string(), MEGAMORPHIC);
+}
+
+
+Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
+                                                       int index,
+                                                       Handle<Map> transition,
+                                                       Handle<String> name) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : name
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  // -----------------------------------
+  Label miss;
+
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->keyed_store_field(), 1, r6, r7);
+
+  // Check that the name has not changed.
+  __ Cmpi(r4, Operand(name), r0);
+  __ bne(&miss);
+
+  // r6 is used as scratch register. r4 and r5 keep their values if a jump to
+  // the miss label is generated.
+  GenerateStoreField(masm(),
+                     object,
+                     index,
+                     transition,
+                     name,
+                     r5, r4, r6, r7,
+                     &miss);
+  __ bind(&miss);
+
+  __ DecrementCounter(counters->keyed_store_field(), 1, r6, r7);
+  Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(transition.is_null()
+                 ? Code::FIELD
+                 : Code::MAP_TRANSITION, name);
+}
+
+
+Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
+    Handle<Map> receiver_map) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : key
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  //  -- r6    : scratch
+  // -----------------------------------
+  ElementsKind elements_kind = receiver_map->elements_kind();
+  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
+  Handle<Code> stub =
+      KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
+
+  __ DispatchMap(r5, r6, receiver_map, stub, DO_SMI_CHECK);
+
+  Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode(Code::NORMAL, factory()->empty_string());
+}
+
+
+Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
+    MapHandleList* receiver_maps,
+    CodeHandleList* handler_stubs,
+    MapHandleList* transitioned_maps) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : key
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  //  -- r6    : scratch
+  // -----------------------------------
+  Label miss;
+  __ JumpIfSmi(r5, &miss);
+
+  int receiver_count = receiver_maps->length();
+  __ LoadP(r6, FieldMemOperand(r5, HeapObject::kMapOffset));
+  for (int i = 0; i < receiver_count; ++i) {
+    __ mov(ip, Operand(receiver_maps->at(i)));
+    __ cmp(r6, ip);
+    if (transitioned_maps->at(i).is_null()) {
+      Label skip;
+      __ bne(&skip);
+      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
+      __ bind(&skip);
+    } else {
+      Label next_map;
+      __ bne(&next_map);
+      __ mov(r6, Operand(transitioned_maps->at(i)));
+      __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al);
+      __ bind(&next_map);
+    }
+  }
+
+  __ bind(&miss);
+  Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
+  __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
+
+  // Return the generated code.
+  return GetCode(Code::NORMAL, factory()->empty_string(), MEGAMORPHIC);
+}
+
+
+Handle<Code> ConstructStubCompiler::CompileConstructStub(
+    Handle<JSFunction> function) {
+  // ----------- S t a t e -------------
+  //  -- r3    : argc
+  //  -- r4    : constructor
+  //  -- lr    : return address
+  //  -- [sp]  : last argument
+  // -----------------------------------
+  Label generic_stub_call;
+
+  // Use r10 for holding undefined which is used in several places below.
+  __ LoadRoot(r10, Heap::kUndefinedValueRootIndex);
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  // Check to see whether there are any break points in the function code. If
+  // there are jump to the generic constructor stub which calls the actual
+  // code for the function thereby hitting the break points.
+  __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r5, FieldMemOperand(r5, SharedFunctionInfo::kDebugInfoOffset));
+  __ cmp(r5, r10);
+  __ bne(&generic_stub_call);
+#endif
+
+  // Load the initial map and verify that it is in fact a map.
+  // r4: constructor function
+  // r10: undefined
+  __ LoadP(r5, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
+  __ JumpIfSmi(r5, &generic_stub_call);
+  __ CompareObjectType(r5, r6, r7, MAP_TYPE);
+  __ bne(&generic_stub_call);
+
+#ifdef DEBUG
+  // Cannot construct functions this way.
+  // r3: argc
+  // r4: constructor function
+  // r5: initial map
+  // r10: undefined
+  __ CompareInstanceType(r5, r6, JS_FUNCTION_TYPE);
+  __ Check(ne, "Function constructed by construct stub.");
+#endif
+
+  // Now allocate the JSObject in new space.
+  // r3: argc
+  // r4: constructor function
+  // r5: initial map
+  // r10: undefined
+  ASSERT(function->has_initial_map());
+  __ lbz(r6, FieldMemOperand(r5, Map::kInstanceSizeOffset));
+#ifdef DEBUG
+  int instance_size = function->initial_map()->instance_size();
+  __ cmpi(r6, Operand(instance_size >> kPointerSizeLog2));
+  __ Check(eq, "Instance size of initial map changed.");
+#endif
+  __ AllocateInNewSpace(r6, r7, r8, r9, &generic_stub_call, SIZE_IN_WORDS);
+
+  // Allocated the JSObject, now initialize the fields. Map is set to initial
+  // map and properties and elements are set to empty fixed array.
+  // r3: argc
+  // r4: constructor function
+  // r5: initial map
+  // r6: object size (in words)
+  // r7: JSObject (not tagged)
+  // r10: undefined
+  __ LoadRoot(r9, Heap::kEmptyFixedArrayRootIndex);
+  __ mr(r8, r7);
+  ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
+  __ StoreP(r5, MemOperand(r8));
+  __ addi(r8, r8, Operand(kPointerSize));
+  ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
+  __ StoreP(r9, MemOperand(r8));
+  __ addi(r8, r8, Operand(kPointerSize));
+  ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
+  __ StoreP(r9, MemOperand(r8));
+  __ addi(r8, r8, Operand(kPointerSize));
+
+  // Calculate the location of the first argument. The stack contains only the
+  // argc arguments.
+  __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2));
+  __ add(r4, sp, r4);
+
+  // Fill all the in-object properties with undefined.
+  // r3: argc
+  // r4: first argument
+  // r6: object size (in words)
+  // r7: JSObject (not tagged)
+  // r8: First in-object property of JSObject (not tagged)
+  // r10: undefined
+  // Fill the initialized properties with a constant value or a passed argument
+  // depending on the this.x = ...; assignment in the function.
+  Handle<SharedFunctionInfo> shared(function->shared());
+  for (int i = 0; i < shared->this_property_assignments_count(); i++) {
+    if (shared->IsThisPropertyAssignmentArgument(i)) {
+      Label not_passed, next;
+      // Check if the argument assigned to the property is actually passed.
+      int arg_number = shared->GetThisPropertyAssignmentArgument(i);
+      __ cmpi(r3, Operand(arg_number));
+      __ ble(&not_passed);
+      // Argument passed - find it on the stack.
+      __ LoadP(r5, MemOperand(r4, (arg_number + 1) * -kPointerSize), r0);
+      __ StoreP(r5, MemOperand(r8));
+      __ addi(r8, r8, Operand(kPointerSize));
+      __ b(&next);
+      __ bind(&not_passed);
+      // Set the property to undefined.
+      __ StoreP(r10, MemOperand(r8));
+      __ addi(r8, r8, Operand(kPointerSize));
+      __ bind(&next);
+    } else {
+      // Set the property to the constant value.
+      Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
+      __ mov(r5, Operand(constant));
+      __ StoreP(r5, MemOperand(r8));
+      __ addi(r8, r8, Operand(kPointerSize));
+    }
+  }
+
+  // Fill the unused in-object property fields with undefined.
+  ASSERT(function->has_initial_map());
+  for (int i = shared->this_property_assignments_count();
+       i < function->initial_map()->inobject_properties();
+       i++) {
+      __ StoreP(r10, MemOperand(r8));
+      __ addi(r8, r8, Operand(kPointerSize));
+  }
+
+  // r3: argc
+  // r7: JSObject (not tagged)
+  // Move argc to r4 and the JSObject to return to r3 and tag it.
+  __ mr(r4, r3);
+  __ mr(r3, r7);
+  __ ori(r3, r3, Operand(kHeapObjectTag));
+
+  // r3: JSObject
+  // r4: argc
+  // Remove caller arguments and receiver from the stack and return.
+  __ ShiftLeftImm(r4, r4, Operand(kPointerSizeLog2));
+  __ add(sp, sp, r4);
+  __ addi(sp, sp, Operand(kPointerSize));
+  Counters* counters = masm()->isolate()->counters();
+  __ IncrementCounter(counters->constructed_objects(), 1, r4, r5);
+  __ IncrementCounter(counters->constructed_objects_stub(), 1, r4, r5);
+  __ blr();
+
+  // Jump to the generic stub in case the specialized code cannot handle the
+  // construction.
+  __ bind(&generic_stub_call);
+  Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
+  __ Jump(code, RelocInfo::CODE_TARGET);
+
+  // Return the generated code.
+  return GetCode();
+}
+
+
+#undef __
+#define __ ACCESS_MASM(masm)
+
+
+void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
+    MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Label slow, miss_force_generic;
+
+  Register key = r3;
+  Register receiver = r4;
+
+  __ JumpIfNotSmi(key, &miss_force_generic);
+  __ SmiUntag(r5, key);
+  __ LoadP(r7, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ LoadFromNumberDictionary(&slow, r7, key, r3, r5, r6, r8);
+  __ Ret();
+
+  __ bind(&slow);
+  __ IncrementCounter(
+      masm->isolate()->counters()->keyed_load_external_array_slow(),
+      1, r5, r6);
+
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Handle<Code> slow_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_Slow();
+  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+
+  // Miss case, call the runtime.
+  __ bind(&miss_force_generic);
+
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+
+  Handle<Code> miss_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
+static void GenerateSmiKeyCheck(MacroAssembler* masm,
+                                Register key,
+                                Register scratch0,
+                                Register scratch1,
+                                DwVfpRegister double_scratch0,
+                                DwVfpRegister double_scratch1,
+                                Label* fail) {
+  Label key_ok;
+  // Check for smi or a smi inside a heap number.  We convert the heap
+  // number and check if the conversion is exact and fits into the smi
+  // range.
+  __ JumpIfSmi(key, &key_ok);
+  __ CheckMap(key,
+              scratch0,
+              Heap::kHeapNumberMapRootIndex,
+              fail,
+              DONT_DO_SMI_CHECK);
+  __ lfd(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset));
+  __ EmitVFPTruncate(kRoundToZero,
+                     scratch0,
+                     double_scratch0,
+                     scratch1,
+                     double_scratch1,
+                     kCheckForInexactConversion);
+  __ bne(fail);
+#if V8_TARGET_ARCH_PPC64
+  __ SmiTag(key, scratch0);
+#else
+  __ SmiTagCheckOverflow(scratch1, scratch0, r0);
+  __ BranchOnOverflow(fail);
+  __ mr(key, scratch1);
+#endif
+  __ bind(&key_ok);
+}
+
+
+void KeyedLoadStubCompiler::GenerateLoadExternalArray(
+    MacroAssembler* masm,
+    ElementsKind elements_kind) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Label miss_force_generic, slow, failed_allocation;
+
+  Register key = r3;
+  Register receiver = r4;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key, r7, r8, d1, d2, &miss_force_generic);
+
+  __ LoadP(r6, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  // r6: elements array
+
+  // Check that the index is in range.
+  __ LoadP(ip, FieldMemOperand(r6, ExternalArray::kLengthOffset));
+  __ cmpl(key, ip);
+  // Unsigned comparison catches both negative and too-large values.
+  __ bge(&miss_force_generic);
+
+  __ LoadP(r6, FieldMemOperand(r6, ExternalArray::kExternalPointerOffset));
+  // r6: base pointer of external storage
+
+  // We are not untagging smi key since an additional shift operation
+  // may be required to compute the array element's offset.
+
+  Register value = r5;
+  switch (elements_kind) {
+    case EXTERNAL_BYTE_ELEMENTS:
+      __ SmiToByteArrayOffset(value, key);
+      __ lbzx(value, MemOperand(r6, value));
+      __ extsb(value, value);
+      break;
+    case EXTERNAL_PIXEL_ELEMENTS:
+    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+      __ SmiToByteArrayOffset(value, key);
+      __ lbzx(value, MemOperand(r6, value));
+      break;
+    case EXTERNAL_SHORT_ELEMENTS:
+      __ SmiToShortArrayOffset(value, key);
+      __ lhzx(value, MemOperand(r6, value));
+      __ extsh(value, value);
+      break;
+    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+      __ SmiToShortArrayOffset(value, key);
+      __ lhzx(value, MemOperand(r6, value));
+      break;
+    case EXTERNAL_INT_ELEMENTS:
+      __ SmiToIntArrayOffset(value, key);
+      __ lwzx(value, MemOperand(r6, value));
+#if V8_TARGET_ARCH_PPC64
+      __ extsw(value, value);
+#endif
+      break;
+    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+      __ SmiToIntArrayOffset(value, key);
+      __ lwzx(value, MemOperand(r6, value));
+      break;
+    case EXTERNAL_FLOAT_ELEMENTS:
+      __ SmiToFloatArrayOffset(value, key);
+      __ lfsx(d0, MemOperand(r6, value));
+      break;
+    case EXTERNAL_DOUBLE_ELEMENTS:
+      __ SmiToDoubleArrayOffset(value, key);
+      __ lfdx(d0, MemOperand(r6, value));
+      break;
+    case FAST_ELEMENTS:
+    case FAST_SMI_ELEMENTS:
+    case FAST_DOUBLE_ELEMENTS:
+    case FAST_HOLEY_ELEMENTS:
+    case FAST_HOLEY_SMI_ELEMENTS:
+    case FAST_HOLEY_DOUBLE_ELEMENTS:
+    case DICTIONARY_ELEMENTS:
+    case NON_STRICT_ARGUMENTS_ELEMENTS:
+      UNREACHABLE();
+      break;
+  }
+
+  // For integer array types:
+  // r5: value
+  // For float array type:
+  // d0: single value
+  // For double array type:
+  // d0: double value
+
+  if (elements_kind == EXTERNAL_INT_ELEMENTS) {
+    // For the Int and UnsignedInt array types, we need to see whether
+    // the value can be represented in a Smi. If not, we need to convert
+    // it to a HeapNumber.
+#if !V8_TARGET_ARCH_PPC64
+    Label box_int;
+    // Check that the value fits in a smi.
+    __ JumpIfNotSmiCandidate(value, r0, &box_int);
+#endif
+    // Tag integer as smi and return it.
+    __ SmiTag(r3, value);
+    __ Ret();
+
+#if !V8_TARGET_ARCH_PPC64
+    __ bind(&box_int);
+    // Allocate a HeapNumber for the result and perform int-to-double
+    // conversion.  Don't touch r3 or r4 as they are needed if allocation
+    // fails.
+    __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r8, r6, r7, r9, &slow);
+    // Now we can use r3 for the result as key is not needed any more.
+    __ mr(r3, r8);
+
+    FloatingPointHelper::ConvertIntToDouble(
+      masm, value, d0);
+    __ stfd(d0, FieldMemOperand(r3, HeapNumber::kValueOffset));
+    __ Ret();
+#endif
+  } else if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
+    // The test is different for unsigned int values. Since we need
+    // the value to be in the range of a positive smi, we can't
+    // handle any of the high bits being set in the value.
+    Label box_int;
+    __ JumpIfNotUnsignedSmiCandidate(value, r0, &box_int);
+
+    // Tag integer as smi and return it.
+    __ SmiTag(r3, value);
+    __ Ret();
+
+    __ bind(&box_int);
+    // Allocate a HeapNumber for the result and perform int-to-double
+    // conversion. Don't use r3 and r4 as AllocateHeapNumber clobbers all
+    // registers - also when jumping due to exhausted young space.
+    __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r8, r6, r7, r9, &slow);
+    __ mr(r3, r8);
+
+    FloatingPointHelper::ConvertUnsignedIntToDouble(
+       masm, value, d0);
+    __ stfd(d0, FieldMemOperand(r3, HeapNumber::kValueOffset));
+    __ Ret();
+
+  } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+    // For the floating-point array type, we need to always allocate a
+    // HeapNumber.
+    // Allocate a HeapNumber for the result. Don't use r3 and r4 as
+    // AllocateHeapNumber clobbers all registers - also when jumping due to
+    // exhausted young space.
+    __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r5, r6, r7, r9, &slow);
+    __ stfd(d0, FieldMemOperand(r5, HeapNumber::kValueOffset));
+    __ mr(r3, r5);
+    __ Ret();
+
+  } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+    // Allocate a HeapNumber for the result. Don't use r3 and r4 as
+    // AllocateHeapNumber clobbers all registers - also when jumping due to
+    // exhausted young space.
+    __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r5, r6, r7, r9, &slow);
+    __ stfd(d0, FieldMemOperand(r5, HeapNumber::kValueOffset));
+    __ mr(r3, r5);
+    __ Ret();
+
+  } else {
+    // Tag integer as smi and return it.
+    __ SmiTag(r3, value);
+    __ Ret();
+  }
+
+  // Slow case, key and receiver still in r3 and r4.
+  __ bind(&slow);
+  __ IncrementCounter(
+      masm->isolate()->counters()->keyed_load_external_array_slow(),
+      1, r5, r6);
+
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+
+  __ Push(r4, r3);
+
+  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
+
+  __ bind(&miss_force_generic);
+  Handle<Code> stub =
+      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+  __ Jump(stub, RelocInfo::CODE_TARGET);
+}
+
+
+void KeyedStoreStubCompiler::GenerateStoreExternalArray(
+    MacroAssembler* masm,
+    ElementsKind elements_kind) {
+  // ---------- S t a t e --------------
+  //  -- r3     : value
+  //  -- r4     : key
+  //  -- r5     : receiver
+  //  -- lr     : return address
+  // -----------------------------------
+  Label slow, check_heap_number, miss_force_generic;
+
+  // Register usage.
+  Register value = r3;
+  Register key = r4;
+  Register receiver = r5;
+  // r6 mostly holds the elements array or the destination external array.
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key, r7, r8, d1, d2, &miss_force_generic);
+
+  __ LoadP(r6, FieldMemOperand(receiver, JSObject::kElementsOffset));
+
+  // Check that the index is in range
+  __ LoadP(ip, FieldMemOperand(r6, ExternalArray::kLengthOffset));
+  __ cmpl(key, ip);
+  // Unsigned comparison catches both negative and too-large values.
+  __ bge(&miss_force_generic);
+
+  // Handle both smis and HeapNumbers in the fast path. Go to the
+  // runtime for all other kinds of values.
+  // r6: external array.
+  if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
+    // Double to pixel conversion is only implemented in the runtime for now.
+    __ JumpIfNotSmi(value, &slow);
+  } else {
+    __ JumpIfNotSmi(value, &check_heap_number);
+  }
+  __ SmiUntag(r8, value);
+  __ LoadP(r6, FieldMemOperand(r6, ExternalArray::kExternalPointerOffset));
+
+  // r6: base pointer of external storage.
+  // r8: value (integer).
+  // r10: scratch register
+  switch (elements_kind) {
+    case EXTERNAL_PIXEL_ELEMENTS:
+      // Clamp the value to [0..255].
+      __ ClampUint8(r8, r8);
+      __ SmiToByteArrayOffset(r10, key);
+      __ stbx(r8, MemOperand(r6, r10));
+      break;
+    case EXTERNAL_BYTE_ELEMENTS:
+    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+      __ SmiToByteArrayOffset(r10, key);
+      __ stbx(r8, MemOperand(r6, r10));
+      break;
+    case EXTERNAL_SHORT_ELEMENTS:
+    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+      __ SmiToShortArrayOffset(r10, key);
+      __ sthx(r8, MemOperand(r6, r10));
+      break;
+    case EXTERNAL_INT_ELEMENTS:
+    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+      __ SmiToIntArrayOffset(r10, key);
+      __ stwx(r8, MemOperand(r6, r10));
+      break;
+    case EXTERNAL_FLOAT_ELEMENTS:
+      // Perform int-to-float conversion and store to memory.
+      __ SmiToFloatArrayOffset(r10, key);
+      // r10: efective address of the float element
+      FloatingPointHelper::ConvertIntToFloat(masm, d0, r8, r9);
+      __ stfsx(d0, MemOperand(r6, r10));
+      break;
+    case EXTERNAL_DOUBLE_ELEMENTS:
+      __ SmiToDoubleArrayOffset(r10, key);
+      // __ add(r6, r6, r10);
+      // r6: effective address of the double element
+      FloatingPointHelper::ConvertIntToDouble(
+          masm, r8,  d0);
+      __ stfdx(d0, MemOperand(r6, r10));
+      break;
+    case FAST_ELEMENTS:
+    case FAST_SMI_ELEMENTS:
+    case FAST_DOUBLE_ELEMENTS:
+    case FAST_HOLEY_ELEMENTS:
+    case FAST_HOLEY_SMI_ELEMENTS:
+    case FAST_HOLEY_DOUBLE_ELEMENTS:
+    case DICTIONARY_ELEMENTS:
+    case NON_STRICT_ARGUMENTS_ELEMENTS:
+      UNREACHABLE();
+      break;
+  }
+
+  // Entry registers are intact, r3 holds the value which is the return value.
+  __ Ret();
+
+  if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
+      // r6: external array.
+      __ bind(&check_heap_number);
+      __ CompareObjectType(value, r8, r9, HEAP_NUMBER_TYPE);
+      __ bne(&slow);
+
+      __ LoadP(r6, FieldMemOperand(r6, ExternalArray::kExternalPointerOffset));
+
+      // r6: base pointer of external storage.
+
+      // The WebGL specification leaves the behavior of storing NaN and
+      // +/-Infinity into integer arrays basically undefined. For more
+      // reproducible behavior, convert these to zero.
+
+      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
+        __ lfd(d0, FieldMemOperand(r3, HeapNumber::kValueOffset));
+        __ SmiToFloatArrayOffset(r8, key);
+        __ frsp(d0, d0);
+        __ stfsx(d0, MemOperand(r6, r8));
+      } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+        __ lfd(d0, FieldMemOperand(r3, HeapNumber::kValueOffset));
+        __ SmiToDoubleArrayOffset(r8, key);
+        __ stfdx(d0, MemOperand(r6, r8));
+      } else {
+        // Hoisted load.
+        __ mr(r8, value);
+        __ lfd(d0, FieldMemOperand(r8, HeapNumber::kValueOffset));
+
+        __ EmitECMATruncate(r8, d0, d1, r10, r7, r9);
+        switch (elements_kind) {
+          case EXTERNAL_BYTE_ELEMENTS:
+          case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+            __ SmiToByteArrayOffset(r10, key);
+            __ stbx(r8, MemOperand(r6, r10));
+            break;
+          case EXTERNAL_SHORT_ELEMENTS:
+          case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+            __ SmiToShortArrayOffset(r10, key);
+            __ sthx(r8, MemOperand(r6, r10));
+            break;
+          case EXTERNAL_INT_ELEMENTS:
+          case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+            __ SmiToIntArrayOffset(r10, key);
+            __ stwx(r8, MemOperand(r6, r10));
+            break;
+          case EXTERNAL_PIXEL_ELEMENTS:
+          case EXTERNAL_FLOAT_ELEMENTS:
+          case EXTERNAL_DOUBLE_ELEMENTS:
+          case FAST_ELEMENTS:
+          case FAST_SMI_ELEMENTS:
+          case FAST_DOUBLE_ELEMENTS:
+          case FAST_HOLEY_ELEMENTS:
+          case FAST_HOLEY_SMI_ELEMENTS:
+          case FAST_HOLEY_DOUBLE_ELEMENTS:
+          case DICTIONARY_ELEMENTS:
+          case NON_STRICT_ARGUMENTS_ELEMENTS:
+            UNREACHABLE();
+            break;
+        }
+      }
+
+    // Entry registers are intact, r3 holds the value which is the return
+    // value.
+    __ Ret();
+  }
+
+  // Slow case, key and receiver still in r3 and r4.
+  __ bind(&slow);
+  __ IncrementCounter(
+      masm->isolate()->counters()->keyed_load_external_array_slow(),
+      1, r5, r6);
+
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+  Handle<Code> slow_ic =
+      masm->isolate()->builtins()->KeyedStoreIC_Slow();
+  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+
+  // Miss case, call the runtime.
+  __ bind(&miss_force_generic);
+
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- r3     : key
+  //  -- r4     : receiver
+  // -----------------------------------
+
+  Handle<Code> miss_ic =
+      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
+void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss_force_generic;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, r3, r7, r8, d1, d2, &miss_force_generic);
+
+  // Get the elements array.
+  __ LoadP(r5, FieldMemOperand(r4, JSObject::kElementsOffset));
+  __ AssertFastElements(r5);
+
+  // Check that the key is within bounds.
+  __ LoadP(r6, FieldMemOperand(r5, FixedArray::kLengthOffset));
+  __ cmpl(r3, r6);
+  __ bge(&miss_force_generic);
+
+  // Load the result and make sure it's not the hole.
+  __ addi(r6, r5, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ SmiToPtrArrayOffset(r7, r3);
+  __ LoadPX(r7, MemOperand(r7, r6));
+  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  __ cmp(r7, ip);
+  __ beq(&miss_force_generic);
+  __ mr(r3, r7);
+  __ Ret();
+
+  __ bind(&miss_force_generic);
+  Handle<Code> stub =
+      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+  __ Jump(stub, RelocInfo::CODE_TARGET);
+}
+
+
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+    MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r3    : key
+  //  -- r4    : receiver
+  // -----------------------------------
+  Label miss_force_generic, slow_allocate_heapnumber;
+
+  Register key_reg = r3;
+  Register receiver_reg = r4;
+  Register elements_reg = r5;
+  Register heap_number_reg = r5;
+  Register indexed_double_offset = r6;
+  Register scratch = r7;
+  Register scratch2 = r8;
+  Register scratch3 = r9;
+  Register heap_number_map = r10;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key_reg, r7, r8, d1, d2, &miss_force_generic);
+
+  // Get the elements array.
+  __ LoadP(elements_reg,
+           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+  // Check that the key is within bounds.
+  __ LoadP(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+  __ cmpl(key_reg, scratch);
+  __ bge(&miss_force_generic);
+
+  // Load the upper word of the double in the fixed array and test for NaN.
+  __ SmiToDoubleArrayOffset(indexed_double_offset, key_reg);
+  __ add(indexed_double_offset, elements_reg, indexed_double_offset);
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
+#else
+  uint32_t upper_32_offset = FixedArray::kHeaderSize;
+#endif
+  __ lwz(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
+  __ Cmpi(scratch, Operand(kHoleNanUpper32), r0);
+  __ beq(&miss_force_generic);
+
+  // Non-NaN. Allocate a new heap number and copy the double value into it.
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
+                        heap_number_map, &slow_allocate_heapnumber);
+
+  // Don't need to reload the upper 32 bits of the double, it's already in
+  // scratch.
+  __ stw(scratch, FieldMemOperand(heap_number_reg,
+                                  HeapNumber::kExponentOffset));
+#if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
+  __ lwz(scratch, FieldMemOperand(indexed_double_offset,
+                                  FixedArray::kHeaderSize));
+#else
+  __ lwz(scratch, FieldMemOperand(indexed_double_offset,
+                                  FixedArray::kHeaderSize+4));
+#endif
+  __ stw(scratch, FieldMemOperand(heap_number_reg,
+                                  HeapNumber::kMantissaOffset));
+
+  __ mr(r3, heap_number_reg);
+  __ Ret();
+
+  __ bind(&slow_allocate_heapnumber);
+  Handle<Code> slow_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_Slow();
+  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+
+  __ bind(&miss_force_generic);
+  Handle<Code> miss_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
+void KeyedStoreStubCompiler::GenerateStoreFastElement(
+    MacroAssembler* masm,
+    bool is_js_array,
+    ElementsKind elements_kind,
+    KeyedAccessGrowMode grow_mode) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : key
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  //  -- r6    : scratch
+  //  -- r7    : scratch (elements)
+  // -----------------------------------
+  Label miss_force_generic, transition_elements_kind, grow, slow;
+  Label finish_store, check_capacity;
+
+  Register value_reg = r3;
+  Register key_reg = r4;
+  Register receiver_reg = r5;
+  Register scratch = r7;
+  Register elements_reg = r6;
+  Register length_reg = r8;
+  Register scratch2 = r9;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key_reg, r7, r8, d1, d2, &miss_force_generic);
+
+  if (IsFastSmiElementsKind(elements_kind)) {
+    __ JumpIfNotSmi(value_reg, &transition_elements_kind);
+  }
+
+  // Check that the key is within bounds.
+  __ LoadP(elements_reg,
+           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+  if (is_js_array) {
+    __ LoadP(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+  } else {
+    __ LoadP(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+  }
+  // Compare smis.
+  __ cmpl(key_reg, scratch);
+  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+    __ bge(&grow);
+  } else {
+    __ bge(&miss_force_generic);
+  }
+
+  // Make sure elements is a fast element array, not 'cow'.
+  __ CheckMap(elements_reg,
+              scratch,
+              Heap::kFixedArrayMapRootIndex,
+              &miss_force_generic,
+              DONT_DO_SMI_CHECK);
+
+  __ bind(&finish_store);
+  if (IsFastSmiElementsKind(elements_kind)) {
+    __ addi(scratch,
+            elements_reg,
+            Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+    __ SmiToPtrArrayOffset(scratch2, key_reg);
+    __ StorePX(value_reg, MemOperand(scratch, scratch2));
+  } else {
+    ASSERT(IsFastObjectElementsKind(elements_kind));
+    __ addi(scratch,
+            elements_reg,
+            Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+    __ SmiToPtrArrayOffset(scratch2, key_reg);
+    __ StorePUX(value_reg, MemOperand(scratch, scratch2));
+    __ mr(receiver_reg, value_reg);
+    __ RecordWrite(elements_reg,  // Object.
+                   scratch,       // Address.
+                   receiver_reg,  // Value.
+                   kLRHasNotBeenSaved,
+                   kDontSaveFPRegs);
+  }
+  // value_reg (r3) is preserved.
+  // Done.
+  __ Ret();
+
+  __ bind(&miss_force_generic);
+  Handle<Code> ic =
+      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  __ bind(&transition_elements_kind);
+  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
+  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
+
+  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+    // Grow the array by a single element if possible.
+    __ bind(&grow);
+
+    // Make sure the array is only growing by a single element, anything else
+    // must be handled by the runtime. Flags already set by previous compare.
+    __ bne(&miss_force_generic);
+
+    // Check for the empty array, and preallocate a small backing store if
+    // possible.
+    __ LoadP(length_reg,
+             FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+    __ LoadP(elements_reg,
+             FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+    __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex);
+    __ bne(&check_capacity);
+
+    int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
+    __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow,
+                          TAG_OBJECT);
+
+    __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
+    __ StoreP(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset), r0);
+    __ LoadSmiLiteral(scratch,
+                      Smi::FromInt(JSArray::kPreallocatedArrayElements));
+    __ StoreP(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset),
+              r0);
+    __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
+    for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
+      __ StoreP(scratch,
+                FieldMemOperand(elements_reg, FixedArray::SizeFor(i)), r0);
+    }
+
+    // Store the element at index zero.
+    __ StoreP(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0)),
+              r0);
+
+    // Install the new backing store in the JSArray.
+    __ StoreP(elements_reg,
+              FieldMemOperand(receiver_reg, JSObject::kElementsOffset), r0);
+    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
+                        scratch, kLRHasNotBeenSaved, kDontSaveFPRegs,
+                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+
+    // Increment the length of the array.
+    __ LoadSmiLiteral(length_reg, Smi::FromInt(1));
+    __ StoreP(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset),
+              r0);
+    __ Ret();
+
+    __ bind(&check_capacity);
+    // Check for cow elements, in general they are not handled by this stub
+    __ CheckMap(elements_reg,
+                scratch,
+                Heap::kFixedCOWArrayMapRootIndex,
+                &miss_force_generic,
+                DONT_DO_SMI_CHECK);
+
+    __ LoadP(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+    __ cmpl(length_reg, scratch);
+    __ bge(&slow);
+
+    // Grow the array and finish the store.
+    __ AddSmiLiteral(length_reg, length_reg, Smi::FromInt(1), r0);
+    __ StoreP(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset),
+              r0);
+    __ b(&finish_store);
+
+    __ bind(&slow);
+    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
+    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
+  }
+}
+
+
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+    MacroAssembler* masm,
+    bool is_js_array,
+    KeyedAccessGrowMode grow_mode) {
+  // ----------- S t a t e -------------
+  //  -- r3    : value
+  //  -- r4    : key
+  //  -- r5    : receiver
+  //  -- lr    : return address
+  //  -- r6    : scratch
+  //  -- r7    : scratch
+  //  -- r8    : scratch
+  // -----------------------------------
+  Label miss_force_generic, transition_elements_kind, grow, slow;
+  Label finish_store, check_capacity;
+
+  Register value_reg = r3;
+  Register key_reg = r4;
+  Register receiver_reg = r5;
+  Register elements_reg = r6;
+  Register scratch1 = r7;
+  Register scratch2 = r8;
+  Register scratch3 = r9;
+  Register scratch4 = r10;
+  Register length_reg = r10;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key_reg, r7, r8, d1, d2, &miss_force_generic);
+
+  __ LoadP(elements_reg,
+           FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+  // Check that the key is within bounds.
+  if (is_js_array) {
+    __ LoadP(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+  } else {
+    __ LoadP(scratch1,
+             FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+  }
+  // Compare smis, unsigned compare catches both negative and out-of-bound
+  // indexes.
+  __ cmpl(key_reg, scratch1);
+  if (grow_mode == ALLOW_JSARRAY_GROWTH) {
+    __ bge(&grow);
+  } else {
+    __ bge(&miss_force_generic);
+  }
+
+  __ bind(&finish_store);
+  __ StoreNumberToDoubleElements(value_reg,
+                                 key_reg,
+                                 receiver_reg,
+                                 // All registers after this are overwritten.
+                                 elements_reg,
+                                 scratch1,
+                                 scratch2,
+                                 scratch3,
+                                 scratch4,
+                                 &transition_elements_kind);
+  __ Ret();
+
+  // Handle store cache miss, replacing the ic with the generic stub.
+  __ bind(&miss_force_generic);
+  Handle<Code> ic =
+      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+
+  __ bind(&transition_elements_kind);
+  Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
+  __ Jump(ic_miss, RelocInfo::CODE_TARGET);
+
+  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+    // Grow the array by a single element if possible.
+    __ bind(&grow);
+
+    // Make sure the array is only growing by a single element, anything else
+    // must be handled by the runtime. Flags already set by previous compare.
+    __ bne(&miss_force_generic);
+
+    // Transition on values that can't be stored in a FixedDoubleArray.
+    Label value_is_smi;
+    __ JumpIfSmi(value_reg, &value_is_smi);
+    __ LoadP(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
+    __ CompareRoot(scratch1, Heap::kHeapNumberMapRootIndex);
+    __ bne(&transition_elements_kind);
+    __ bind(&value_is_smi);
+
+    // Check for the empty array, and preallocate a small backing store if
+    // possible.
+    __ LoadP(length_reg,
+             FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+    __ LoadP(elements_reg,
+             FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+    __ CompareRoot(elements_reg, Heap::kEmptyFixedArrayRootIndex);
+    __ bne(&check_capacity);
+
+    int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
+    __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
+                          TAG_OBJECT);
+
+    // Initialize the new FixedDoubleArray. Leave elements unitialized for
+    // efficiency, they are guaranteed to be initialized before use.
+    __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
+    __ StoreP(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset),
+              r0);
+    __ LoadSmiLiteral(scratch1,
+                      Smi::FromInt(JSArray::kPreallocatedArrayElements));
+    __ StoreP(scratch1,
+              FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset),
+              r0);
+
+    // Install the new backing store in the JSArray.
+    __ StoreP(elements_reg,
+              FieldMemOperand(receiver_reg, JSObject::kElementsOffset), r0);
+    __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
+                        scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs,
+                        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+
+    // Increment the length of the array.
+    __ LoadSmiLiteral(length_reg, Smi::FromInt(1));
+    __ StoreP(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset),
+              r0);
+    __ LoadP(elements_reg,
+             FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+    __ b(&finish_store);
+
+    __ bind(&check_capacity);
+    // Make sure that the backing store can hold additional elements.
+    __ LoadP(scratch1,
+             FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
+    __ cmpl(length_reg, scratch1);
+    __ bge(&slow);
+
+    // Grow the array and finish the store.
+    __ AddSmiLiteral(length_reg, length_reg, Smi::FromInt(1), r0);
+    __ StoreP(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset),
+              r0);
+    __ b(&finish_store);
+
+    __ bind(&slow);
+    Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
+    __ Jump(ic_slow, RelocInfo::CODE_TARGET);
+  }
+}
+
+
+#undef __
+
+} }  // namespace v8::internal
+
+#endif  // V8_TARGET_ARCH_PPC
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index b853f33..7e93e34 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -1819,7 +1819,10 @@ class IndexedReferencesExtractor : public ObjectVisitor {
     Address field = obj->address() + offset;
     ASSERT(!Memory::Object_at(field)->IsFailure());
     ASSERT(Memory::Object_at(field)->IsHeapObject());
-    *field |= kFailureTag;
+    // Address field is a byte pointer, we need to cast it
+    // to avoid setting the wrong bit on big endian platforms
+    intptr_t *tagged = reinterpret_cast<intptr_t *>(field);
+    *tagged |= kFailureTag;
   }
 
  private:
diff --git a/src/regexp-macro-assembler.h b/src/regexp-macro-assembler.h
index bcf3673..86c5626 100644
--- a/src/regexp-macro-assembler.h
+++ b/src/regexp-macro-assembler.h
@@ -54,6 +54,7 @@ class RegExpMacroAssembler {
     kIA32Implementation,
     kARMImplementation,
     kMIPSImplementation,
+    kPPCImplementation,
     kX64Implementation,
     kBytecodeImplementation
   };
diff --git a/src/runtime.cc b/src/runtime.cc
index 19d9a3f..5120b2c 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8553,8 +8553,15 @@ static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
 #else
 typedef uint64_t ObjectPair;
 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
   return reinterpret_cast<uint32_t>(x) |
       (reinterpret_cast<ObjectPair>(y) << 32);
+#else  // BIG ENDIAN
+  return reinterpret_cast<uint32_t>(y) |
+      (reinterpret_cast<ObjectPair>(x) << 32);
+#endif
+/*
+*/
 }
 #endif
 
diff --git a/src/serialize.cc b/src/serialize.cc
index 2ea09f8..3a5d018 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -697,6 +697,22 @@ void Deserializer::ReadObject(int space_number,
   bool is_codespace = (space_number == CODE_SPACE);
   ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace);
 #endif
+#if defined(_AIX) || defined(V8_TARGET_ARCH_PPC64)
+  // If we're on a platform that uses function_descriptors
+  // these jump tables make use of RelocInfo::INTERNAL_REFERENCE.
+  // As the V8 serialization code doesn't handle that relocation type
+  // we use this hack to fix up code that has function_descriptors
+  if (space_number == CODE_SPACE) {
+    Code * code = reinterpret_cast<Code*>(HeapObject::FromAddress(address));
+    for (RelocIterator it(code); !it.done(); it.next()) {
+      RelocInfo::Mode rmode = it.rinfo()->rmode();
+      if (rmode == RelocInfo::INTERNAL_REFERENCE) {
+        uintptr_t* p = reinterpret_cast<uintptr_t*>(code->instruction_start());
+        *p = reinterpret_cast<uintptr_t>(p + 3);
+      }
+    }
+  }
+#endif
 }
 
 void Deserializer::ReadChunk(Object** current,
@@ -941,15 +957,16 @@ void Deserializer::ReadChunk(Object** current,
       // allocation point and write a pointer to it to the current object.
       ALL_SPACES(kBackref, kPlain, kStartOfObject)
       ALL_SPACES(kBackrefWithSkip, kPlain, kStartOfObject)
-#if V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || \
+    defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64)
       // Deserialize a new object from pointer found in code and write
-      // a pointer to it to the current object. Required only for MIPS, and
+      // a pointer to it to the current object. Required only for MIPS/PPC, and
       // omitted on the other architectures because it is fully unrolled and
       // would cause bloat.
       ALL_SPACES(kNewObject, kFromCode, kStartOfObject)
       // Find a recently deserialized code object using its offset from the
       // current allocation point and write a pointer to it to the current
-      // object. Required only for MIPS.
+      // object. Required only for MIPS/PPC.
       ALL_SPACES(kBackref, kFromCode, kStartOfObject)
       ALL_SPACES(kBackrefWithSkip, kFromCode, kStartOfObject)
 #endif
@@ -1164,12 +1181,14 @@ int Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
   for (int i = 0; i < root_index_wave_front_; i++) {
     Object* root = heap->roots_array_start()[i];
     if (!root->IsSmi() && root == heap_object) {
-#if V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || \
+    defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64)
       if (from == kFromCode) {
-        // In order to avoid code bloat in the deserializer we don't have
-        // support for the encoding that specifies a particular root should
-        // be written into the lui/ori instructions on MIPS.  Therefore we
-        // should not generate such serialization data for MIPS.
+        // In order to avoid code bloat in the deserializer we don't
+        // have support for the encoding that specifies a particular
+        // root should be written into the lui/ori instructions on
+        // MIPS or lis/addic on PPC.  Therefore we should not generate
+        // such serialization data for MIPS/PPC.
         return kInvalidRootIndex;
       }
 #endif
diff --git a/src/simulator.h b/src/simulator.h
index 485e930..edfa42d 100644
--- a/src/simulator.h
+++ b/src/simulator.h
@@ -34,6 +34,8 @@
 #include "x64/simulator-x64.h"
 #elif V8_TARGET_ARCH_ARM
 #include "arm/simulator-arm.h"
+#elif V8_TARGET_ARCH_PPC
+#include "ppc/simulator-ppc.h"
 #elif V8_TARGET_ARCH_MIPS
 #include "mips/simulator-mips.h"
 #else
diff --git a/src/version.cc b/src/version.cc
index 715c2e5..f7dcbd3 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     14
 #define BUILD_NUMBER      5
-#define PATCH_LEVEL       8
+#define PATCH_LEVEL       9
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/test/cctest/.test-assembler-arm.cc.swp b/test/cctest/.test-assembler-arm.cc.swp
new file mode 100644
index 0000000..a67d410
Binary files /dev/null and b/test/cctest/.test-assembler-arm.cc.swp differ
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 66d848c..05330dd 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -118,6 +118,12 @@
             'test-disasm-arm.cc'
           ],
         }],
+        ['v8_target_arch=="ppc" or v8_target_arch=="ppc64"', {
+          'sources': [
+            'test-assembler-ppc.cc',
+            'test-disasm-ppc.cc'
+          ],
+        }],
         ['v8_target_arch=="mipsel"', {
           'sources': [
             'test-assembler-mips.cc',
@@ -134,6 +140,11 @@
             'test-platform-macos.cc',
           ],
         }],
+        [ 'OS=="aix" and v8_target_arch=="ppc64"', {
+          'sources': [
+            'test-api2.cc',
+          ],
+        }],
         [ 'OS=="win"', {
           'sources': [
             'test-platform-win32.cc',
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 728a8f7..d078178 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -46,6 +46,18 @@
 #include "parser.h"
 #include "unicode-inl.h"
 
+#if defined(_AIX) && defined(V8_HOST_ARCH_64_BIT)
+// AIX gcc is unable to compile this file in its entirety due to the
+// following open issue:
+//   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=378
+// As a workaround, the file is split into two parts: test-api.cc and
+// test-api2.cc.
+#define TEST_API_IN_PARTS
+#if !defined(TEST_API_PART2)
+#define TEST_API_PART1
+#endif
+#endif
+
 static const bool kLogThreading = false;
 
 static bool IsNaN(double x) {
diff --git a/test/cctest/test-api2.cc b/test/cctest/test-api2.cc
new file mode 100644
index 0000000..982ff61
--- /dev/null
+++ b/test/cctest/test-api2.cc
@@ -0,0 +1,37 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include "v8.h"
+
+#if defined(_AIX) && defined(V8_HOST_ARCH_64_BIT)
+#define TEST_API_PART2
+// AIX gcc is unable to compile test-api.cc in its entirety due to the
+// following open issue:
+//   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=378
+// As a workaround, the file is split into two parts: test-api.cc and
+// test-api2.cc.
+#include "test-api.cc"
+#endif
diff --git a/test/cctest/test-assembler-ppc.cc b/test/cctest/test-assembler-ppc.cc
new file mode 100644
index 0000000..6e2a448
--- /dev/null
+++ b/test/cctest/test-assembler-ppc.cc
@@ -0,0 +1,1076 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "disassembler.h"
+#include "factory.h"
+#include "ppc/simulator-ppc.h"
+#include "ppc/assembler-ppc-inl.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+// Define these function prototypes to match JSEntryFunction in execution.cc.
+typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
+typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
+typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
+typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
+
+
+static v8::Persistent<v8::Context> env;
+
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
+#define __ assm.
+
+// Simple add parameter 1 to parameter 2 and return
+TEST(0) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+
+  __ add(r3, r3, r4);
+  __ blr();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+  intptr_t res =
+    reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
+  ::printf("f() = %" V8PRIdPTR "\n", res);
+  CHECK_EQ(7, static_cast<int>(res));
+}
+
+// Loop 100 times, adding loop counter to result
+TEST(1) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+  Label L, C;
+
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+
+  __ mr(r4, r3);
+  __ li(r3, Operand(0, RelocInfo::NONE));
+  __ b(&C);
+
+  __ bind(&L);
+  __ add(r3, r3, r4);
+  __ subi(r4, r4, Operand(1));
+
+  __ bind(&C);
+  __ cmpi(r4, Operand(0, RelocInfo::NONE));
+  __ bne(&L);
+  __ blr();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+  intptr_t res =
+    reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
+  ::printf("f() = %" V8PRIdPTR  "\n", res);
+  CHECK_EQ(5050, static_cast<int>(res));
+}
+
+
+TEST(2) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+  Label L, C;
+
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+
+  __ mr(r4, r3);
+  __ li(r3, Operand(1));
+  __ b(&C);
+
+  __ bind(&L);
+#if defined(V8_TARGET_ARCH_PPC64)
+  __ mulld(r3, r4, r3);
+#else
+  __ mullw(r3, r4, r3);
+#endif
+  __ subi(r4, r4, Operand(1));
+
+  __ bind(&C);
+  __ cmpi(r4, Operand(0, RelocInfo::NONE));
+  __ bne(&L);
+  __ blr();
+
+  // some relocated stuff here, not executed
+  __ RecordComment("dead code, just testing relocations");
+  __ mov(r0, Operand(FACTORY->true_value()));
+  __ RecordComment("dead code, just testing immediate operands");
+  __ mov(r0, Operand(-1));
+  __ mov(r0, Operand(0xFF000000));
+  __ mov(r0, Operand(0xF0F0F0F0));
+  __ mov(r0, Operand(0xFFF0FFFF));
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+  intptr_t res =
+    reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
+  ::printf("f() = %" V8PRIdPTR "\n", res);
+  CHECK_EQ(3628800, static_cast<int>(res));
+}
+
+
+
+TEST(3) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    int i;
+    char c;
+    int16_t s;
+  } T;
+  T t;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+  Label L, C;
+
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+
+  // build a frame
+#if V8_TARGET_ARCH_PPC64
+  __ stdu(sp, MemOperand(sp, -32));
+  __ std(fp, MemOperand(sp, 24));
+#else
+  __ stwu(sp, MemOperand(sp, -16));
+  __ stw(fp, MemOperand(sp, 12));
+#endif
+  __ mr(fp, sp);
+
+  // r4 points to our struct
+  __ mr(r4, r3);
+
+  // modify field int i of struct
+  __ lwz(r3, MemOperand(r4, OFFSET_OF(T, i)));
+  __ srwi(r5, r3, Operand(1));
+  __ stw(r5, MemOperand(r4, OFFSET_OF(T, i)));
+
+  // modify field char c of struct
+  __ lbz(r5, MemOperand(r4, OFFSET_OF(T, c)));
+  __ add(r3, r5, r3);
+  __ slwi(r5, r5, Operand(2));
+  __ stb(r5, MemOperand(r4, OFFSET_OF(T, c)));
+
+  // modify field int16_t s of struct
+  __ lhz(r5, MemOperand(r4, OFFSET_OF(T, s)));
+  __ add(r3, r5, r3);
+  __ srwi(r5, r5, Operand(3));
+  __ sth(r5, MemOperand(r4, OFFSET_OF(T, s)));
+
+  // restore frame
+#if V8_TARGET_ARCH_PPC64
+  __ addi(r11, fp, Operand(32));
+  __ ld(fp, MemOperand(r11, -8));
+#else
+  __ addi(r11, fp, Operand(16));
+  __ lwz(fp, MemOperand(r11, -4));
+#endif
+  __ mr(sp, r11);
+  __ blr();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+  t.i = 100000;
+  t.c = 10;
+  t.s = 1000;
+  intptr_t res =
+    reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
+  ::printf("f() = %" V8PRIdPTR "\n", res);
+  CHECK_EQ(101010, static_cast<int>(res));
+  CHECK_EQ(100000/2, t.i);
+  CHECK_EQ(10*4, t.c);
+  CHECK_EQ(1000/8, t.s);
+}
+
+#if 0
+TEST(4) {
+  // Test the VFP floating point instructions.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    double c;
+    double d;
+    double e;
+    double f;
+    double g;
+    double h;
+    int i;
+    double m;
+    double n;
+    float x;
+    float y;
+  } T;
+  T t;
+
+  // Create a function that accepts &t, and loads, manipulates, and stores
+  // the doubles and floats.
+  Assembler assm(Isolate::Current(), NULL, 0);
+  Label L, C;
+
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+
+    __ mov(ip, Operand(sp));
+    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
+    __ sub(fp, ip, Operand(4));
+
+    __ mov(r4, Operand(r0));
+    __ vldr(d6, r4, OFFSET_OF(T, a));
+    __ vldr(d7, r4, OFFSET_OF(T, b));
+    __ vadd(d5, d6, d7);
+    __ vstr(d5, r4, OFFSET_OF(T, c));
+
+    __ vmov(r2, r3, d5);
+    __ vmov(d4, r2, r3);
+    __ vstr(d4, r4, OFFSET_OF(T, b));
+
+    // Load t.x and t.y, switch values, and store back to the struct.
+    __ vldr(s0, r4, OFFSET_OF(T, x));
+    __ vldr(s31, r4, OFFSET_OF(T, y));
+    __ vmov(s16, s0);
+    __ vmov(s0, s31);
+    __ vmov(s31, s16);
+    __ vstr(s0, r4, OFFSET_OF(T, x));
+    __ vstr(s31, r4, OFFSET_OF(T, y));
+
+    // Move a literal into a register that can be encoded in the instruction.
+    __ vmov(d4, 1.0);
+    __ vstr(d4, r4, OFFSET_OF(T, e));
+
+    // Move a literal into a register that requires 64 bits to encode.
+    // 0x3ff0000010000000 = 1.000000059604644775390625
+    __ vmov(d4, 1.000000059604644775390625);
+    __ vstr(d4, r4, OFFSET_OF(T, d));
+
+    // Convert from floating point to integer.
+    __ vmov(d4, 2.0);
+    __ vcvt_s32_f64(s31, d4);
+    __ vstr(s31, r4, OFFSET_OF(T, i));
+
+    // Convert from integer to floating point.
+    __ mov(lr, Operand(42));
+    __ vmov(s31, lr);
+    __ vcvt_f64_s32(d4, s31);
+    __ vstr(d4, r4, OFFSET_OF(T, f));
+
+    // Test vabs.
+    __ vldr(d1, r4, OFFSET_OF(T, g));
+    __ vabs(d0, d1);
+    __ vstr(d0, r4, OFFSET_OF(T, g));
+    __ vldr(d2, r4, OFFSET_OF(T, h));
+    __ vabs(d0, d2);
+    __ vstr(d0, r4, OFFSET_OF(T, h));
+
+    // Test vneg.
+    __ vldr(d1, r4, OFFSET_OF(T, m));
+    __ vneg(d0, d1);
+    __ vstr(d0, r4, OFFSET_OF(T, m));
+    __ vldr(d1, r4, OFFSET_OF(T, n));
+    __ vneg(d0, d1);
+    __ vstr(d0, r4, OFFSET_OF(T, n));
+
+    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+    t.a = 1.5;
+    t.b = 2.75;
+    t.c = 17.17;
+    t.d = 0.0;
+    t.e = 0.0;
+    t.f = 0.0;
+    t.g = -2718.2818;
+    t.h = 31415926.5;
+    t.i = 0;
+    t.m = -2718.2818;
+    t.n = 123.456;
+    t.x = 4.5;
+    t.y = 9.0;
+    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
+    USE(dummy);
+    CHECK_EQ(4.5, t.y);
+    CHECK_EQ(9.0, t.x);
+    CHECK_EQ(-123.456, t.n);
+    CHECK_EQ(2718.2818, t.m);
+    CHECK_EQ(2, t.i);
+    CHECK_EQ(2718.2818, t.g);
+    CHECK_EQ(31415926.5, t.h);
+    CHECK_EQ(42.0, t.f);
+    CHECK_EQ(1.0, t.e);
+    CHECK_EQ(1.000000059604644775390625, t.d);
+    CHECK_EQ(4.25, t.c);
+    CHECK_EQ(4.25, t.b);
+    CHECK_EQ(1.5, t.a);
+  }
+}
+
+
+TEST(5) {
+  // Test the ARMv7 bitfield instructions.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatures::Scope scope(ARMv7);
+    // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
+    __ ubfx(r0, r0, 1, 12);  // 0b00..010101010101 = 0x555
+    __ sbfx(r0, r0, 0, 5);   // 0b11..111111110101 = -11
+    __ bfc(r0, 1, 3);        // 0b11..111111110001 = -15
+    __ mov(r1, Operand(7));
+    __ bfi(r0, r1, 3, 3);    // 0b11..111111111001 = -7
+    __ mov(pc, Operand(lr));
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+    int res = reinterpret_cast<int>(
+                CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
+    ::printf("f() = %d\n", res);
+    CHECK_EQ(-7, res);
+  }
+}
+
+
+TEST(6) {
+  // Test saturating instructions.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatures::Scope scope(ARMv7);
+    __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
+    __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
+    __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
+    __ addi(r0, r1, Operand(r2));
+    __ addi(r0, r0, Operand(r3));
+    __ mov(pc, Operand(lr));
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+    int res = reinterpret_cast<int>(
+                CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
+    ::printf("f() = %d\n", res);
+    CHECK_EQ(382, res);
+  }
+}
+
+enum VCVTTypes {
+  s32_f64,
+  u32_f64
+};
+
+static void TestRoundingMode(VCVTTypes types,
+                             VFPRoundingMode mode,
+                             double value,
+                             int expected,
+                             bool expected_exception = false) {
+  InitializeVM();
+  v8::HandleScope scope;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+
+    Label wrong_exception;
+
+    __ vmrs(r1);
+    // Set custom FPSCR.
+    __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
+    __ orr(r2, r2, Operand(mode));
+    __ vmsr(r2);
+
+    // Load value, convert, and move back result to r0 if everything went well.
+    __ vmov(d1, value);
+    switch (types) {
+      case s32_f64:
+        __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
+        break;
+
+      case u32_f64:
+        __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
+        break;
+
+      default:
+        UNREACHABLE();
+        break;
+    }
+    // Check for vfp exceptions
+    __ vmrs(r2);
+    __ tst(r2, Operand(kVFPExceptionMask));
+    // Check that we behaved as expected.
+    __ b(&wrong_exception,
+         expected_exception ? eq : ne);
+    // There was no exception. Retrieve the result and return.
+    __ vmov(r0, s0);
+    __ mov(pc, Operand(lr));
+
+    // The exception behaviour is not what we expected.
+    // Load a special value and return.
+    __ bind(&wrong_exception);
+    __ mov(r0, Operand(11223344));
+    __ mov(pc, Operand(lr));
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+    int res = reinterpret_cast<int>(
+                CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
+    ::printf("res = %d\n", res);
+    CHECK_EQ(expected, res);
+  }
+}
+
+
+TEST(7) {
+  // Test vfp rounding modes.
+
+  // s32_f64 (double to integer).
+
+  TestRoundingMode(s32_f64, RN,  0, 0);
+  TestRoundingMode(s32_f64, RN,  0.5, 0);
+  TestRoundingMode(s32_f64, RN, -0.5, 0);
+  TestRoundingMode(s32_f64, RN,  1.5, 2);
+  TestRoundingMode(s32_f64, RN, -1.5, -2);
+  TestRoundingMode(s32_f64, RN,  123.7, 124);
+  TestRoundingMode(s32_f64, RN, -123.7, -124);
+  TestRoundingMode(s32_f64, RN,  123456.2,  123456);
+  TestRoundingMode(s32_f64, RN, -123456.2, -123456);
+  TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
+  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
+  TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
+  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
+  TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
+  TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
+  TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
+  TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
+
+  TestRoundingMode(s32_f64, RM,  0, 0);
+  TestRoundingMode(s32_f64, RM,  0.5, 0);
+  TestRoundingMode(s32_f64, RM, -0.5, -1);
+  TestRoundingMode(s32_f64, RM,  123.7, 123);
+  TestRoundingMode(s32_f64, RM, -123.7, -124);
+  TestRoundingMode(s32_f64, RM,  123456.2,  123456);
+  TestRoundingMode(s32_f64, RM, -123456.2, -123457);
+  TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
+  TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
+  TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
+  TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
+  TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
+  TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
+
+  TestRoundingMode(s32_f64, RZ,  0, 0);
+  TestRoundingMode(s32_f64, RZ,  0.5, 0);
+  TestRoundingMode(s32_f64, RZ, -0.5, 0);
+  TestRoundingMode(s32_f64, RZ,  123.7,  123);
+  TestRoundingMode(s32_f64, RZ, -123.7, -123);
+  TestRoundingMode(s32_f64, RZ,  123456.2,  123456);
+  TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
+  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
+  TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
+  TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
+  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
+  TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
+  TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
+
+
+  // u32_f64 (double to integer).
+
+  // Negative values.
+  TestRoundingMode(u32_f64, RN, -0.5, 0);
+  TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
+  TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
+  TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
+
+  TestRoundingMode(u32_f64, RM, -0.5, 0, true);
+  TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
+  TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
+  TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
+
+  TestRoundingMode(u32_f64, RZ, -0.5, 0);
+  TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
+  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
+  TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
+
+  // Positive values.
+  // kMaxInt is the maximum *signed* integer: 0x7fffffff.
+  static const uint32_t kMaxUInt = 0xffffffffu;
+  TestRoundingMode(u32_f64, RZ,  0, 0);
+  TestRoundingMode(u32_f64, RZ,  0.5, 0);
+  TestRoundingMode(u32_f64, RZ,  123.7,  123);
+  TestRoundingMode(u32_f64, RZ,  123456.2,  123456);
+  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
+  TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
+  TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
+                                static_cast<uint32_t>(kMaxInt) + 1);
+  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
+  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
+
+  TestRoundingMode(u32_f64, RM,  0, 0);
+  TestRoundingMode(u32_f64, RM,  0.5, 0);
+  TestRoundingMode(u32_f64, RM,  123.7, 123);
+  TestRoundingMode(u32_f64, RM,  123456.2,  123456);
+  TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
+  TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
+  TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
+                                static_cast<uint32_t>(kMaxInt) + 1);
+  TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
+  TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
+
+  TestRoundingMode(u32_f64, RN,  0, 0);
+  TestRoundingMode(u32_f64, RN,  0.5, 0);
+  TestRoundingMode(u32_f64, RN,  1.5, 2);
+  TestRoundingMode(u32_f64, RN,  123.7, 124);
+  TestRoundingMode(u32_f64, RN,  123456.2,  123456);
+  TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
+  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
+  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
+                                static_cast<uint32_t>(kMaxInt) + 1);
+  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
+  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
+  TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
+}
+
+TEST(8) {
+  // Test VFP multi load/store with ia_w.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    double c;
+    double d;
+    double e;
+    double f;
+    double g;
+    double h;
+  } D;
+  D d;
+
+  typedef struct {
+    float a;
+    float b;
+    float c;
+    float d;
+    float e;
+    float f;
+    float g;
+    float h;
+  } F;
+  F f;
+
+  // Create a function that uses vldm/vstm to move some double and
+  // single precision values around in memory.
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  if (CpuFeatures::IsSupported(VFP2)) {
+    CpuFeatures::Scope scope(VFP2);
+
+    __ mov(ip, Operand(sp));
+    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
+    __ sub(fp, ip, Operand(4));
+
+    __ addi(r4, r0, Operand(OFFSET_OF(D, a)));
+    __ vldm(ia_w, r4, d0, d3);
+    __ vldm(ia_w, r4, d4, d7);
+
+    __ addi(r4, r0, Operand(OFFSET_OF(D, a)));
+    __ vstm(ia_w, r4, d6, d7);
+    __ vstm(ia_w, r4, d0, d5);
+
+    __ addi(r4, r1, Operand(OFFSET_OF(F, a)));
+    __ vldm(ia_w, r4, s0, s3);
+    __ vldm(ia_w, r4, s4, s7);
+
+    __ addi(r4, r1, Operand(OFFSET_OF(F, a)));
+    __ vstm(ia_w, r4, s6, s7);
+    __ vstm(ia_w, r4, s0, s5);
+
+    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
+    d.a = 1.1;
+    d.b = 2.2;
+    d.c = 3.3;
+    d.d = 4.4;
+    d.e = 5.5;
+    d.f = 6.6;
+    d.g = 7.7;
+    d.h = 8.8;
+
+    f.a = 1.0;
+    f.b = 2.0;
+    f.c = 3.0;
+    f.d = 4.0;
+    f.e = 5.0;
+    f.f = 6.0;
+    f.g = 7.0;
+    f.h = 8.0;
+
+    Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
+    USE(dummy);
+
+    CHECK_EQ(7.7, d.a);
+    CHECK_EQ(8.8, d.b);
+    CHECK_EQ(1.1, d.c);
+    CHECK_EQ(2.2, d.d);
+    CHECK_EQ(3.3, d.e);
+    CHECK_EQ(4.4, d.f);
+    CHECK_EQ(5.5, d.g);
+    CHECK_EQ(6.6, d.h);
+
+    CHECK_EQ(7.0, f.a);
+    CHECK_EQ(8.0, f.b);
+    CHECK_EQ(1.0, f.c);
+    CHECK_EQ(2.0, f.d);
+    CHECK_EQ(3.0, f.e);
+    CHECK_EQ(4.0, f.f);
+    CHECK_EQ(5.0, f.g);
+    CHECK_EQ(6.0, f.h);
+  }
+}
+
+
+TEST(9) {
+  // Test VFP multi load/store with ia.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    double c;
+    double d;
+    double e;
+    double f;
+    double g;
+    double h;
+  } D;
+  D d;
+
+  typedef struct {
+    float a;
+    float b;
+    float c;
+    float d;
+    float e;
+    float f;
+    float g;
+    float h;
+  } F;
+  F f;
+
+  // Create a function that uses vldm/vstm to move some double and
+  // single precision values around in memory.
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  if (CpuFeatures::IsSupported(VFP2)) {
+    CpuFeatures::Scope scope(VFP2);
+
+    __ mov(ip, Operand(sp));
+    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
+    __ sub(fp, ip, Operand(4));
+
+    __ addi(r4, r0, Operand(OFFSET_OF(D, a)));
+    __ vldm(ia, r4, d0, d3);
+    __ addi(r4, r4, Operand(4 * 8));
+    __ vldm(ia, r4, d4, d7);
+
+    __ addi(r4, r0, Operand(OFFSET_OF(D, a)));
+    __ vstm(ia, r4, d6, d7);
+    __ addi(r4, r4, Operand(2 * 8));
+    __ vstm(ia, r4, d0, d5);
+
+    __ addi(r4, r1, Operand(OFFSET_OF(F, a)));
+    __ vldm(ia, r4, s0, s3);
+    __ addi(r4, r4, Operand(4 * 4));
+    __ vldm(ia, r4, s4, s7);
+
+    __ addi(r4, r1, Operand(OFFSET_OF(F, a)));
+    __ vstm(ia, r4, s6, s7);
+    __ addi(r4, r4, Operand(2 * 4));
+    __ vstm(ia, r4, s0, s5);
+
+    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
+    d.a = 1.1;
+    d.b = 2.2;
+    d.c = 3.3;
+    d.d = 4.4;
+    d.e = 5.5;
+    d.f = 6.6;
+    d.g = 7.7;
+    d.h = 8.8;
+
+    f.a = 1.0;
+    f.b = 2.0;
+    f.c = 3.0;
+    f.d = 4.0;
+    f.e = 5.0;
+    f.f = 6.0;
+    f.g = 7.0;
+    f.h = 8.0;
+
+    Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
+    USE(dummy);
+
+    CHECK_EQ(7.7, d.a);
+    CHECK_EQ(8.8, d.b);
+    CHECK_EQ(1.1, d.c);
+    CHECK_EQ(2.2, d.d);
+    CHECK_EQ(3.3, d.e);
+    CHECK_EQ(4.4, d.f);
+    CHECK_EQ(5.5, d.g);
+    CHECK_EQ(6.6, d.h);
+
+    CHECK_EQ(7.0, f.a);
+    CHECK_EQ(8.0, f.b);
+    CHECK_EQ(1.0, f.c);
+    CHECK_EQ(2.0, f.d);
+    CHECK_EQ(3.0, f.e);
+    CHECK_EQ(4.0, f.f);
+    CHECK_EQ(5.0, f.g);
+    CHECK_EQ(6.0, f.h);
+  }
+}
+
+
+TEST(10) {
+  // Test VFP multi load/store with db_w.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    double a;
+    double b;
+    double c;
+    double d;
+    double e;
+    double f;
+    double g;
+    double h;
+  } D;
+  D d;
+
+  typedef struct {
+    float a;
+    float b;
+    float c;
+    float d;
+    float e;
+    float f;
+    float g;
+    float h;
+  } F;
+  F f;
+
+  // Create a function that uses vldm/vstm to move some double and
+  // single precision values around in memory.
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  if (CpuFeatures::IsSupported(VFP2)) {
+    CpuFeatures::Scope scope(VFP2);
+
+    __ mov(ip, Operand(sp));
+    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
+    __ sub(fp, ip, Operand(4));
+
+    __ addi(r4, r0, Operand(OFFSET_OF(D, h) + 8));
+    __ vldm(db_w, r4, d4, d7);
+    __ vldm(db_w, r4, d0, d3);
+
+    __ addi(r4, r0, Operand(OFFSET_OF(D, h) + 8));
+    __ vstm(db_w, r4, d0, d5);
+    __ vstm(db_w, r4, d6, d7);
+
+    __ addi(r4, r1, Operand(OFFSET_OF(F, h) + 4));
+    __ vldm(db_w, r4, s4, s7);
+    __ vldm(db_w, r4, s0, s3);
+
+    __ addi(r4, r1, Operand(OFFSET_OF(F, h) + 4));
+    __ vstm(db_w, r4, s0, s5);
+    __ vstm(db_w, r4, s6, s7);
+
+    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Object* code = HEAP->CreateCode(
+        desc,
+        Code::ComputeFlags(Code::STUB),
+        Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+    CHECK(code->IsCode());
+#ifdef DEBUG
+    Code::cast(code)->Print();
+#endif
+    F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
+    d.a = 1.1;
+    d.b = 2.2;
+    d.c = 3.3;
+    d.d = 4.4;
+    d.e = 5.5;
+    d.f = 6.6;
+    d.g = 7.7;
+    d.h = 8.8;
+
+    f.a = 1.0;
+    f.b = 2.0;
+    f.c = 3.0;
+    f.d = 4.0;
+    f.e = 5.0;
+    f.f = 6.0;
+    f.g = 7.0;
+    f.h = 8.0;
+
+    Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
+    USE(dummy);
+
+    CHECK_EQ(7.7, d.a);
+    CHECK_EQ(8.8, d.b);
+    CHECK_EQ(1.1, d.c);
+    CHECK_EQ(2.2, d.d);
+    CHECK_EQ(3.3, d.e);
+    CHECK_EQ(4.4, d.f);
+    CHECK_EQ(5.5, d.g);
+    CHECK_EQ(6.6, d.h);
+
+    CHECK_EQ(7.0, f.a);
+    CHECK_EQ(8.0, f.b);
+    CHECK_EQ(1.0, f.c);
+    CHECK_EQ(2.0, f.d);
+    CHECK_EQ(3.0, f.e);
+    CHECK_EQ(4.0, f.f);
+    CHECK_EQ(5.0, f.g);
+    CHECK_EQ(6.0, f.h);
+  }
+}
+
+
+TEST(11) {
+  // Test instructions using the carry flag.
+  InitializeVM();
+  v8::HandleScope scope;
+
+  typedef struct {
+    int32_t a;
+    int32_t b;
+    int32_t c;
+    int32_t d;
+  } I;
+  I i;
+
+  i.a = 0xabcd0001;
+  i.b = 0xabcd0000;
+
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  // Test HeapObject untagging.
+  __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
+  __ mov(r1, Operand(r1, ASR, 1), SetCC);
+  __ adc(r1, r1, Operand(r1), LeaveCC, cs);
+  __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
+
+  __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
+  __ mov(r2, Operand(r2, ASR, 1), SetCC);
+  __ adc(r2, r2, Operand(r2), LeaveCC, cs);
+  __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
+
+  // Test corner cases.
+  __ mov(r1, Operand(0xffffffff));
+  __ mov(r2, Operand(0));
+  __ mov(r3, Operand(r1, ASR, 1), SetCC);  // Set the carry.
+  __ adc(r3, r1, Operand(r2));
+  __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
+
+  __ mov(r1, Operand(0xffffffff));
+  __ mov(r2, Operand(0));
+  __ mov(r3, Operand(r2, ASR, 1), SetCC);  // Unset the carry.
+  __ adc(r3, r1, Operand(r2));
+  __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
+
+  __ mov(pc, Operand(lr));
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+#ifdef DEBUG
+  Code::cast(code)->Print();
+#endif
+  F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
+  Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
+  USE(dummy);
+
+  CHECK_EQ(0xabcd0001, i.a);
+  CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
+  CHECK_EQ(0x00000000, i.c);
+  CHECK_EQ(0xffffffff, i.d);
+}
+
+
+TEST(12) {
+  // Test chaining of label usages within instructions (issue 1644).
+  InitializeVM();
+  v8::HandleScope scope;
+  Assembler assm(Isolate::Current(), NULL, 0);
+
+  Label target;
+  __ b(eq, &target);
+  __ b(ne, &target);
+  __ bind(&target);
+  __ nop();
+}
+#endif  // roohack
+
+#undef __
diff --git a/test/cctest/test-disasm-ppc.cc b/test/cctest/test-disasm-ppc.cc
new file mode 100644
index 0000000..62b488c
--- /dev/null
+++ b/test/cctest/test-disasm-ppc.cc
@@ -0,0 +1,765 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "debug.h"
+#include "disasm.h"
+#include "disassembler.h"
+#include "macro-assembler.h"
+#include "serialize.h"
+#include "cctest.h"
+
+// todo: fix references to these
+#define lr r14
+#define pc r15
+
+using namespace v8::internal;
+
+
+static v8::Persistent<v8::Context> env;
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
+bool DisassembleAndCompare(byte* pc, const char* compare_string) {
+  disasm::NameConverter converter;
+  disasm::Disassembler disasm(converter);
+  EmbeddedVector<char, 128> disasm_buffer;
+
+  disasm.InstructionDecode(disasm_buffer, pc);
+
+  if (strcmp(compare_string, disasm_buffer.start()) != 0) {
+    fprintf(stderr,
+            "expected: \n"
+            "%s\n"
+            "disassembled: \n"
+            "%s\n\n",
+            compare_string, disasm_buffer.start());
+    return false;
+  }
+  return true;
+}
+
+
+// Set up V8 to a state where we can at least run the assembler and
+// disassembler. Declare the variables and allocate the data structures used
+// in the rest of the macros.
+#define SET_UP()                                           \
+  InitializeVM();                                         \
+  v8::HandleScope scope;                                  \
+  byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \
+  Assembler assm(Isolate::Current(), buffer, 4*1024);     \
+  bool failure = false;
+
+
+// This macro assembles one instruction using the preallocated assembler and
+// disassembles the generated instruction, comparing the output to the expected
+// value. If the comparison fails an error message is printed, but the test
+// continues to run until the end.
+#define COMPARE(asm_, compare_string) \
+  { \
+    int pc_offset = assm.pc_offset(); \
+    byte *progcounter = &buffer[pc_offset]; \
+    assm.asm_; \
+    if (!DisassembleAndCompare(progcounter, compare_string)) failure = true; \
+  }
+
+// Force emission of any pending literals into a pool.
+#define EMIT_PENDING_LITERALS() \
+  assm.CheckConstPool(true, false)
+
+
+// Verify that all invocations of the COMPARE macro passed successfully.
+// Exit with a failure if at least one of the tests failed.
+#define VERIFY_RUN() \
+if (failure) { \
+    V8_Fatal(__FILE__, __LINE__, "ARM Disassembler tests failed.\n"); \
+  }
+
+#ifdef PENGUIN_CLEANUP
+TEST(Type0) {
+  SET_UP();
+
+  COMPARE(and_(r0, r1, r2),
+          "e0010002       and r0, r1, r2");
+  COMPARE(and_(r1, r2, r3, LeaveRC),
+          "e0021003       and r1, r2, r3");
+  COMPARE(and_(r2, r3, Operand(r4), SetCC),
+          "e0132004       ands r2, r3, r4");
+  COMPARE(and_(r3, r4, Operand(r5), LeaveCC, eq),
+          "00043005       andeq r3, r4, r5");
+
+  COMPARE(eor(r4, r5, Operand(r6, LSL, 0)),
+          "e0254006       eor r4, r5, r6");
+  COMPARE(eor(r4, r5, Operand(r7, LSL, 1), SetCC),
+          "e0354087       eors r4, r5, r7, lsl #1");
+  COMPARE(eor(r4, r5, Operand(r8, LSL, 2), LeaveCC, ne),
+          "10254108       eorne r4, r5, r8, lsl #2");
+  COMPARE(eor(r4, r5, Operand(r9, LSL, 3), SetCC, cs),
+          "20354189       eorcss r4, r5, r9, lsl #3");
+
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 31), LeaveCC, hs),
+          "20465f8a       subcs r5, r6, r10, lsl #31");
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 30), SetCC, cc),
+          "30565f0a       subccs r5, r6, r10, lsl #30");
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 24), LeaveCC, lo),
+          "30465c0a       subcc r5, r6, r10, lsl #24");
+  COMPARE(sub(r5, r6, Operand(r10, LSL, 16), SetCC, mi),
+          "4056580a       submis r5, r6, r10, lsl #16");
+
+  COMPARE(rsb(r6, r7, Operand(r11)),
+          "e067600b       rsb r6, r7, fp");
+  COMPARE(rsb(r6, r7, Operand(r11, LSR, 1)),
+          "e06760ab       rsb r6, r7, fp, lsr #1");
+  COMPARE(rsb(r6, r7, Operand(r11, LSR, 0), SetCC),
+          "e077602b       rsbs r6, r7, r11, lsr #32");
+  COMPARE(rsb(r6, r7, Operand(r11, LSR, 31), LeaveCC, pl),
+          "50676fab       rsbpl r6, r7, r11, lsr #31");
+
+  COMPARE(add(r7, r8, Operand(ip, ASR, 1)),
+          "e08870cc       add r7, r8, ip, asr #1");
+  COMPARE(add(r7, r8, Operand(ip, ASR, 0)),
+          "e088704c       add r7, r8, ip, asr #32");
+  COMPARE(add(r7, r8, Operand(ip), SetCC),
+          "e098700c       adds r7, r8, ip");
+  COMPARE(add(r7, r8, Operand(ip, ASR, 31), SetCC, vs),
+          "60987fcc       addvss r7, r8, ip, asr #31");
+
+  COMPARE(adc(r7, r11, Operand(ip, ASR, 5)),
+          "e0ab72cc       adc r7, r11, ip, asr #5");
+  COMPARE(adc(r4, ip, Operand(ip, ASR, 1), LeaveCC, vc),
+          "70ac40cc       adcvc r4, ip, ip, asr #1");
+  COMPARE(adc(r5, sp, Operand(ip), SetCC),
+          "e0bd500c       adcs r5, sp, ip");
+  COMPARE(adc(r8, lr, Operand(ip, ASR, 31), SetCC, vc),
+          "70be8fcc       adcvcs r8, lr, ip, asr #31");
+
+  COMPARE(sbc(r7, r1, Operand(ip, ROR, 1), LeaveCC, hi),
+          "80c170ec       sbchi r7, r1, ip, ror #1");
+  COMPARE(sbc(r7, r9, Operand(ip, ROR, 4)),
+          "e0c9726c       sbc r7, r9, ip, ror #4");
+  COMPARE(sbc(r7, r10, Operand(ip), SetCC),
+          "e0da700c       sbcs r7, r10, ip");
+  COMPARE(sbc(r7, ip, Operand(ip, ROR, 31), SetCC, hi),
+          "80dc7fec       sbchis r7, ip, ip, ror #31");
+
+  COMPARE(rsc(r7, r8, Operand(ip, LSL, r0)),
+          "e0e8701c       rsc r7, r8, ip, lsl r0");
+  COMPARE(rsc(r7, r8, Operand(ip, LSL, r1)),
+          "e0e8711c       rsc r7, r8, ip, lsl r1");
+  COMPARE(rsc(r7, r8, Operand(ip), SetCC),
+          "e0f8700c       rscs r7, r8, ip");
+  COMPARE(rsc(r7, r8, Operand(ip, LSL, r3), SetCC, ls),
+          "90f8731c       rsclss r7, r8, ip, lsl r3");
+
+  COMPARE(tst(r7, Operand(r5, ASR, ip), ge),
+          "a1170c55       tstge r7, r5, asr ip");
+  COMPARE(tst(r7, Operand(r6, ASR, sp)),
+          "e1170d56       tst r7, r6, asr sp");
+  COMPARE(tst(r7, Operand(r7), ge),
+          "a1170007       tstge r7, r7");
+  COMPARE(tst(r7, Operand(r8, ASR, r11), ge),
+          "a1170b58       tstge r7, r8, asr fp");
+
+  COMPARE(teq(r7, Operand(r5, ROR, r0), lt),
+          "b1370075       teqlt r7, r5, ror r0");
+  COMPARE(teq(r7, Operand(r6, ROR, lr)),
+          "e1370e76       teq r7, r6, ror lr");
+  COMPARE(teq(r7, Operand(r7), lt),
+          "b1370007       teqlt r7, r7");
+  COMPARE(teq(r7, Operand(r8, ROR, r1)),
+          "e1370178       teq r7, r8, ror r1");
+
+  COMPARE(cmp(r7, Operand(r4)),
+          "e1570004       cmp r7, r4");
+  COMPARE(cmp(r7, Operand(r6, LSL, 1), gt),
+          "c1570086       cmpgt r7, r6, lsl #1");
+  COMPARE(cmp(r7, Operand(r8, LSR, 3), gt),
+          "c15701a8       cmpgt r7, r8, lsr #3");
+  COMPARE(cmp(r7, Operand(r8, ASR, 19)),
+          "e15709c8       cmp r7, r8, asr #19");
+
+  COMPARE(cmn(r0, Operand(r4)),
+          "e1700004       cmn r0, r4");
+  COMPARE(cmn(r1, Operand(r6, ROR, 1)),
+          "e17100e6       cmn r1, r6, ror #1");
+  COMPARE(cmn(r2, Operand(r8)),
+          "e1720008       cmn r2, r8");
+  COMPARE(cmn(r3, Operand(r11), le),
+          "d173000b       cmnle r3, fp");
+
+  COMPARE(orr(r7, r8, Operand(lr), LeaveCC, al),
+          "e188700e       orr r7, r8, lr");
+  COMPARE(orr(r7, r8, Operand(r11)),
+          "e188700b       orr r7, r8, fp");
+  COMPARE(orr(r7, r8, Operand(sp), SetCC),
+          "e198700d       orrs r7, r8, sp");
+  COMPARE(orr(r7, r8, Operand(ip), SetCC, al),
+          "e198700c       orrs r7, r8, ip");
+
+  COMPARE(mov(r0, Operand(r1), LeaveCC, eq),
+          "01a00001       moveq r0, r1");
+  COMPARE(mov(r0, Operand(r2)),
+          "e1a00002       mov r0, r2");
+  COMPARE(mov(r0, Operand(r3), SetCC),
+          "e1b00003       movs r0, r3");
+  COMPARE(mov(r0, Operand(r4), SetCC, pl),
+          "51b00004       movpls r0, r4");
+
+  COMPARE(bic(r0, lr, Operand(r1), LeaveCC, vs),
+          "61ce0001       bicvs r0, lr, r1");
+  COMPARE(bic(r0, r9, Operand(r2), LeaveCC, vc),
+          "71c90002       bicvc r0, r9, r2");
+  COMPARE(bic(r0, r5, Operand(r3), SetCC),
+          "e1d50003       bics r0, r5, r3");
+  COMPARE(bic(r0, r1, Operand(r4), SetCC, pl),
+          "51d10004       bicpls r0, r1, r4");
+
+  COMPARE(mvn(r10, Operand(r1)),
+          "e1e0a001       mvn r10, r1");
+  COMPARE(mvn(r9, Operand(r2)),
+          "e1e09002       mvn r9, r2");
+  COMPARE(mvn(r0, Operand(r3), SetCC),
+          "e1f00003       mvns r0, r3");
+  COMPARE(mvn(r5, Operand(r4), SetCC, cc),
+          "31f05004       mvnccs r5, r4");
+
+  // Instructions autotransformed by the assembler.
+  // mov -> mvn.
+  COMPARE(mov(r3, Operand(-1), LeaveCC, al),
+          "e3e03000       mvn r3, #0");
+  COMPARE(mov(r4, Operand(-2), SetCC, al),
+          "e3f04001       mvns r4, #1");
+  COMPARE(mov(r5, Operand(0x0ffffff0), SetCC, ne),
+          "13f052ff       mvnnes r5, #-268435441");
+  COMPARE(mov(r6, Operand(-1), LeaveCC, ne),
+          "13e06000       mvnne r6, #0");
+
+  // mvn -> mov.
+  COMPARE(mvn(r3, Operand(-1), LeaveCC, al),
+          "e3a03000       mov r3, #0");
+  COMPARE(mvn(r4, Operand(-2), SetCC, al),
+          "e3b04001       movs r4, #1");
+  COMPARE(mvn(r5, Operand(0x0ffffff0), SetCC, ne),
+          "13b052ff       movnes r5, #-268435441");
+  COMPARE(mvn(r6, Operand(-1), LeaveCC, ne),
+          "13a06000       movne r6, #0");
+
+  // mov -> movw.
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    COMPARE(mov(r5, Operand(0x01234), LeaveCC, ne),
+            "13015234       movwne r5, #4660");
+    // We only disassemble one instruction so the eor instruction is not here.
+    COMPARE(eor(r5, r4, Operand(0x1234), LeaveCC, ne),
+            "1301c234       movwne ip, #4660");
+    // Movw can't do setcc so we don't get that here.  Mov immediate with setcc
+    // is pretty strange anyway.
+    COMPARE(mov(r5, Operand(0x01234), SetCC, ne),
+            "159fc000       ldrne ip, [pc, #+0]");
+    // Emit a literal pool now, otherwise this could be dumped later, in the
+    // middle of a different test.
+    EMIT_PENDING_LITERALS();
+
+    // We only disassemble one instruction so the eor instruction is not here.
+    // The eor does the setcc so we get a movw here.
+    COMPARE(eor(r5, r4, Operand(0x1234), SetCC, ne),
+            "1301c234       movwne ip, #4660");
+
+    COMPARE(movt(r5, 0x4321, ne),
+            "13445321       movtne r5, #17185");
+    COMPARE(movw(r5, 0xabcd, eq),
+            "030a5bcd       movweq r5, #43981");
+  }
+
+  // Eor doesn't have an eor-negative variant, but we can do an mvn followed by
+  // an eor to get the same effect.
+  COMPARE(eor(r5, r4, Operand(0xffffff34), SetCC, ne),
+          "13e0c0cb       mvnne ip, #203");
+
+  // and <-> bic.
+  COMPARE(andi(r3, r5, Operand(0xfc03ffff)),
+          "e3c537ff       bic r3, r5, #66846720");
+  COMPARE(bic(r3, r5, Operand(0xfc03ffff)),
+          "e20537ff       and r3, r5, #66846720");
+
+  // sub <-> add.
+  COMPARE(add(r3, r5, Operand(-1024)),
+          "e2453b01       sub r3, r5, #1024");
+  COMPARE(sub(r3, r5, Operand(-1024)),
+          "e2853b01       add r3, r5, #1024");
+
+  // cmp <-> cmn.
+  COMPARE(cmp(r3, Operand(-1024)),
+          "e3730b01       cmn r3, #1024");
+  COMPARE(cmn(r3, Operand(-1024)),
+          "e3530b01       cmp r3, #1024");
+
+  // Miscellaneous instructions encoded as type 0.
+  COMPARE(blx(ip),
+          "e12fff3c       blx ip");
+  COMPARE(bkpt(0),
+          "e1200070       bkpt 0");
+  COMPARE(bkpt(0xffff),
+          "e12fff7f       bkpt 65535");
+  COMPARE(clz(r6, r7),
+          "e16f6f17       clz r6, r7");
+
+  VERIFY_RUN();
+}
+
+
+TEST(Type1) {
+  SET_UP();
+
+  COMPARE(andi(r0, r1, Operand(0x00000000)),
+          "e2010000       andi r0, r1, #0");
+  COMPARE(andi(r1, r2, Operand(0x00000001), LeaveRC),
+          "e2021001       andi r1, r2, #1");
+  COMPARE(and_(r2, r3, Operand(0x00000010), SetCC),
+          "e2132010       ands r2, r3, #16");
+  COMPARE(and_(r3, r4, Operand(0x00000100), LeaveCC, eq),
+          "02043c01       andeq r3, r4, #256");
+  COMPARE(and_(r4, r5, Operand(0x00001000), SetCC, ne),
+          "12154a01       andnes r4, r5, #4096");
+
+  COMPARE(eor(r4, r5, Operand(0x00001000)),
+          "e2254a01       eor r4, r5, #4096");
+  COMPARE(eor(r4, r4, Operand(0x00010000), LeaveCC),
+          "e2244801       eor r4, r4, #65536");
+  COMPARE(eor(r4, r3, Operand(0x00100000), SetCC),
+          "e2334601       eors r4, r3, #1048576");
+  COMPARE(eor(r4, r2, Operand(0x01000000), LeaveCC, cs),
+          "22224401       eorcs r4, r2, #16777216");
+  COMPARE(eor(r4, r1, Operand(0x10000000), SetCC, cc),
+          "32314201       eorccs r4, r1, #268435456");
+
+  VERIFY_RUN();
+}
+#endif
+
+
+TEST(Type3) {
+  SET_UP();
+
+#ifdef PENGUIN_CLEANUP
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    COMPARE(ubfx(r0, r1, 5, 10),
+            "e7e902d1       ubfx r0, r1, #5, #10");
+    COMPARE(ubfx(r1, r0, 5, 10),
+            "e7e912d0       ubfx r1, r0, #5, #10");
+    COMPARE(ubfx(r0, r1, 31, 1),
+            "e7e00fd1       ubfx r0, r1, #31, #1");
+    COMPARE(ubfx(r1, r0, 31, 1),
+            "e7e01fd0       ubfx r1, r0, #31, #1");
+
+    COMPARE(sbfx(r0, r1, 5, 10),
+            "e7a902d1       sbfx r0, r1, #5, #10");
+    COMPARE(sbfx(r1, r0, 5, 10),
+            "e7a912d0       sbfx r1, r0, #5, #10");
+    COMPARE(sbfx(r0, r1, 31, 1),
+            "e7a00fd1       sbfx r0, r1, #31, #1");
+    COMPARE(sbfx(r1, r0, 31, 1),
+            "e7a01fd0       sbfx r1, r0, #31, #1");
+
+    COMPARE(bfc(r0, 5, 10),
+            "e7ce029f       bfc r0, #5, #10");
+    COMPARE(bfc(r1, 5, 10),
+            "e7ce129f       bfc r1, #5, #10");
+    COMPARE(bfc(r0, 31, 1),
+            "e7df0f9f       bfc r0, #31, #1");
+    COMPARE(bfc(r1, 31, 1),
+            "e7df1f9f       bfc r1, #31, #1");
+
+    COMPARE(bfi(r0, r1, 5, 10),
+            "e7ce0291       bfi r0, r1, #5, #10");
+    COMPARE(bfi(r1, r0, 5, 10),
+            "e7ce1290       bfi r1, r0, #5, #10");
+    COMPARE(bfi(r0, r1, 31, 1),
+            "e7df0f91       bfi r0, r1, #31, #1");
+    COMPARE(bfi(r1, r0, 31, 1),
+            "e7df1f90       bfi r1, r0, #31, #1");
+
+    COMPARE(usat(r0, 1, Operand(r1)),
+            "e6e10011       usat r0, #1, r1");
+    COMPARE(usat(r2, 7, Operand(lr)),
+            "e6e7201e       usat r2, #7, lr");
+    COMPARE(usat(r3, 31, Operand(r4, LSL, 31)),
+            "e6ff3f94       usat r3, #31, r4, lsl #31");
+    COMPARE(usat(r8, 0, Operand(r5, ASR, 17)),
+            "e6e088d5       usat r8, #0, r5, asr #17");
+  }
+#endif
+
+  VERIFY_RUN();
+}
+
+
+#ifdef PENGUIN_CLEANUP
+TEST(Vfp) {
+  SET_UP();
+
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+    COMPARE(vmov(d0, d1),
+            "eeb00b41       vmov.f64 d0, d1");
+    COMPARE(vmov(d3, d3, eq),
+            "0eb03b43       vmov.f64eq d3, d3");
+
+    COMPARE(vmov(s0, s31),
+            "eeb00a6f       vmov.f32 s0, s31");
+    COMPARE(vmov(s31, s0),
+            "eef0fa40       vmov.f32 s31, s0");
+    COMPARE(vmov(r0, s0),
+            "ee100a10       vmov r0, s0");
+    COMPARE(vmov(r10, s31),
+            "ee1faa90       vmov r10, s31");
+    COMPARE(vmov(s0, r0),
+            "ee000a10       vmov s0, r0");
+    COMPARE(vmov(s31, r10),
+            "ee0faa90       vmov s31, r10");
+
+    COMPARE(vabs(d0, d1),
+            "eeb00bc1       vabs.f64 d0, d1");
+    COMPARE(vabs(d3, d4, mi),
+            "4eb03bc4       vabs.f64mi d3, d4");
+
+    COMPARE(vneg(d0, d1),
+            "eeb10b41       vneg.f64 d0, d1");
+    COMPARE(vneg(d3, d4, mi),
+            "4eb13b44       vneg.f64mi d3, d4");
+
+    COMPARE(vadd(d0, d1, d2),
+            "ee310b02       vadd.f64 d0, d1, d2");
+    COMPARE(vadd(d3, d4, d5, mi),
+            "4e343b05       vadd.f64mi d3, d4, d5");
+
+    COMPARE(vsub(d0, d1, d2),
+            "ee310b42       vsub.f64 d0, d1, d2");
+    COMPARE(vsub(d3, d4, d5, ne),
+            "1e343b45       vsub.f64ne d3, d4, d5");
+
+    COMPARE(vmul(d2, d1, d0),
+            "ee212b00       vmul.f64 d2, d1, d0");
+    COMPARE(vmul(d6, d4, d5, cc),
+            "3e246b05       vmul.f64cc d6, d4, d5");
+
+    COMPARE(vdiv(d2, d2, d2),
+            "ee822b02       vdiv.f64 d2, d2, d2");
+    COMPARE(vdiv(d6, d7, d7, hi),
+            "8e876b07       vdiv.f64hi d6, d7, d7");
+
+    COMPARE(vsqrt(d0, d0),
+            "eeb10bc0       vsqrt.f64 d0, d0");
+    COMPARE(vsqrt(d2, d3, ne),
+            "1eb12bc3       vsqrt.f64ne d2, d3");
+
+    COMPARE(vmov(d0, 1.0),
+            "eeb70b00       vmov.f64 d0, #1");
+    COMPARE(vmov(d2, -13.0),
+            "eeba2b0a       vmov.f64 d2, #-13");
+
+    COMPARE(vldr(s0, r0, 0),
+            "ed900a00       vldr s0, [r0 + 4*0]");
+    COMPARE(vldr(s1, r1, 4),
+            "edd10a01       vldr s1, [r1 + 4*1]");
+    COMPARE(vldr(s15, r4, 16),
+            "edd47a04       vldr s15, [r4 + 4*4]");
+    COMPARE(vldr(s16, r5, 20),
+            "ed958a05       vldr s16, [r5 + 4*5]");
+    COMPARE(vldr(s31, r10, 1020),
+            "eddafaff       vldr s31, [r10 + 4*255]");
+
+    COMPARE(vstr(s0, r0, 0),
+            "ed800a00       vstr s0, [r0 + 4*0]");
+    COMPARE(vstr(s1, r1, 4),
+            "edc10a01       vstr s1, [r1 + 4*1]");
+    COMPARE(vstr(s15, r8, 8),
+            "edc87a02       vstr s15, [r8 + 4*2]");
+    COMPARE(vstr(s16, r9, 12),
+            "ed898a03       vstr s16, [r9 + 4*3]");
+    COMPARE(vstr(s31, r10, 1020),
+            "edcafaff       vstr s31, [r10 + 4*255]");
+
+    COMPARE(vldr(d0, r0, 0),
+            "ed900b00       vldr d0, [r0 + 4*0]");
+    COMPARE(vldr(d1, r1, 4),
+            "ed911b01       vldr d1, [r1 + 4*1]");
+    COMPARE(vldr(d15, r10, 1020),
+            "ed9afbff       vldr d15, [r10 + 4*255]");
+    COMPARE(vstr(d0, r0, 0),
+            "ed800b00       vstr d0, [r0 + 4*0]");
+    COMPARE(vstr(d1, r1, 4),
+            "ed811b01       vstr d1, [r1 + 4*1]");
+    COMPARE(vstr(d15, r10, 1020),
+            "ed8afbff       vstr d15, [r10 + 4*255]");
+
+    COMPARE(vmsr(r5),
+            "eee15a10       vmsr FPSCR, r5");
+    COMPARE(vmsr(r10, pl),
+            "5ee1aa10       vmsrpl FPSCR, r10");
+    COMPARE(vmsr(pc),
+            "eee1fa10       vmsr FPSCR, APSR");
+    COMPARE(vmrs(r5),
+            "eef15a10       vmrs r5, FPSCR");
+    COMPARE(vmrs(r10, ge),
+            "aef1aa10       vmrsge r10, FPSCR");
+    COMPARE(vmrs(pc),
+            "eef1fa10       vmrs APSR, FPSCR");
+
+    COMPARE(vstm(ia, r0, d1, d3),
+            "ec801b06       vstmia r0, {d1-d3}");
+    COMPARE(vldm(ia, r1, d2, d5),
+            "ec912b08       vldmia r1, {d2-d5}");
+    COMPARE(vstm(ia, r2, d0, d15),
+            "ec820b20       vstmia r2, {d0-d15}");
+    COMPARE(vldm(ia, r3, d0, d15),
+            "ec930b20       vldmia r3, {d0-d15}");
+    COMPARE(vstm(ia, r4, s1, s3),
+            "ecc40a03       vstmia r4, {s1-s3}");
+    COMPARE(vldm(ia, r5, s2, s5),
+            "ec951a04       vldmia r5, {s2-s5}");
+    COMPARE(vstm(ia, r6, s0, s31),
+            "ec860a20       vstmia r6, {s0-s31}");
+    COMPARE(vldm(ia, r7, s0, s31),
+            "ec970a20       vldmia r7, {s0-s31}");
+  }
+
+  VERIFY_RUN();
+}
+#endif
+
+#ifdef PENGUIN_CLEANUP
+TEST(LoadStore) {
+  SET_UP();
+
+  COMPARE(ldrb(r0, MemOperand(r1)),
+          "e5d10000       ldrb r0, [r1, #+0]");
+  COMPARE(ldrb(r2, MemOperand(r3, 42)),
+          "e5d3202a       ldrb r2, [r3, #+42]");
+  COMPARE(ldrb(r4, MemOperand(r5, -42)),
+          "e555402a       ldrb r4, [r5, #-42]");
+  COMPARE(ldrb(r6, MemOperand(r7, 42, PostIndex)),
+          "e4d7602a       ldrb r6, [r7], #+42");
+  COMPARE(ldrb(r8, MemOperand(r9, -42, PostIndex)),
+          "e459802a       ldrb r8, [r9], #-42");
+  COMPARE(ldrb(r10, MemOperand(r11, 42, PreIndex)),
+          "e5fba02a       ldrb r10, [fp, #+42]!");
+  COMPARE(ldrb(ip, MemOperand(sp, -42, PreIndex)),
+          "e57dc02a       ldrb ip, [sp, #-42]!");
+  COMPARE(ldrb(r0, MemOperand(r1, r2)),
+          "e7d10002       ldrb r0, [r1, +r2]");
+  COMPARE(ldrb(r0, MemOperand(r1, r2, NegOffset)),
+          "e7510002       ldrb r0, [r1, -r2]");
+  COMPARE(ldrb(r0, MemOperand(r1, r2, PostIndex)),
+          "e6d10002       ldrb r0, [r1], +r2");
+  COMPARE(ldrb(r0, MemOperand(r1, r2, NegPostIndex)),
+          "e6510002       ldrb r0, [r1], -r2");
+  COMPARE(ldrb(r0, MemOperand(r1, r2, PreIndex)),
+          "e7f10002       ldrb r0, [r1, +r2]!");
+  COMPARE(ldrb(r0, MemOperand(r1, r2, NegPreIndex)),
+          "e7710002       ldrb r0, [r1, -r2]!");
+
+  COMPARE(strb(r0, MemOperand(r1)),
+          "e5c10000       strb r0, [r1, #+0]");
+  COMPARE(strb(r2, MemOperand(r3, 42)),
+          "e5c3202a       strb r2, [r3, #+42]");
+  COMPARE(strb(r4, MemOperand(r5, -42)),
+          "e545402a       strb r4, [r5, #-42]");
+  COMPARE(strb(r6, MemOperand(r7, 42, PostIndex)),
+          "e4c7602a       strb r6, [r7], #+42");
+  COMPARE(strb(r8, MemOperand(r9, -42, PostIndex)),
+          "e449802a       strb r8, [r9], #-42");
+  COMPARE(strb(r10, MemOperand(r11, 42, PreIndex)),
+          "e5eba02a       strb r10, [fp, #+42]!");
+  COMPARE(strb(ip, MemOperand(sp, -42, PreIndex)),
+          "e56dc02a       strb ip, [sp, #-42]!");
+  COMPARE(strb(r0, MemOperand(r1, r2)),
+          "e7c10002       strb r0, [r1, +r2]");
+  COMPARE(strb(r0, MemOperand(r1, r2, NegOffset)),
+          "e7410002       strb r0, [r1, -r2]");
+  COMPARE(strb(r0, MemOperand(r1, r2, PostIndex)),
+          "e6c10002       strb r0, [r1], +r2");
+  COMPARE(strb(r0, MemOperand(r1, r2, NegPostIndex)),
+          "e6410002       strb r0, [r1], -r2");
+  COMPARE(strb(r0, MemOperand(r1, r2, PreIndex)),
+          "e7e10002       strb r0, [r1, +r2]!");
+  COMPARE(strb(r0, MemOperand(r1, r2, NegPreIndex)),
+          "e7610002       strb r0, [r1, -r2]!");
+
+  COMPARE(ldrh(r0, MemOperand(r1)),
+          "e1d100b0       ldrh r0, [r1, #+0]");
+  COMPARE(ldrh(r2, MemOperand(r3, 42)),
+          "e1d322ba       ldrh r2, [r3, #+42]");
+  COMPARE(ldrh(r4, MemOperand(r5, -42)),
+          "e15542ba       ldrh r4, [r5, #-42]");
+  COMPARE(ldrh(r6, MemOperand(r7, 42, PostIndex)),
+          "e0d762ba       ldrh r6, [r7], #+42");
+  COMPARE(ldrh(r8, MemOperand(r9, -42, PostIndex)),
+          "e05982ba       ldrh r8, [r9], #-42");
+//  COMPARE(ldrh(r10, MemOperand(fp, 42, PreIndex)),
+//          "e1fba2ba       ldrh r10, [fp, #+42]!");
+  COMPARE(ldrh(ip, MemOperand(sp, -42, PreIndex)),
+          "e17dc2ba       ldrh ip, [sp, #-42]!");
+  COMPARE(ldrh(r0, MemOperand(r1, r2)),
+          "e19100b2       ldrh r0, [r1, +r2]");
+  COMPARE(ldrh(r0, MemOperand(r1, r2, NegOffset)),
+          "e11100b2       ldrh r0, [r1, -r2]");
+  COMPARE(ldrh(r0, MemOperand(r1, r2, PostIndex)),
+          "e09100b2       ldrh r0, [r1], +r2");
+  COMPARE(ldrh(r0, MemOperand(r1, r2, NegPostIndex)),
+          "e01100b2       ldrh r0, [r1], -r2");
+  COMPARE(ldrh(r0, MemOperand(r1, r2, PreIndex)),
+          "e1b100b2       ldrh r0, [r1, +r2]!");
+  COMPARE(ldrh(r0, MemOperand(r1, r2, NegPreIndex)),
+          "e13100b2       ldrh r0, [r1, -r2]!");
+
+  COMPARE(strh(r0, MemOperand(r1)),
+          "e1c100b0       strh r0, [r1, #+0]");
+  COMPARE(strh(r2, MemOperand(r3, 42)),
+          "e1c322ba       strh r2, [r3, #+42]");
+  COMPARE(strh(r4, MemOperand(r5, -42)),
+          "e14542ba       strh r4, [r5, #-42]");
+  COMPARE(strh(r6, MemOperand(r7, 42, PostIndex)),
+          "e0c762ba       strh r6, [r7], #+42");
+  COMPARE(strh(r8, MemOperand(r9, -42, PostIndex)),
+          "e04982ba       strh r8, [r9], #-42");
+//  COMPARE(strh(r10, MemOperand(fp, 42, PreIndex)),
+//          "e1eba2ba       strh r10, [fp, #+42]!");
+  COMPARE(strh(ip, MemOperand(sp, -42, PreIndex)),
+          "e16dc2ba       strh ip, [sp, #-42]!");
+  COMPARE(strh(r0, MemOperand(r1, r2)),
+          "e18100b2       strh r0, [r1, +r2]");
+  COMPARE(strh(r0, MemOperand(r1, r2, NegOffset)),
+          "e10100b2       strh r0, [r1, -r2]");
+  COMPARE(strh(r0, MemOperand(r1, r2, PostIndex)),
+          "e08100b2       strh r0, [r1], +r2");
+  COMPARE(strh(r0, MemOperand(r1, r2, NegPostIndex)),
+          "e00100b2       strh r0, [r1], -r2");
+  COMPARE(strh(r0, MemOperand(r1, r2, PreIndex)),
+          "e1a100b2       strh r0, [r1, +r2]!");
+  COMPARE(strh(r0, MemOperand(r1, r2, NegPreIndex)),
+          "e12100b2       strh r0, [r1, -r2]!");
+
+  COMPARE(ldr(r0, MemOperand(r1)),
+          "e5910000       ldr r0, [r1, #+0]");
+  COMPARE(ldr(r2, MemOperand(r3, 42)),
+          "e593202a       ldr r2, [r3, #+42]");
+  COMPARE(ldr(r4, MemOperand(r5, -42)),
+          "e515402a       ldr r4, [r5, #-42]");
+  COMPARE(ldr(r6, MemOperand(r7, 42, PostIndex)),
+          "e497602a       ldr r6, [r7], #+42");
+  COMPARE(ldr(r8, MemOperand(r9, -42, PostIndex)),
+          "e419802a       ldr r8, [r9], #-42");
+//  COMPARE(ldr(r10, MemOperand(fp, 42, PreIndex)),
+//          "e5bba02a       ldr r10, [fp, #+42]!");
+  COMPARE(ldr(ip, MemOperand(sp, -42, PreIndex)),
+          "e53dc02a       ldr ip, [sp, #-42]!");
+  COMPARE(ldr(r0, MemOperand(r1, r2)),
+          "e7910002       ldr r0, [r1, +r2]");
+  COMPARE(ldr(r0, MemOperand(r1, r2, NegOffset)),
+          "e7110002       ldr r0, [r1, -r2]");
+  COMPARE(ldr(r0, MemOperand(r1, r2, PostIndex)),
+          "e6910002       ldr r0, [r1], +r2");
+  COMPARE(ldr(r0, MemOperand(r1, r2, NegPostIndex)),
+          "e6110002       ldr r0, [r1], -r2");
+  COMPARE(ldr(r0, MemOperand(r1, r2, PreIndex)),
+          "e7b10002       ldr r0, [r1, +r2]!");
+  COMPARE(ldr(r0, MemOperand(r1, r2, NegPreIndex)),
+          "e7310002       ldr r0, [r1, -r2]!");
+
+  COMPARE(str(r0, MemOperand(r1)),
+          "e5810000       str r0, [r1, #+0]");
+  COMPARE(str(r2, MemOperand(r3, 42)),
+          "e583202a       str r2, [r3, #+42]");
+  COMPARE(str(r4, MemOperand(r5, -42)),
+          "e505402a       str r4, [r5, #-42]");
+  COMPARE(str(r6, MemOperand(r7, 42, PostIndex)),
+          "e487602a       str r6, [r7], #+42");
+  COMPARE(str(r8, MemOperand(r9, -42, PostIndex)),
+          "e409802a       str r8, [r9], #-42");
+//  COMPARE(str(r10, MemOperand(fp, 42, PreIndex)),
+//          "e5aba02a       str r10, [fp, #+42]!");
+  COMPARE(str(ip, MemOperand(sp, -42, PreIndex)),
+          "e52dc02a       str ip, [sp, #-42]!");
+  COMPARE(str(r0, MemOperand(r1, r2)),
+          "e7810002       str r0, [r1, +r2]");
+  COMPARE(str(r0, MemOperand(r1, r2, NegOffset)),
+          "e7010002       str r0, [r1, -r2]");
+  COMPARE(str(r0, MemOperand(r1, r2, PostIndex)),
+          "e6810002       str r0, [r1], +r2");
+  COMPARE(str(r0, MemOperand(r1, r2, NegPostIndex)),
+          "e6010002       str r0, [r1], -r2");
+  COMPARE(str(r0, MemOperand(r1, r2, PreIndex)),
+          "e7a10002       str r0, [r1, +r2]!");
+  COMPARE(str(r0, MemOperand(r1, r2, NegPreIndex)),
+          "e7210002       str r0, [r1, -r2]!");
+
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatures::Scope scope(ARMv7);
+    COMPARE(ldrd(r0, r1, MemOperand(r1)),
+            "e1c100d0       ldrd r0, [r1, #+0]");
+    COMPARE(ldrd(r2, r3, MemOperand(r3, 127)),
+            "e1c327df       ldrd r2, [r3, #+127]");
+    COMPARE(ldrd(r4, r5, MemOperand(r5, -127)),
+            "e14547df       ldrd r4, [r5, #-127]");
+    COMPARE(ldrd(r6, r7, MemOperand(r7, 127, PostIndex)),
+            "e0c767df       ldrd r6, [r7], #+127");
+    COMPARE(ldrd(r8, r9, MemOperand(r9, -127, PostIndex)),
+            "e04987df       ldrd r8, [r9], #-127");
+//    COMPARE(ldrd(r10, fp, MemOperand(fp, 127, PreIndex)),
+//            "e1eba7df       ldrd r10, [fp, #+127]!");
+    COMPARE(ldrd(ip, sp, MemOperand(sp, -127, PreIndex)),
+            "e16dc7df       ldrd ip, [sp, #-127]!");
+
+    COMPARE(strd(r0, r1, MemOperand(r1)),
+            "e1c100f0       strd r0, [r1, #+0]");
+    COMPARE(strd(r2, r3, MemOperand(r3, 127)),
+            "e1c327ff       strd r2, [r3, #+127]");
+    COMPARE(strd(r4, r5, MemOperand(r5, -127)),
+            "e14547ff       strd r4, [r5, #-127]");
+    COMPARE(strd(r6, r7, MemOperand(r7, 127, PostIndex)),
+            "e0c767ff       strd r6, [r7], #+127");
+    COMPARE(strd(r8, r9, MemOperand(r9, -127, PostIndex)),
+            "e04987ff       strd r8, [r9], #-127");
+//    COMPARE(strd(r10, fp, MemOperand(fp, 127, PreIndex)),
+//            "e1eba7ff       strd r10, [fp, #+127]!");
+    COMPARE(strd(ip, sp, MemOperand(sp, -127, PreIndex)),
+            "e16dc7ff       strd ip, [sp, #-127]!");
+  }
+
+  VERIFY_RUN();
+}
+#endif
+
diff --git a/test/cctest/test-hashing.cc b/test/cctest/test-hashing.cc
index a626510..716d334 100644
--- a/test/cctest/test-hashing.cc
+++ b/test/cctest/test-hashing.cc
@@ -113,6 +113,24 @@ void generate(MacroAssembler* masm, i::Vector<const char> string) {
   __ pop(kRootRegister);
   __ jr(ra);
   __ nop();
+#elif V8_TARGET_ARCH_PPC
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+
+  __ push(kRootRegister);
+  __ InitializeRootRegister();
+
+  __ li(r3, Operand::Zero());
+  __ li(ip, Operand(string.at(0)));
+  StringHelper::GenerateHashInit(masm, r3, ip, r0);
+  for (int i = 1; i < string.length(); i++) {
+    __ li(ip, Operand(string.at(i)));
+    StringHelper::GenerateHashAddCharacter(masm, r3, ip, r0);
+  }
+  StringHelper::GenerateHashGetHash(masm, r3, r0);
+  __ pop(kRootRegister);
+  __ blr();
 #endif
 }
 
@@ -148,6 +166,16 @@ void generate(MacroAssembler* masm, uint32_t key) {
   __ pop(kRootRegister);
   __ jr(ra);
   __ nop();
+#elif V8_TARGET_ARCH_PPC
+#if ABI_USES_FUNCTION_DESCRIPTORS
+  __ function_descriptor();
+#endif
+  __ push(kRootRegister);
+  __ InitializeRootRegister();
+  __ li(r3, Operand(key));
+  __ GetNumberHash(r3, ip);
+  __ pop(kRootRegister);
+  __ blr();
 #endif
 }
 
@@ -172,7 +200,7 @@ void check(i::Vector<const char> string) {
   v8_string->set_hash_field(String::kEmptyHashField);
 #ifdef USE_SIMULATOR
   uint32_t codegen_hash =
-      reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
+      reinterpret_cast<uintptr_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
 #else
   uint32_t codegen_hash = hash();
 #endif
@@ -199,7 +227,7 @@ void check(uint32_t key) {
   HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
 #ifdef USE_SIMULATOR
   uint32_t codegen_hash =
-      reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
+      reinterpret_cast<uintptr_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
 #else
   uint32_t codegen_hash = hash();
 #endif
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 6927c43..e075e2a 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -133,7 +133,7 @@ TEST(HeapObjects) {
   CHECK(value->IsNumber());
   CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
 
-#ifndef V8_TARGET_ARCH_X64
+#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_PPC64)
   // TODO(lrn): We need a NumberFromIntptr function in order to test this.
   value = HEAP->NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
   CHECK(value->IsHeapNumber());
diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc
index 5035f87..0bc2e70 100644
--- a/test/cctest/test-lockers.cc
+++ b/test/cctest/test-lockers.cc
@@ -204,7 +204,7 @@ static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) {
 
 // Run many threads all locking on the same isolate
 TEST(IsolateLockingStress) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 50;
 #else
   const int kNThreads = 100;
@@ -241,7 +241,8 @@ class IsolateNonlockingThread : public JoinableThread {
 
 // Run many threads each accessing its own isolate without locking
 TEST(MultithreadedParallelIsolates) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) \
+  || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 10;
 #else
   const int kNThreads = 50;
@@ -279,7 +280,7 @@ class IsolateNestedLockingThread : public JoinableThread {
 
 // Run  many threads with nested locks
 TEST(IsolateNestedLocking) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 50;
 #else
   const int kNThreads = 100;
@@ -319,7 +320,8 @@ class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread {
 
 // Run parallel threads that lock and access different isolates in parallel
 TEST(SeparateIsolatesLocksNonexclusive) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) \
+  || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 50;
 #else
   const int kNThreads = 100;
@@ -393,7 +395,8 @@ class LockerUnlockerThread : public JoinableThread {
 
 // Use unlocker inside of a Locker, multiple threads.
 TEST(LockerUnlocker) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) \
+  || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 50;
 #else
   const int kNThreads = 100;
@@ -446,7 +449,8 @@ class LockTwiceAndUnlockThread : public JoinableThread {
 
 // Use Unlocker inside two Lockers.
 TEST(LockTwiceAndUnlock) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) \
+  || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 50;
 #else
   const int kNThreads = 100;
@@ -567,7 +571,7 @@ class LockUnlockLockThread : public JoinableThread {
 
 // Locker inside an Unlocker inside a Locker.
 TEST(LockUnlockLockMultithreaded) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 50;
 #else
   const int kNThreads = 100;
@@ -618,7 +622,7 @@ class LockUnlockLockDefaultIsolateThread : public JoinableThread {
 
 // Locker inside an Unlocker inside a Locker for default isolate.
 TEST(LockUnlockLockDefaultIsolateMultithreaded) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 50;
 #else
   const int kNThreads = 100;
@@ -690,7 +694,8 @@ class IsolateGenesisThread : public JoinableThread {
 // Test installing extensions in separate isolates concurrently.
 // http://code.google.com/p/v8/issues/detail?id=1821
 TEST(ExtensionsRegistration) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) \
+  || defined(V8_TARGET_ARCH_PPC)
   const int kNThreads = 10;
 #else
   const int kNThreads = 40;
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index c0ab763..0e8a3a4 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -525,6 +525,18 @@ static intptr_t MemoryInUse() {
   return memory_use;
 }
 
+#if defined(V8_TARGET_ARCH_PPC)
+const intptr_t maxSnap64 = 3600;  // ???
+const intptr_t max64     = 4000;  // ???
+const intptr_t maxSnap32 = 2800;  // 2624
+const intptr_t max32     = 3300;  // 3136
+#else
+const intptr_t maxSnap64 = 3600;  // 3396
+const intptr_t max64     = 4000;  // 3948
+const intptr_t maxSnap32 = 2500;  // 2400
+const intptr_t max32     = 2860;  // 2760
+#endif
+
 
 TEST(BootUpMemoryUse) {
   intptr_t initial_memory = MemoryInUse();
@@ -539,15 +551,15 @@ TEST(BootUpMemoryUse) {
     intptr_t delta = MemoryInUse() - initial_memory;
     if (sizeof(initial_memory) == 8) {
       if (v8::internal::Snapshot::IsEnabled()) {
-        CHECK_LE(delta, 3600 * 1024);  // 3396.
+        CHECK_LE(delta, maxSnap64 * 1024);
       } else {
-        CHECK_LE(delta, 4000 * 1024);  // 3948.
+        CHECK_LE(delta, max64 * 1024);
       }
     } else {
       if (v8::internal::Snapshot::IsEnabled()) {
-        CHECK_LE(delta, 2500 * 1024);  // 2400.
+        CHECK_LE(delta, maxSnap32 * 1024);
       } else {
-        CHECK_LE(delta, 2860 * 1024);  // 2760.
+        CHECK_LE(delta, max32 * 1024);
       }
     }
   }
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index e433b92..71b82b3 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -49,6 +49,11 @@
 #include "arm/macro-assembler-arm.h"
 #include "arm/regexp-macro-assembler-arm.h"
 #endif
+#ifdef V8_TARGET_ARCH_PPC
+#include "ppc/assembler-ppc.h"
+#include "ppc/macro-assembler-ppc.h"
+#include "ppc/regexp-macro-assembler-ppc.h"
+#endif
 #ifdef V8_TARGET_ARCH_MIPS
 #include "mips/assembler-mips.h"
 #include "mips/macro-assembler-mips.h"
@@ -702,6 +707,8 @@ typedef RegExpMacroAssemblerIA32 ArchRegExpMacroAssembler;
 typedef RegExpMacroAssemblerX64 ArchRegExpMacroAssembler;
 #elif V8_TARGET_ARCH_ARM
 typedef RegExpMacroAssemblerARM ArchRegExpMacroAssembler;
+#elif V8_TARGET_ARCH_PPC
+typedef RegExpMacroAssemblerPPC ArchRegExpMacroAssembler;
 #elif V8_TARGET_ARCH_MIPS
 typedef RegExpMacroAssemblerMIPS ArchRegExpMacroAssembler;
 #endif
diff --git a/test/cctest/test-threads.cc b/test/cctest/test-threads.cc
index 713d1e8..c4a6861 100644
--- a/test/cctest/test-threads.cc
+++ b/test/cctest/test-threads.cc
@@ -170,7 +170,11 @@ class ThreadIdValidationThread : public v8::internal::Thread {
 };
 
 TEST(ThreadIdValidation) {
+#ifdef V8_TARGET_ARCH_PPC
+  const int kNThreads = 50;
+#else
   const int kNThreads = 100;
+#endif
   i::List<ThreadIdValidationThread*> threads(kNThreads);
   i::List<i::ThreadId> refs(kNThreads);
   i::Semaphore* semaphore = i::OS::CreateSemaphore(0);
diff --git a/test/mjsunit/big-array-literal.js b/test/mjsunit/big-array-literal.js
index 8e0ff87..0fcc52c 100644
--- a/test/mjsunit/big-array-literal.js
+++ b/test/mjsunit/big-array-literal.js
@@ -26,7 +26,8 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // On MacOS, this test needs a stack size of at least 538 kBytes.
-// Flags: --stack-size=600
+// On PPC64, this test needs a stack size of at least 698 kBytes.
+// Flags: --stack-size=700
 
 // Test that we can make large object literals that work.
 // Also test that we can attempt to make even larger object literals without
diff --git a/test/mjsunit/d8-os.js b/test/mjsunit/d8-os.js
index f6b9839..29d3103 100644
--- a/test/mjsunit/d8-os.js
+++ b/test/mjsunit/d8-os.js
@@ -135,7 +135,7 @@ if (this.os && os.system) {
       assertThrows("os.system('sleep', ['2000'], -1, 20);", "sleep 2");
 
       // Check that -1 means no timeout.
-      os.system('sleep', ['0.1'], -1, -1);
+      os.system('sleep', ['1'], -1, -1);
 
     }
 
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 037093b..8020d27 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -179,3 +179,11 @@ debug-liveedit-stack-padding: SKIP
 debug-liveedit-restart-frame: SKIP
 debug-liveedit-double-call: SKIP
 
+##############################################################################
+[ $arch == ppc || $arch == ppc64 ]
+
+# Stack manipulations in LiveEdit is not implemented for this arch.
+debug-liveedit-check-stack: SKIP
+debug-liveedit-stack-padding: SKIP
+debug-liveedit-restart-frame: SKIP
+debug-liveedit-double-call: SKIP
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 7a54ef4..4e398f2 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -533,6 +533,40 @@
                 '../../src/arm/stub-cache-arm.cc',
               ],
             }],
+            ['v8_target_arch=="ppc" or v8_target_arch=="ppc64"', {
+              'sources': [
+                '../../src/ppc/assembler-ppc-inl.h',
+                '../../src/ppc/assembler-ppc.cc',
+                '../../src/ppc/assembler-ppc.h',
+                '../../src/ppc/builtins-ppc.cc',
+                '../../src/ppc/code-stubs-ppc.cc',
+                '../../src/ppc/code-stubs-ppc.h',
+                '../../src/ppc/codegen-ppc.cc',
+                '../../src/ppc/codegen-ppc.h',
+                '../../src/ppc/constants-ppc.h',
+                '../../src/ppc/constants-ppc.cc',
+                '../../src/ppc/cpu-ppc.cc',
+                '../../src/ppc/debug-ppc.cc',
+                '../../src/ppc/deoptimizer-ppc.cc',
+                '../../src/ppc/disasm-ppc.cc',
+                '../../src/ppc/frames-ppc.cc',
+                '../../src/ppc/frames-ppc.h',
+                '../../src/ppc/full-codegen-ppc.cc',
+                '../../src/ppc/ic-ppc.cc',
+                '../../src/ppc/lithium-ppc.cc',
+                '../../src/ppc/lithium-ppc.h',
+                '../../src/ppc/lithium-codegen-ppc.cc',
+                '../../src/ppc/lithium-codegen-ppc.h',
+                '../../src/ppc/lithium-gap-resolver-ppc.cc',
+                '../../src/ppc/lithium-gap-resolver-ppc.h',
+                '../../src/ppc/macro-assembler-ppc.cc',
+                '../../src/ppc/macro-assembler-ppc.h',
+                '../../src/ppc/regexp-macro-assembler-ppc.cc',
+                '../../src/ppc/regexp-macro-assembler-ppc.h',
+                '../../src/ppc/simulator-ppc.cc',
+                '../../src/ppc/stub-cache-ppc.cc',
+              ],
+            }],
             ['v8_target_arch=="ia32" or v8_target_arch=="mac" or OS=="mac"', {
               'sources': [
                 '../../src/ia32/assembler-ia32-inl.h',
@@ -706,6 +740,13 @@
                 ],
               }
             ],
+            ['OS=="aix"', {
+                'sources': [
+                  '../../src/platform-aix.cc',
+                  '../../src/platform-posix.cc',
+                ],
+              }
+            ],
             ['OS=="solaris"', {
                 'link_settings': {
                   'libraries': [
diff --git a/tools/run-tests.py b/tools/run-tests.py
index a1de3dc..b37f938 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -64,6 +64,8 @@ SUPPORTED_ARCHS = ["android_arm",
                    "android_ia32",
                    "arm",
                    "ia32",
+                   "ppc",
+                   "ppc64",
                    "mipsel",
                    "x64"]
 
diff --git a/tools/test-wrapper-gypbuild.py b/tools/test-wrapper-gypbuild.py
index 4dd6338..e83878e 100755
--- a/tools/test-wrapper-gypbuild.py
+++ b/tools/test-wrapper-gypbuild.py
@@ -66,7 +66,7 @@ def BuildOptions():
                     default='release,debug')
   result.add_option("--arch",
                     help='The architectures to run tests for (comma-separated)',
-                    default='ia32,x64,arm')
+                    default='ia32,x64,arm,ppc')
 
   # Flags that are passed on to the wrapped test.py script:
   result.add_option("-v", "--verbose", help="Verbose output",
@@ -151,7 +151,7 @@ def ProcessOptions(options):
       print "Unknown mode %s" % mode
       return False
   for arch in options.arch:
-    if not arch in ['ia32', 'x64', 'arm', 'mipsel', 'android_arm',
+    if not arch in ['ia32', 'x64', 'arm', 'ppc', 'mipsel', 'android_arm',
                     'android_ia32']:
       print "Unknown architecture %s" % arch
       return False
diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py
index bf1de45..6afa5dc 100644
--- a/tools/testrunner/local/statusfile.py
+++ b/tools/testrunner/local/statusfile.py
@@ -59,7 +59,7 @@ DEFS = {FAIL_OK: [FAIL, OKAY],
 # Support arches, modes to be written as keywords instead of strings.
 VARIABLES = {ALWAYS: True}
 for var in ["debug", "release", "android_arm", "android_ia32", "arm", "ia32",
-            "mipsel", "x64"]:
+            "mipsel", "x64", "ppc", "ppc64"]:
   VARIABLES[var] = var
 
 
diff --git a/tools/utils.py b/tools/utils.py
index 232314c..f27e3f9 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -63,6 +63,8 @@ def GuessOS():
     return 'solaris'
   elif id == 'NetBSD':
     return 'netbsd'
+  elif id == 'AIX':
+    return 'aix'
   else:
     return None
 
@@ -83,6 +85,8 @@ def GuessArchitecture():
     return 'ia32'
   elif id == 'amd64':
     return 'ia32'
+  elif id == 'ppc64':
+    return 'ppc'
   else:
     return None
 
