Skip to content
Browse files

Upgrade V8 to 2.0.5.4

  • Loading branch information...
1 parent 359d017 commit fd73a3a3985b5d4064d3dbb1e5bda7eab259e9c7 @ry ry committed
Showing with 6,762 additions and 1,564 deletions.
  1. +1 −0 deps/v8/.gitignore
  2. +2 −1 deps/v8/AUTHORS
  3. +41 −9 deps/v8/ChangeLog
  4. +19 −0 deps/v8/SConstruct
  5. +16 −10 deps/v8/include/v8.h
  6. +6 −1 deps/v8/src/SConscript
  7. +4 −90 deps/v8/src/api.cc
  8. +88 −98 deps/v8/src/arm/assembler-arm.cc
  9. +124 −97 deps/v8/src/arm/assembler-arm.h
  10. +267 −0 deps/v8/src/arm/assembler-thumb2-inl.h
  11. +1,821 −0 deps/v8/src/arm/assembler-thumb2.cc
  12. +1,027 −0 deps/v8/src/arm/assembler-thumb2.h
  13. +45 −47 deps/v8/src/arm/codegen-arm.cc
  14. +4 −17 deps/v8/src/arm/codegen-arm.h
  15. +10 −11 deps/v8/src/arm/disasm-arm.cc
  16. +192 −158 deps/v8/src/arm/fast-codegen-arm.cc
  17. +4 −0 deps/v8/src/arm/frames-arm.cc
  18. +4 −6 deps/v8/src/arm/ic-arm.cc
  19. +27 −3 deps/v8/src/arm/macro-assembler-arm.cc
  20. +6 −0 deps/v8/src/arm/macro-assembler-arm.h
  21. +10 −10 deps/v8/src/arm/simulator-arm.cc
  22. +38 −9 deps/v8/src/arm/stub-cache-arm.cc
  23. +0 −3 deps/v8/src/arm/virtual-frame-arm.cc
  24. +0 −1 deps/v8/src/arm/virtual-frame-arm.h
  25. +10 −0 deps/v8/src/assembler.cc
  26. +4 −0 deps/v8/src/assembler.h
  27. +14 −3 deps/v8/src/ast.h
  28. +26 −0 deps/v8/src/bootstrapper.cc
  29. +4 −0 deps/v8/src/bootstrapper.h
  30. +89 −54 deps/v8/src/code-stubs.cc
  31. +19 −0 deps/v8/src/code-stubs.h
  32. +49 −0 deps/v8/src/codegen.h
  33. +34 −44 deps/v8/src/compiler.cc
  34. +4 −1 deps/v8/src/contexts.cc
  35. +10 −0 deps/v8/src/execution.cc
  36. +9 −6 deps/v8/src/factory.cc
  37. +4 −2 deps/v8/src/factory.h
  38. +223 −85 deps/v8/src/fast-codegen.cc
  39. +193 −2 deps/v8/src/fast-codegen.h
  40. +11 −6 deps/v8/src/global-handles.cc
  41. +18 −1 deps/v8/src/globals.h
  42. +69 −0 deps/v8/src/heap-inl.h
  43. +3 −2 deps/v8/src/heap-profiler.cc
  44. +5 −1 deps/v8/src/heap-profiler.h
  45. +130 −29 deps/v8/src/heap.cc
  46. +64 −5 deps/v8/src/heap.h
  47. +11 −0 deps/v8/src/ia32/assembler-ia32.cc
  48. +1 −0 deps/v8/src/ia32/assembler-ia32.h
  49. +25 −22 deps/v8/src/ia32/builtins-ia32.cc
  50. +406 −55 deps/v8/src/ia32/codegen-ia32.cc
  51. +14 −11 deps/v8/src/ia32/codegen-ia32.h
  52. +8 −0 deps/v8/src/ia32/disasm-ia32.cc
  53. +203 −178 deps/v8/src/ia32/fast-codegen-ia32.cc
  54. +121 −44 deps/v8/src/ia32/ic-ia32.cc
  55. +87 −8 deps/v8/src/ia32/macro-assembler-ia32.cc
  56. +39 −2 deps/v8/src/ia32/macro-assembler-ia32.h
  57. +108 −45 deps/v8/src/ia32/stub-cache-ia32.cc
  58. +7 −4 deps/v8/src/ia32/virtual-frame-ia32.cc
  59. +3 −3 deps/v8/src/ia32/virtual-frame-ia32.h
  60. +6 −16 deps/v8/src/ic.cc
  61. +18 −6 deps/v8/src/ic.h
  62. +5 −0 deps/v8/src/macro-assembler.h
  63. +10 −64 deps/v8/src/mark-compact.cc
  64. +24 −11 deps/v8/src/math.js
  65. +5 −0 deps/v8/src/messages.js
  66. +6 −6 deps/v8/src/objects-inl.h
  67. +10 −4 deps/v8/src/objects.cc
  68. +28 −19 deps/v8/src/objects.h
  69. +3 −0 deps/v8/src/parser.cc
  70. +5 −5 deps/v8/src/prettyprinter.cc
  71. +1 −1 deps/v8/src/prettyprinter.h
  72. +1 −1 deps/v8/src/rewriter.cc
  73. +94 −11 deps/v8/src/runtime.cc
  74. +4 −0 deps/v8/src/runtime.h
  75. +6 −0 deps/v8/src/runtime.js
  76. +1 −2 deps/v8/src/scopes.cc
  77. +8 −3 deps/v8/src/scopes.h
  78. +15 −7 deps/v8/src/serialize.cc
  79. +2 −2 deps/v8/src/spaces.cc
  80. +12 −15 deps/v8/src/spaces.h
  81. +2 −2 deps/v8/src/stub-cache.cc
  82. +6 −5 deps/v8/src/stub-cache.h
  83. +0 −2 deps/v8/src/token.cc
  84. +3 −6 deps/v8/src/token.h
  85. +0 −2 deps/v8/src/v8-counters.h
  86. +205 −2 deps/v8/src/v8natives.js
  87. +2 −2 deps/v8/src/variables.cc
  88. +7 −7 deps/v8/src/variables.h
  89. +2 −2 deps/v8/src/version.cc
  90. +257 −19 deps/v8/src/x64/codegen-x64.cc
  91. +35 −3 deps/v8/src/x64/codegen-x64.h
  92. +198 −155 deps/v8/src/x64/fast-codegen-x64.cc
Sorry, we could not display the entire diff because it was too big.
View
1 deps/v8/.gitignore
@@ -14,6 +14,7 @@
*.pdb
#*#
*~
+.cpplint-cache
d8
d8_g
shell
View
3 deps/v8/AUTHORS
@@ -13,10 +13,11 @@ Daniel James <dnljms@gmail.com>
Jan de Mooij <jandemooij@gmail.com>
Jay Freeman <saurik@saurik.com>
Joel Stanley <joel.stan@gmail.com>
+John Jozwiak <jjozwiak@codeaurora.org>
Matt Hanselman <mjhanselman@gmail.com>
Paolo Giarrusso <p.giarrusso@gmail.com>
Rafal Krypa <rafal@krypa.net>
Rene Rebe <rene@exactcode.de>
Ryan Dahl <coldredlemur@gmail.com>
Patrick Gansterer <paroga@paroga.com>
-John Jozwiak <jjozwiak@codeaurora.org>
+Subrato K De <subratokde@codeaurora.org>
View
50 deps/v8/ChangeLog
@@ -1,3 +1,35 @@
+2009-12-18: Version 2.0.5
+
+ Extended to upper limit of map space to allow for 7 times as many map
+ to be allocated (issue 524).
+
+ Improved performance of code using closures.
+
+ Improved performance of some binary operations involving doubles.
+
+
+2009-12-16: Version 2.0.4
+
+ Added ECMAScript 5 Object.create.
+
+ Improved performance of Math.max and Math.min.
+
+ Optimized adding of strings on 64-bit platforms.
+
+ Improved handling of external strings by using a separate table
+ instead of weak handles. This improves garbage collection
+ performance and uses less memory.
+
+ Changed code generation for object and array literals in toplevel
+ code to be more compact by doing more work in the runtime.
+
+ Fixed a crash bug triggered when garbage collection happened during
+ generation of a callback load inline cache stub.
+
+ Fixed crash bug sometimes triggered when local variables shadowed
+ parameters in functions that used the arguments object.
+
+
2009-12-03: Version 2.0.3
Optimized handling and adding of strings, for-in and Array.join.
@@ -35,7 +67,7 @@
Reverted a change which caused Chromium interactive ui test
failures.
-
+
2009-11-18: Version 2.0.0
Added support for VFP on ARM.
@@ -80,7 +112,7 @@
2009-10-16: Version 1.3.16
-
+
X64: Convert smis to holding 32 bits of payload.
Introduce v8::Integer::NewFromUnsigned method.
@@ -225,7 +257,7 @@
notifications when V8 has not yet been initialized.
Fixed ARM simulator compilation problem on Windows.
-
+
2009-08-25: Version 1.3.7
@@ -340,9 +372,9 @@
function is a built-in.
Initial implementation of constructor heap profile for JS objects.
-
+
More fine grained control of profiling aspects through the API.
-
+
Optimized the called as constructor check for API calls.
@@ -367,8 +399,8 @@
Added an external allocation limit to avoid issues where small V8
objects would hold on to large amounts of external memory without
causing garbage collections.
-
- Finished more of the inline caching stubs for x64 targets.
+
+ Finished more of the inline caching stubs for x64 targets.
2009-07-13: Version 1.2.14
@@ -448,9 +480,9 @@
Fixed a bug in the string type inference.
Fixed a bug in the handling of 'constant function' properties.
-
+
Improved overall performance.
-
+
2009-06-16: Version 1.2.8
View
19 deps/v8/SConstruct 100755 → 100644
@@ -143,6 +143,9 @@ LIBRARY_FLAGS = {
},
'os:macos': {
'CCFLAGS': ['-ansi', '-mmacosx-version-min=10.4'],
+ 'library:shared': {
+ 'CPPDEFINES': ['V8_SHARED']
+ }
},
'os:freebsd': {
'CPPPATH' : ['/usr/local/include'],
@@ -178,6 +181,12 @@ LIBRARY_FLAGS = {
'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32']
},
+ 'armvariant:thumb2': {
+ 'CPPDEFINES': ['V8_ARM_VARIANT_THUMB']
+ },
+ 'armvariant:arm': {
+ 'CPPDEFINES': ['V8_ARM_VARIANT_ARM']
+ },
'arch:x64': {
'CPPDEFINES': ['V8_TARGET_ARCH_X64'],
'CCFLAGS': ['-m64'],
@@ -243,6 +252,7 @@ V8_EXTRA_FLAGS = {
'gcc': {
'all': {
'WARNINGFLAGS': ['-Wall',
+ '-Werror',
'-W',
'-Wno-unused-parameter',
'-Wnon-virtual-dtor']
@@ -655,6 +665,11 @@ SIMPLE_OPTIONS = {
'values': ['default', 'hidden'],
'default': 'hidden',
'help': 'shared library symbol visibility'
+ },
+ 'armvariant': {
+ 'values': ['arm', 'thumb2', 'none'],
+ 'default': 'none',
+ 'help': 'generate thumb2 instructions instead of arm instructions (default)'
}
}
@@ -838,6 +853,10 @@ def PostprocessOptions(options):
# Print a warning if profiling is enabled without profiling support
print "Warning: forcing profilingsupport on when prof is on"
options['profilingsupport'] = 'on'
+ if (options['armvariant'] == 'none' and options['arch'] == 'arm'):
+ options['armvariant'] = 'arm'
+ if (options['armvariant'] != 'none' and options['arch'] != 'arm'):
+ options['armvariant'] = 'none'
def ParseEnvOverrides(arg, imports):
View
26 deps/v8/include/v8.h
@@ -833,13 +833,26 @@ class V8EXPORT String : public Primitive {
* Returns true if the string is both external and ascii
*/
bool IsExternalAscii() const;
+
+ class V8EXPORT ExternalStringResourceBase {
+ public:
+ virtual ~ExternalStringResourceBase() {}
+ protected:
+ ExternalStringResourceBase() {}
+ private:
+ // Disallow copying and assigning.
+ ExternalStringResourceBase(const ExternalStringResourceBase&);
+ void operator=(const ExternalStringResourceBase&);
+ };
+
/**
* An ExternalStringResource is a wrapper around a two-byte string
* buffer that resides outside V8's heap. Implement an
* ExternalStringResource to manage the life cycle of the underlying
* buffer. Note that the string data must be immutable.
*/
- class V8EXPORT ExternalStringResource { // NOLINT
+ class V8EXPORT ExternalStringResource
+ : public ExternalStringResourceBase {
public:
/**
* Override the destructor to manage the life cycle of the underlying
@@ -852,10 +865,6 @@ class V8EXPORT String : public Primitive {
virtual size_t length() const = 0;
protected:
ExternalStringResource() {}
- private:
- // Disallow copying and assigning.
- ExternalStringResource(const ExternalStringResource&);
- void operator=(const ExternalStringResource&);
};
/**
@@ -869,7 +878,8 @@ class V8EXPORT String : public Primitive {
* Use String::New or convert to 16 bit data for non-ASCII.
*/
- class V8EXPORT ExternalAsciiStringResource { // NOLINT
+ class V8EXPORT ExternalAsciiStringResource
+ : public ExternalStringResourceBase {
public:
/**
* Override the destructor to manage the life cycle of the underlying
@@ -882,10 +892,6 @@ class V8EXPORT String : public Primitive {
virtual size_t length() const = 0;
protected:
ExternalAsciiStringResource() {}
- private:
- // Disallow copying and assigning.
- ExternalAsciiStringResource(const ExternalAsciiStringResource&);
- void operator=(const ExternalAsciiStringResource&);
};
/**
View
7 deps/v8/src/SConscript
@@ -106,7 +106,6 @@ SOURCES = {
zone.cc
"""),
'arch:arm': Split("""
- arm/assembler-arm.cc
arm/builtins-arm.cc
arm/codegen-arm.cc
arm/constants-arm.cc
@@ -123,6 +122,12 @@ SOURCES = {
arm/stub-cache-arm.cc
arm/virtual-frame-arm.cc
"""),
+ 'armvariant:arm': Split("""
+ arm/assembler-arm.cc
+ """),
+ 'armvariant:thumb2': Split("""
+ arm/assembler-thumb2.cc
+ """),
'arch:ia32': Split("""
ia32/assembler-ia32.cc
ia32/builtins-ia32.cc
View
94 deps/v8/src/api.cc
@@ -3082,81 +3082,13 @@ i::Handle<i::String> NewExternalAsciiStringHandle(
}
-static void DisposeExternalString(v8::Persistent<v8::Value> obj,
- void* parameter) {
- ENTER_V8;
- i::ExternalTwoByteString* str =
- i::ExternalTwoByteString::cast(*Utils::OpenHandle(*obj));
-
- // External symbols are deleted when they are pruned out of the symbol
- // table. Generally external symbols are not registered with the weak handle
- // callbacks unless they are upgraded to a symbol after being externalized.
- if (!str->IsSymbol()) {
- v8::String::ExternalStringResource* resource =
- reinterpret_cast<v8::String::ExternalStringResource*>(parameter);
- if (resource != NULL) {
- const int total_size =
- static_cast<int>(resource->length() * sizeof(*resource->data()));
- i::Counters::total_external_string_memory.Decrement(total_size);
-
- // The object will continue to live in the JavaScript heap until the
- // handle is entirely cleaned out by the next GC. For example the
- // destructor for the resource below could bring it back to life again.
- // Which is why we make sure to not have a dangling pointer here.
- str->set_resource(NULL);
- delete resource;
- }
- }
-
- // In any case we do not need this handle any longer.
- obj.Dispose();
-}
-
-
-static void DisposeExternalAsciiString(v8::Persistent<v8::Value> obj,
- void* parameter) {
- ENTER_V8;
- i::ExternalAsciiString* str =
- i::ExternalAsciiString::cast(*Utils::OpenHandle(*obj));
-
- // External symbols are deleted when they are pruned out of the symbol
- // table. Generally external symbols are not registered with the weak handle
- // callbacks unless they are upgraded to a symbol after being externalized.
- if (!str->IsSymbol()) {
- v8::String::ExternalAsciiStringResource* resource =
- reinterpret_cast<v8::String::ExternalAsciiStringResource*>(parameter);
- if (resource != NULL) {
- const int total_size =
- static_cast<int>(resource->length() * sizeof(*resource->data()));
- i::Counters::total_external_string_memory.Decrement(total_size);
-
- // The object will continue to live in the JavaScript heap until the
- // handle is entirely cleaned out by the next GC. For example the
- // destructor for the resource below could bring it back to life again.
- // Which is why we make sure to not have a dangling pointer here.
- str->set_resource(NULL);
- delete resource;
- }
- }
-
- // In any case we do not need this handle any longer.
- obj.Dispose();
-}
-
-
Local<String> v8::String::NewExternal(
v8::String::ExternalStringResource* resource) {
EnsureInitialized("v8::String::NewExternal()");
LOG_API("String::NewExternal");
ENTER_V8;
- const int total_size =
- static_cast<int>(resource->length() * sizeof(*resource->data()));
- i::Counters::total_external_string_memory.Increment(total_size);
i::Handle<i::String> result = NewExternalStringHandle(resource);
- i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
- i::GlobalHandles::MakeWeak(handle.location(),
- resource,
- &DisposeExternalString);
+ i::ExternalStringTable::AddString(*result);
return Utils::ToLocal(result);
}
@@ -3168,13 +3100,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
i::Handle<i::String> obj = Utils::OpenHandle(this);
bool result = obj->MakeExternal(resource);
if (result && !obj->IsSymbol()) {
- // Operation was successful and the string is not a symbol. In this case
- // we need to make sure that the we call the destructor for the external
- // resource when no strong references to the string remain.
- i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
- i::GlobalHandles::MakeWeak(handle.location(),
- resource,
- &DisposeExternalString);
+ i::ExternalStringTable::AddString(*obj);
}
return result;
}
@@ -3185,14 +3111,8 @@ Local<String> v8::String::NewExternal(
EnsureInitialized("v8::String::NewExternal()");
LOG_API("String::NewExternal");
ENTER_V8;
- const int total_size =
- static_cast<int>(resource->length() * sizeof(*resource->data()));
- i::Counters::total_external_string_memory.Increment(total_size);
i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
- i::Handle<i::Object> handle = i::GlobalHandles::Create(*result);
- i::GlobalHandles::MakeWeak(handle.location(),
- resource,
- &DisposeExternalAsciiString);
+ i::ExternalStringTable::AddString(*result);
return Utils::ToLocal(result);
}
@@ -3205,13 +3125,7 @@ bool v8::String::MakeExternal(
i::Handle<i::String> obj = Utils::OpenHandle(this);
bool result = obj->MakeExternal(resource);
if (result && !obj->IsSymbol()) {
- // Operation was successful and the string is not a symbol. In this case
- // we need to make sure that the we call the destructor for the external
- // resource when no strong references to the string remain.
- i::Handle<i::Object> handle = i::GlobalHandles::Create(*obj);
- i::GlobalHandles::MakeWeak(handle.location(),
- resource,
- &DisposeExternalAsciiString);
+ i::ExternalStringTable::AddString(*obj);
}
return result;
}
View
186 deps/v8/src/arm/assembler-arm.cc
@@ -114,55 +114,55 @@ CRegister cr15 = { 15 };
// Support for the VFP registers s0 to s31 (d0 to d15).
// Note that "sN:sM" is the same as "dN/2".
-Register s0 = { 0 };
-Register s1 = { 1 };
-Register s2 = { 2 };
-Register s3 = { 3 };
-Register s4 = { 4 };
-Register s5 = { 5 };
-Register s6 = { 6 };
-Register s7 = { 7 };
-Register s8 = { 8 };
-Register s9 = { 9 };
-Register s10 = { 10 };
-Register s11 = { 11 };
-Register s12 = { 12 };
-Register s13 = { 13 };
-Register s14 = { 14 };
-Register s15 = { 15 };
-Register s16 = { 16 };
-Register s17 = { 17 };
-Register s18 = { 18 };
-Register s19 = { 19 };
-Register s20 = { 20 };
-Register s21 = { 21 };
-Register s22 = { 22 };
-Register s23 = { 23 };
-Register s24 = { 24 };
-Register s25 = { 25 };
-Register s26 = { 26 };
-Register s27 = { 27 };
-Register s28 = { 28 };
-Register s29 = { 29 };
-Register s30 = { 30 };
-Register s31 = { 31 };
-
-Register d0 = { 0 };
-Register d1 = { 1 };
-Register d2 = { 2 };
-Register d3 = { 3 };
-Register d4 = { 4 };
-Register d5 = { 5 };
-Register d6 = { 6 };
-Register d7 = { 7 };
-Register d8 = { 8 };
-Register d9 = { 9 };
-Register d10 = { 10 };
-Register d11 = { 11 };
-Register d12 = { 12 };
-Register d13 = { 13 };
-Register d14 = { 14 };
-Register d15 = { 15 };
+SwVfpRegister s0 = { 0 };
+SwVfpRegister s1 = { 1 };
+SwVfpRegister s2 = { 2 };
+SwVfpRegister s3 = { 3 };
+SwVfpRegister s4 = { 4 };
+SwVfpRegister s5 = { 5 };
+SwVfpRegister s6 = { 6 };
+SwVfpRegister s7 = { 7 };
+SwVfpRegister s8 = { 8 };
+SwVfpRegister s9 = { 9 };
+SwVfpRegister s10 = { 10 };
+SwVfpRegister s11 = { 11 };
+SwVfpRegister s12 = { 12 };
+SwVfpRegister s13 = { 13 };
+SwVfpRegister s14 = { 14 };
+SwVfpRegister s15 = { 15 };
+SwVfpRegister s16 = { 16 };
+SwVfpRegister s17 = { 17 };
+SwVfpRegister s18 = { 18 };
+SwVfpRegister s19 = { 19 };
+SwVfpRegister s20 = { 20 };
+SwVfpRegister s21 = { 21 };
+SwVfpRegister s22 = { 22 };
+SwVfpRegister s23 = { 23 };
+SwVfpRegister s24 = { 24 };
+SwVfpRegister s25 = { 25 };
+SwVfpRegister s26 = { 26 };
+SwVfpRegister s27 = { 27 };
+SwVfpRegister s28 = { 28 };
+SwVfpRegister s29 = { 29 };
+SwVfpRegister s30 = { 30 };
+SwVfpRegister s31 = { 31 };
+
+DwVfpRegister d0 = { 0 };
+DwVfpRegister d1 = { 1 };
+DwVfpRegister d2 = { 2 };
+DwVfpRegister d3 = { 3 };
+DwVfpRegister d4 = { 4 };
+DwVfpRegister d5 = { 5 };
+DwVfpRegister d6 = { 6 };
+DwVfpRegister d7 = { 7 };
+DwVfpRegister d8 = { 8 };
+DwVfpRegister d9 = { 9 };
+DwVfpRegister d10 = { 10 };
+DwVfpRegister d11 = { 11 };
+DwVfpRegister d12 = { 12 };
+DwVfpRegister d13 = { 13 };
+DwVfpRegister d14 = { 14 };
+DwVfpRegister d15 = { 15 };
// -----------------------------------------------------------------------------
// Implementation of RelocInfo
@@ -1371,11 +1371,10 @@ void Assembler::stc2(Coprocessor coproc,
// Support for VFP.
-void Assembler::fmdrr(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s,
- const Condition cond) {
+void Assembler::vmov(const DwVfpRegister dst,
+ const Register src1,
+ const Register src2,
+ const Condition cond) {
// Dm = <Rt,Rt2>.
// Instruction details available in ARM DDI 0406A, A8-646.
// cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
@@ -1387,11 +1386,10 @@ void Assembler::fmdrr(const Register dst,
}
-void Assembler::fmrrd(const Register dst1,
- const Register dst2,
- const Register src,
- const SBit s,
- const Condition cond) {
+void Assembler::vmov(const Register dst1,
+ const Register dst2,
+ const DwVfpRegister src,
+ const Condition cond) {
// <Rt,Rt2> = Dm.
// Instruction details available in ARM DDI 0406A, A8-646.
// cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
@@ -1403,9 +1401,8 @@ void Assembler::fmrrd(const Register dst1,
}
-void Assembler::fmsr(const Register dst,
+void Assembler::vmov(const SwVfpRegister dst,
const Register src,
- const SBit s,
const Condition cond) {
// Sn = Rt.
// Instruction details available in ARM DDI 0406A, A8-642.
@@ -1418,9 +1415,8 @@ void Assembler::fmsr(const Register dst,
}
-void Assembler::fmrs(const Register dst,
- const Register src,
- const SBit s,
+void Assembler::vmov(const Register dst,
+ const SwVfpRegister src,
const Condition cond) {
// Rt = Sn.
// Instruction details available in ARM DDI 0406A, A8-642.
@@ -1433,10 +1429,9 @@ void Assembler::fmrs(const Register dst,
}
-void Assembler::fsitod(const Register dst,
- const Register src,
- const SBit s,
- const Condition cond) {
+void Assembler::vcvt(const DwVfpRegister dst,
+ const SwVfpRegister src,
+ const Condition cond) {
// Dd = Sm (integer in Sm converted to IEEE 64-bit doubles in Dd).
// Instruction details available in ARM DDI 0406A, A8-576.
// cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) |opc2=000(18-16) |
@@ -1448,10 +1443,9 @@ void Assembler::fsitod(const Register dst,
}
-void Assembler::ftosid(const Register dst,
- const Register src,
- const SBit s,
- const Condition cond) {
+void Assembler::vcvt(const SwVfpRegister dst,
+ const DwVfpRegister src,
+ const Condition cond) {
// Sd = Dm (IEEE 64-bit doubles in Dm converted to 32 bit integer in Sd).
// Instruction details available in ARM DDI 0406A, A8-576.
// cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)|
@@ -1463,12 +1457,11 @@ void Assembler::ftosid(const Register dst,
}
-void Assembler::faddd(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s,
- const Condition cond) {
- // Dd = faddd(Dn, Dm) double precision floating point addition.
+void Assembler::vadd(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond) {
+ // Dd = vadd(Dn, Dm) double precision floating point addition.
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
// Instruction details available in ARM DDI 0406A, A8-536.
// cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
@@ -1479,12 +1472,11 @@ void Assembler::faddd(const Register dst,
}
-void Assembler::fsubd(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s,
- const Condition cond) {
- // Dd = fsubd(Dn, Dm) double precision floating point subtraction.
+void Assembler::vsub(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond) {
+ // Dd = vsub(Dn, Dm) double precision floating point subtraction.
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
// Instruction details available in ARM DDI 0406A, A8-784.
// cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
@@ -1495,12 +1487,11 @@ void Assembler::fsubd(const Register dst,
}
-void Assembler::fmuld(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s,
- const Condition cond) {
- // Dd = fmuld(Dn, Dm) double precision floating point multiplication.
+void Assembler::vmul(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond) {
+ // Dd = vmul(Dn, Dm) double precision floating point multiplication.
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
// Instruction details available in ARM DDI 0406A, A8-784.
// cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
@@ -1511,12 +1502,11 @@ void Assembler::fmuld(const Register dst,
}
-void Assembler::fdivd(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s,
- const Condition cond) {
- // Dd = fdivd(Dn, Dm) double precision floating point division.
+void Assembler::vdiv(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond) {
+ // Dd = vdiv(Dn, Dm) double precision floating point division.
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
// Instruction details available in ARM DDI 0406A, A8-584.
// cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
@@ -1527,8 +1517,8 @@ void Assembler::fdivd(const Register dst,
}
-void Assembler::fcmp(const Register src1,
- const Register src2,
+void Assembler::vcmp(const DwVfpRegister src1,
+ const DwVfpRegister src2,
const SBit s,
const Condition cond) {
// vcmp(Dd, Dm) double precision floating point comparison.
View
221 deps/v8/src/arm/assembler-arm.h
@@ -103,57 +103,94 @@ extern Register sp;
extern Register lr;
extern Register pc;
-// Support for VFP registers s0 to s32 (d0 to d16).
-// Note that "sN:sM" is the same as "dN/2".
-extern Register s0;
-extern Register s1;
-extern Register s2;
-extern Register s3;
-extern Register s4;
-extern Register s5;
-extern Register s6;
-extern Register s7;
-extern Register s8;
-extern Register s9;
-extern Register s10;
-extern Register s11;
-extern Register s12;
-extern Register s13;
-extern Register s14;
-extern Register s15;
-extern Register s16;
-extern Register s17;
-extern Register s18;
-extern Register s19;
-extern Register s20;
-extern Register s21;
-extern Register s22;
-extern Register s23;
-extern Register s24;
-extern Register s25;
-extern Register s26;
-extern Register s27;
-extern Register s28;
-extern Register s29;
-extern Register s30;
-extern Register s31;
-
-extern Register d0;
-extern Register d1;
-extern Register d2;
-extern Register d3;
-extern Register d4;
-extern Register d5;
-extern Register d6;
-extern Register d7;
-extern Register d8;
-extern Register d9;
-extern Register d10;
-extern Register d11;
-extern Register d12;
-extern Register d13;
-extern Register d14;
-extern Register d15;
+
+// Single word VFP register.
+struct SwVfpRegister {
+ bool is_valid() const { return 0 <= code_ && code_ < 32; }
+ bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
+ int code() const {
+ ASSERT(is_valid());
+ return code_;
+ }
+ int bit() const {
+ ASSERT(is_valid());
+ return 1 << code_;
+ }
+
+ int code_;
+};
+
+
+// Double word VFP register.
+struct DwVfpRegister {
+ // Supporting d0 to d15, can be later extended to d31.
+ bool is_valid() const { return 0 <= code_ && code_ < 16; }
+ 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_;
+ }
+
+ int code_;
+};
+
+
+// Support for VFP registers s0 to s31 (d0 to d15).
+// Note that "s(N):s(N+1)" is the same as "d(N/2)".
+extern SwVfpRegister s0;
+extern SwVfpRegister s1;
+extern SwVfpRegister s2;
+extern SwVfpRegister s3;
+extern SwVfpRegister s4;
+extern SwVfpRegister s5;
+extern SwVfpRegister s6;
+extern SwVfpRegister s7;
+extern SwVfpRegister s8;
+extern SwVfpRegister s9;
+extern SwVfpRegister s10;
+extern SwVfpRegister s11;
+extern SwVfpRegister s12;
+extern SwVfpRegister s13;
+extern SwVfpRegister s14;
+extern SwVfpRegister s15;
+extern SwVfpRegister s16;
+extern SwVfpRegister s17;
+extern SwVfpRegister s18;
+extern SwVfpRegister s19;
+extern SwVfpRegister s20;
+extern SwVfpRegister s21;
+extern SwVfpRegister s22;
+extern SwVfpRegister s23;
+extern SwVfpRegister s24;
+extern SwVfpRegister s25;
+extern SwVfpRegister s26;
+extern SwVfpRegister s27;
+extern SwVfpRegister s28;
+extern SwVfpRegister s29;
+extern SwVfpRegister s30;
+extern SwVfpRegister s31;
+
+extern DwVfpRegister d0;
+extern DwVfpRegister d1;
+extern DwVfpRegister d2;
+extern DwVfpRegister d3;
+extern DwVfpRegister d4;
+extern DwVfpRegister d5;
+extern DwVfpRegister d6;
+extern DwVfpRegister d7;
+extern DwVfpRegister d8;
+extern DwVfpRegister d9;
+extern DwVfpRegister d10;
+extern DwVfpRegister d11;
+extern DwVfpRegister d12;
+extern DwVfpRegister d13;
+extern DwVfpRegister d14;
+extern DwVfpRegister d15;
+
// Coprocessor register
struct CRegister {
@@ -759,55 +796,45 @@ class Assembler : public Malloced {
// However, some simple modifications can allow
// these APIs to support D16 to D31.
- void fmdrr(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s = LeaveCC,
- const Condition cond = al);
- void fmrrd(const Register dst1,
- const Register dst2,
- const Register src,
- const SBit s = LeaveCC,
- const Condition cond = al);
- void fmsr(const Register dst,
- const Register src,
- const SBit s = LeaveCC,
+ void vmov(const DwVfpRegister dst,
+ const Register src1,
+ const Register src2,
+ const Condition cond = al);
+ void vmov(const Register dst1,
+ const Register dst2,
+ const DwVfpRegister src,
const Condition cond = al);
- void fmrs(const Register dst,
+ void vmov(const SwVfpRegister dst,
const Register src,
- const SBit s = LeaveCC,
const Condition cond = al);
- void fsitod(const Register dst,
- const Register src,
- const SBit s = LeaveCC,
- const Condition cond = al);
- void ftosid(const Register dst,
- const Register src,
- const SBit s = LeaveCC,
- const Condition cond = al);
-
- void faddd(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s = LeaveCC,
- const Condition cond = al);
- void fsubd(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s = LeaveCC,
- const Condition cond = al);
- void fmuld(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s = LeaveCC,
- const Condition cond = al);
- void fdivd(const Register dst,
- const Register src1,
- const Register src2,
- const SBit s = LeaveCC,
- const Condition cond = al);
- void fcmp(const Register src1,
- const Register src2,
+ void vmov(const Register dst,
+ const SwVfpRegister src,
+ const Condition cond = al);
+ void vcvt(const DwVfpRegister dst,
+ const SwVfpRegister src,
+ const Condition cond = al);
+ void vcvt(const SwVfpRegister dst,
+ const DwVfpRegister src,
+ const Condition cond = al);
+
+ void vadd(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vsub(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vmul(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vdiv(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vcmp(const DwVfpRegister src1,
+ const DwVfpRegister src2,
const SBit s = LeaveCC,
const Condition cond = al);
void vmrs(const Register dst,
View
267 deps/v8/src/arm/assembler-thumb2-inl.h
@@ -0,0 +1,267 @@
+// 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 2006-2008 the V8 project authors. All rights reserved.
+
+#ifndef V8_ARM_ASSEMBLER_THUMB2_INL_H_
+#define V8_ARM_ASSEMBLER_THUMB2_INL_H_
+
+#include "arm/assembler-thumb2.h"
+#include "cpu.h"
+
+
+namespace v8 {
+namespace internal {
+
+Condition NegateCondition(Condition cc) {
+ ASSERT(cc != al);
+ return static_cast<Condition>(cc ^ ne);
+}
+
+
+void RelocInfo::apply(intptr_t delta) {
+ if (RelocInfo::IsInternalReference(rmode_)) {
+ // absolute code pointer inside code object moves with the code object.
+ int32_t* p = reinterpret_cast<int32_t*>(pc_);
+ *p += delta; // relocate entry
+ }
+ // We do not use pc relative addressing on ARM, 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);
+ return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_));
+}
+
+
+void RelocInfo::set_target_address(Address target) {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ Assembler::set_target_address_at(pc_, target);
+}
+
+
+Object* RelocInfo::target_object() {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+ return Memory::Object_at(Assembler::target_address_address_at(pc_));
+}
+
+
+Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+ return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_));
+}
+
+
+Object** RelocInfo::target_object_address() {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+ return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_));
+}
+
+
+void RelocInfo::set_target_object(Object* target) {
+ ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+ Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target));
+}
+
+
+Address* RelocInfo::target_reference_address() {
+ ASSERT(rmode_ == EXTERNAL_REFERENCE);
+ return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_));
+}
+
+
+Address RelocInfo::call_address() {
+ ASSERT(IsPatchedReturnSequence());
+ // The 2 instructions offset assumes patched return sequence.
+ ASSERT(IsJSReturn(rmode()));
+ return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize);
+}
+
+
+void RelocInfo::set_call_address(Address target) {
+ ASSERT(IsPatchedReturnSequence());
+ // The 2 instructions offset assumes patched return sequence.
+ ASSERT(IsJSReturn(rmode()));
+ Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target;
+}
+
+
+Object* RelocInfo::call_object() {
+ return *call_object_address();
+}
+
+
+Object** RelocInfo::call_object_address() {
+ ASSERT(IsPatchedReturnSequence());
+ // The 2 instructions offset assumes patched return sequence.
+ ASSERT(IsJSReturn(rmode()));
+ return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize);
+}
+
+
+void RelocInfo::set_call_object(Object* target) {
+ *call_object_address() = target;
+}
+
+
+bool RelocInfo::IsPatchedReturnSequence() {
+ // On ARM a "call instruction" is actually two instructions.
+ // mov lr, pc
+ // ldr pc, [pc, #XXX]
+ return (Assembler::instr_at(pc_) == kMovLrPc)
+ && ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern)
+ == kLdrPCPattern);
+}
+
+
+Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) {
+ rm_ = no_reg;
+ imm32_ = immediate;
+ rmode_ = rmode;
+}
+
+
+Operand::Operand(const char* s) {
+ rm_ = no_reg;
+ imm32_ = reinterpret_cast<int32_t>(s);
+ rmode_ = RelocInfo::EMBEDDED_STRING;
+}
+
+
+Operand::Operand(const ExternalReference& f) {
+ rm_ = no_reg;
+ imm32_ = reinterpret_cast<int32_t>(f.address());
+ rmode_ = RelocInfo::EXTERNAL_REFERENCE;
+}
+
+
+Operand::Operand(Object** opp) {
+ rm_ = no_reg;
+ imm32_ = reinterpret_cast<int32_t>(opp);
+ rmode_ = RelocInfo::NONE;
+}
+
+
+Operand::Operand(Context** cpp) {
+ rm_ = no_reg;
+ imm32_ = reinterpret_cast<int32_t>(cpp);
+ rmode_ = RelocInfo::NONE;
+}
+
+
+Operand::Operand(Smi* value) {
+ rm_ = no_reg;
+ imm32_ = reinterpret_cast<intptr_t>(value);
+ rmode_ = RelocInfo::NONE;
+}
+
+
+Operand::Operand(Register rm) {
+ rm_ = rm;
+ rs_ = no_reg;
+ shift_op_ = LSL;
+ shift_imm_ = 0;
+}
+
+
+bool Operand::is_reg() const {
+ return rm_.is_valid() &&
+ rs_.is(no_reg) &&
+ shift_op_ == LSL &&
+ shift_imm_ == 0;
+}
+
+
+void Assembler::CheckBuffer() {
+ if (buffer_space() <= kGap) {
+ GrowBuffer();
+ }
+ if (pc_offset() >= next_buffer_check_) {
+ CheckConstPool(false, true);
+ }
+}
+
+
+void Assembler::emit(Instr x) {
+ CheckBuffer();
+ *reinterpret_cast<Instr*>(pc_) = x;
+ pc_ += kInstrSize;
+}
+
+
+Address Assembler::target_address_address_at(Address pc) {
+ Instr instr = Memory::int32_at(pc);
+ // Verify that the instruction at pc is a ldr<cond> <Rd>, [pc +/- offset_12].
+ ASSERT((instr & 0x0f7f0000) == 0x051f0000);
+ int offset = instr & 0xfff; // offset_12 is unsigned
+ if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign
+ // Verify that the constant pool comes after the instruction referencing it.
+ ASSERT(offset >= -4);
+ return pc + offset + 8;
+}
+
+
+Address Assembler::target_address_at(Address pc) {
+ return Memory::Address_at(target_address_address_at(pc));
+}
+
+
+void Assembler::set_target_at(Address constant_pool_entry,
+ Address target) {
+ Memory::Address_at(constant_pool_entry) = target;
+}
+
+
+void Assembler::set_target_address_at(Address pc, Address target) {
+ Memory::Address_at(target_address_address_at(pc)) = target;
+ // Intuitively, we would think it is necessary to flush the instruction cache
+ // after patching a target address in the code as follows:
+ // CPU::FlushICache(pc, sizeof(target));
+ // However, on ARM, no instruction was actually patched by the assignment
+ // above; the target address is not part of an instruction, it is patched in
+ // the constant pool and is read via a data access; the instruction accessing
+ // this address in the constant pool remains unchanged.
+}
+
+} } // namespace v8::internal
+
+#endif // V8_ARM_ASSEMBLER_THUMB2_INL_H_
View
1,821 deps/v8/src/arm/assembler-thumb2.cc
1,821 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
1,027 deps/v8/src/arm/assembler-thumb2.h
@@ -0,0 +1,1027 @@
+// 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 2006-2008 the V8 project authors. All rights reserved.
+
+// A light-weight ARM Assembler
+// Generates user mode instructions for the ARM architecture up to version 5
+
+#ifndef V8_ARM_ASSEMBLER_THUMB2_H_
+#define V8_ARM_ASSEMBLER_THUMB2_H_
+#include <stdio.h>
+#include "assembler.h"
+#include "serialize.h"
+
+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 {
+ bool is_valid() const { return 0 <= code_ && code_ < 16; }
+ 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_;
+ }
+
+ // (unfortunately we can't make this private in a struct)
+ int code_;
+};
+
+
+extern Register no_reg;
+extern Register r0;
+extern Register r1;
+extern Register r2;
+extern Register r3;
+extern Register r4;
+extern Register r5;
+extern Register r6;
+extern Register r7;
+extern Register r8;
+extern Register r9;
+extern Register r10;
+extern Register fp;
+extern Register ip;
+extern Register sp;
+extern Register lr;
+extern Register pc;
+
+
+// Single word VFP register.
+struct SwVfpRegister {
+ bool is_valid() const { return 0 <= code_ && code_ < 32; }
+ bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
+ int code() const {
+ ASSERT(is_valid());
+ return code_;
+ }
+ int bit() const {
+ ASSERT(is_valid());
+ return 1 << code_;
+ }
+
+ int code_;
+};
+
+
+// Double word VFP register.
+struct DwVfpRegister {
+ // Supporting d0 to d15, can be later extended to d31.
+ bool is_valid() const { return 0 <= code_ && code_ < 16; }
+ 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_;
+ }
+
+ int code_;
+};
+
+
+// Support for VFP registers s0 to s31 (d0 to d15).
+// Note that "s(N):s(N+1)" is the same as "d(N/2)".
+extern SwVfpRegister s0;
+extern SwVfpRegister s1;
+extern SwVfpRegister s2;
+extern SwVfpRegister s3;
+extern SwVfpRegister s4;
+extern SwVfpRegister s5;
+extern SwVfpRegister s6;
+extern SwVfpRegister s7;
+extern SwVfpRegister s8;
+extern SwVfpRegister s9;
+extern SwVfpRegister s10;
+extern SwVfpRegister s11;
+extern SwVfpRegister s12;
+extern SwVfpRegister s13;
+extern SwVfpRegister s14;
+extern SwVfpRegister s15;
+extern SwVfpRegister s16;
+extern SwVfpRegister s17;
+extern SwVfpRegister s18;
+extern SwVfpRegister s19;
+extern SwVfpRegister s20;
+extern SwVfpRegister s21;
+extern SwVfpRegister s22;
+extern SwVfpRegister s23;
+extern SwVfpRegister s24;
+extern SwVfpRegister s25;
+extern SwVfpRegister s26;
+extern SwVfpRegister s27;
+extern SwVfpRegister s28;
+extern SwVfpRegister s29;
+extern SwVfpRegister s30;
+extern SwVfpRegister s31;
+
+extern DwVfpRegister d0;
+extern DwVfpRegister d1;
+extern DwVfpRegister d2;
+extern DwVfpRegister d3;
+extern DwVfpRegister d4;
+extern DwVfpRegister d5;
+extern DwVfpRegister d6;
+extern DwVfpRegister d7;
+extern DwVfpRegister d8;
+extern DwVfpRegister d9;
+extern DwVfpRegister d10;
+extern DwVfpRegister d11;
+extern DwVfpRegister d12;
+extern DwVfpRegister d13;
+extern DwVfpRegister d14;
+extern DwVfpRegister d15;
+
+
+// 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_;
+};
+
+
+extern CRegister no_creg;
+extern CRegister cr0;
+extern CRegister cr1;
+extern CRegister cr2;
+extern CRegister cr3;
+extern CRegister cr4;
+extern CRegister cr5;
+extern CRegister cr6;
+extern CRegister cr7;
+extern CRegister cr8;
+extern CRegister cr9;
+extern CRegister cr10;
+extern CRegister cr11;
+extern CRegister cr12;
+extern CRegister cr13;
+extern CRegister cr14;
+extern CRegister cr15;
+
+
+// Coprocessor number
+enum Coprocessor {
+ p0 = 0,
+ p1 = 1,
+ p2 = 2,
+ p3 = 3,
+ p4 = 4,
+ p5 = 5,
+ p6 = 6,
+ p7 = 7,
+ p8 = 8,
+ p9 = 9,
+ p10 = 10,
+ p11 = 11,
+ p12 = 12,
+ p13 = 13,
+ p14 = 14,
+ p15 = 15
+};
+
+
+// Condition field in instructions
+enum Condition {
+ eq = 0 << 28, // Z set equal.
+ ne = 1 << 28, // Z clear not equal.
+ nz = 1 << 28, // Z clear not zero.
+ cs = 2 << 28, // C set carry set.
+ hs = 2 << 28, // C set unsigned higher or same.
+ cc = 3 << 28, // C clear carry clear.
+ lo = 3 << 28, // C clear unsigned lower.
+ mi = 4 << 28, // N set negative.
+ pl = 5 << 28, // N clear positive or zero.
+ vs = 6 << 28, // V set overflow.
+ vc = 7 << 28, // V clear no overflow.
+ hi = 8 << 28, // C set, Z clear unsigned higher.
+ ls = 9 << 28, // C clear or Z set unsigned lower or same.
+ ge = 10 << 28, // N == V greater or equal.
+ lt = 11 << 28, // N != V less than.
+ gt = 12 << 28, // Z clear, N == V greater than.
+ le = 13 << 28, // Z set or N != V less then or equal
+ al = 14 << 28 // always.
+};
+
+
+// Returns the equivalent of !cc.
+INLINE(Condition NegateCondition(Condition cc));
+
+
+// Corresponds to transposing the operands of a comparison.
+inline Condition ReverseCondition(Condition cc) {
+ switch (cc) {
+ case lo:
+ return hi;
+ case hi:
+ return lo;
+ case hs:
+ return ls;
+ case ls:
+ return hs;
+ case lt:
+ return gt;
+ case gt:
+ return lt;
+ case ge:
+ return le;
+ case le:
+ return ge;
+ default:
+ return cc;
+ };
+}
+
+
+// Branch hints are not used on the ARM. They are defined so that they can
+// appear in shared function signatures, but will be ignored in ARM
+// implementations.
+enum Hint { no_hint };
+
+// Hints are not used on the arm. Negating is trivial.
+inline Hint NegateHint(Hint ignored) { return no_hint; }
+
+
+// -----------------------------------------------------------------------------
+// Addressing modes and instruction variants
+
+// Shifter operand shift operation
+enum ShiftOp {
+ LSL = 0 << 5,
+ LSR = 1 << 5,
+ ASR = 2 << 5,
+ ROR = 3 << 5,
+ RRX = -1
+};
+
+
+// Condition code updating mode
+enum SBit {
+ SetCC = 1 << 20, // set condition code
+ LeaveCC = 0 << 20 // leave condition code unchanged
+};
+
+
+// Status register selection
+enum SRegister {
+ CPSR = 0 << 22,
+ SPSR = 1 << 22
+};
+
+
+// Status register fields
+enum SRegisterField {
+ CPSR_c = CPSR | 1 << 16,
+ CPSR_x = CPSR | 1 << 17,
+ CPSR_s = CPSR | 1 << 18,
+ CPSR_f = CPSR | 1 << 19,
+ SPSR_c = SPSR | 1 << 16,
+ SPSR_x = SPSR | 1 << 17,
+ SPSR_s = SPSR | 1 << 18,
+ SPSR_f = SPSR | 1 << 19
+};
+
+// Status register field mask (or'ed SRegisterField enum values)
+typedef uint32_t SRegisterFieldMask;
+
+
+// Memory operand addressing mode
+enum AddrMode {
+ // bit encoding P U W
+ Offset = (8|4|0) << 21, // offset (without writeback to base)
+ PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback
+ PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback
+ NegOffset = (8|0|0) << 21, // negative offset (without writeback to base)
+ NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback
+ NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback
+};
+
+
+// Load/store multiple addressing mode
+enum BlockAddrMode {
+ // bit encoding P U W
+ da = (0|0|0) << 21, // decrement after
+ ia = (0|4|0) << 21, // increment after
+ db = (8|0|0) << 21, // decrement before
+ ib = (8|4|0) << 21, // increment before
+ da_w = (0|0|1) << 21, // decrement after with writeback to base
+ ia_w = (0|4|1) << 21, // increment after with writeback to base
+ db_w = (8|0|1) << 21, // decrement before with writeback to base
+ ib_w = (8|4|1) << 21 // increment before with writeback to base
+};
+
+
+// Coprocessor load/store operand size
+enum LFlag {
+ Long = 1 << 22, // long load/store coprocessor
+ Short = 0 << 22 // short load/store coprocessor
+};
+
+
+// -----------------------------------------------------------------------------
+// Machine instruction Operands
+
+// Class Operand represents a shifter operand in data processing instructions
+class Operand BASE_EMBEDDED {
+ public:
+ // immediate
+ INLINE(explicit Operand(int32_t immediate,
+ RelocInfo::Mode rmode = RelocInfo::NONE));
+ INLINE(explicit Operand(const ExternalReference& f));
+ INLINE(explicit Operand(const char* s));
+ INLINE(explicit Operand(Object** opp));
+ INLINE(explicit Operand(Context** cpp));
+ explicit Operand(Handle<Object> handle);
+ INLINE(explicit Operand(Smi* value));
+
+ // rm
+ INLINE(explicit Operand(Register rm));
+
+ // rm <shift_op> shift_imm
+ explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
+
+ // rm <shift_op> rs
+ explicit Operand(Register rm, ShiftOp shift_op, Register rs);
+
+ // Return true if this is a register operand.
+ INLINE(bool is_reg() const);
+
+ Register rm() const { return rm_; }
+
+ private:
+ Register rm_;
+ Register rs_;
+ ShiftOp shift_op_;
+ int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
+ int32_t imm32_; // valid if rm_ == no_reg
+ RelocInfo::Mode rmode_;
+
+ friend class Assembler;
+};
+
+
+// Class MemOperand represents a memory operand in load and store instructions
+class MemOperand BASE_EMBEDDED {
+ public:
+ // [rn +/- offset] Offset/NegOffset
+ // [rn +/- offset]! PreIndex/NegPreIndex
+ // [rn], +/- offset PostIndex/NegPostIndex
+ // offset is any signed 32-bit value; offset is first loaded to register ip if
+ // it does not fit the addressing mode (12-bit unsigned and sign bit)
+ explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
+
+ // [rn +/- rm] Offset/NegOffset
+ // [rn +/- rm]! PreIndex/NegPreIndex
+ // [rn], +/- rm PostIndex/NegPostIndex
+ explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
+
+ // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
+ // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
+ // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
+ explicit MemOperand(Register rn, Register rm,
+ ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
+
+ private:
+ Register rn_; // base
+ Register rm_; // register offset
+ int32_t offset_; // valid if rm_ == no_reg
+ ShiftOp shift_op_;
+ int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
+ AddrMode am_; // bits P, U, and W
+
+ 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) {
+ if (f == VFP3 && !FLAG_enable_vfp3) return false;
+ return (supported_ & (1u << f)) != 0;
+ }
+
+ // Check whether a feature is currently enabled.
+ static bool IsEnabled(CpuFeature f) {
+ return (enabled_ & (1u << f)) != 0;
+ }
+
+ // Enable a specified feature within a scope.
+ class Scope BASE_EMBEDDED {
+#ifdef DEBUG
+ public:
+ explicit Scope(CpuFeature f) {
+ ASSERT(CpuFeatures::IsSupported(f));
+ ASSERT(!Serializer::enabled() ||
+ (found_by_runtime_probing_ & (1u << f)) == 0);
+ old_enabled_ = CpuFeatures::enabled_;
+ CpuFeatures::enabled_ |= 1u << f;
+ }
+ ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
+ private:
+ unsigned old_enabled_;
+#else
+ public:
+ explicit Scope(CpuFeature f) {}
+#endif
+ };
+
+ private:
+ static unsigned supported_;
+ static unsigned enabled_;
+ static unsigned found_by_runtime_probing_;
+};
+
+
+typedef int32_t Instr;
+
+
+extern const Instr kMovLrPc;
+extern const Instr kLdrPCPattern;
+
+
+class Assembler : public Malloced {
+ 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(void* buffer, int buffer_size);
+ ~Assembler();
+
+ // 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
+
+ // 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);
+
+ // Return the address in the constant pool of the code target address used by
+ // the branch/call instruction at pc.
+ INLINE(static Address target_address_address_at(Address pc));
+
+ // 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));
+
+ // This sets the branch destination (which is in the constant pool on ARM).
+ // This is for calls and branches within generated code.
+ inline static void set_target_at(Address constant_pool_entry, Address target);
+
+ // This sets the branch destination (which is in the constant pool on ARM).
+ // This is for calls and branches to runtime code.
+ inline static void set_external_target_at(Address constant_pool_entry,
+ Address target) {
+ set_target_at(constant_pool_entry, target);
+ }
+
+ // Here we are patching the address in the constant pool, not the actual call
+ // instruction. The address in the constant pool is the same size as a
+ // pointer.
+ static const int kCallTargetSize = kPointerSize;
+ static const int kExternalTargetSize = kPointerSize;
+
+ // Size of an instruction.
+ static const int kInstrSize = sizeof(Instr);
+
+ // Distance between the instruction referring to the address of the call
+ // target (ldr pc, [target addr in const pool]) and the return address
+ static const int kCallTargetAddressOffset = kInstrSize;
+
+ // Distance between start of patched return sequence and the emitted address
+ // to jump to.
+ static const int kPatchReturnSequenceAddressOffset = kInstrSize;
+
+ // Difference between address of current opcode and value read from pc
+ // register.
+ static const int kPcLoadDelta = 8;
+
+ static const int kJSReturnSequenceLength = 4;
+
+ // ---------------------------------------------------------------------------
+ // 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);
+
+ // Branch instructions
+ void b(int branch_offset, Condition cond = al);
+ void bl(int branch_offset, Condition cond = al);
+ void blx(int branch_offset); // v5 and above
+ void blx(Register target, Condition cond = al); // v5 and above
+ void bx(Register target, Condition cond = al); // v5 and above, plus v4t
+
+ // Convenience branch instructions using labels
+ void b(Label* L, Condition cond = al) {
+ b(branch_offset(L, cond == al), cond);
+ }
+ void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
+ void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
+ void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
+ void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
+
+ // Data-processing instructions
+ void and_(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void eor(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void sub(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+ void sub(Register dst, Register src1, Register src2,
+ SBit s = LeaveCC, Condition cond = al) {
+ sub(dst, src1, Operand(src2), s, cond);
+ }
+
+ void rsb(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void add(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void adc(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void sbc(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void rsc(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void tst(Register src1, const Operand& src2, Condition cond = al);
+ void tst(Register src1, Register src2, Condition cond = al) {
+ tst(src1, Operand(src2), cond);
+ }
+
+ void teq(Register src1, const Operand& src2, Condition cond = al);
+
+ void cmp(Register src1, const Operand& src2, Condition cond = al);
+ void cmp(Register src1, Register src2, Condition cond = al) {
+ cmp(src1, Operand(src2), cond);
+ }
+
+ void cmn(Register src1, const Operand& src2, Condition cond = al);
+
+ void orr(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+ void orr(Register dst, Register src1, Register src2,
+ SBit s = LeaveCC, Condition cond = al) {
+ orr(dst, src1, Operand(src2), s, cond);
+ }
+
+ void mov(Register dst, const Operand& src,
+ SBit s = LeaveCC, Condition cond = al);
+ void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
+ mov(dst, Operand(src), s, cond);
+ }
+
+ void bic(Register dst, Register src1, const Operand& src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void mvn(Register dst, const Operand& src,
+ SBit s = LeaveCC, Condition cond = al);
+
+ // Multiply instructions
+
+ void mla(Register dst, Register src1, Register src2, Register srcA,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void mul(Register dst, Register src1, Register src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void smlal(Register dstL, Register dstH, Register src1, Register src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void smull(Register dstL, Register dstH, Register src1, Register src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void umlal(Register dstL, Register dstH, Register src1, Register src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ void umull(Register dstL, Register dstH, Register src1, Register src2,
+ SBit s = LeaveCC, Condition cond = al);
+
+ // Miscellaneous arithmetic instructions
+
+ void clz(Register dst, Register src, Condition cond = al); // v5 and above
+
+ // Status register access instructions
+
+ void mrs(Register dst, SRegister s, Condition cond = al);
+ void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
+
+ // Load/Store instructions
+ void ldr(Register dst, const MemOperand& src, Condition cond = al);
+ void str(Register src, const MemOperand& dst, Condition cond = al);
+ void ldrb(Register dst, const MemOperand& src, Condition cond = al);
+ void strb(Register src, const MemOperand& dst, Condition cond = al);
+ void ldrh(Register dst, const MemOperand& src, Condition cond = al);
+ void strh(Register src, const MemOperand& dst, Condition cond = al);
+ void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
+ void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
+
+ // Load/Store multiple instructions
+ void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
+ void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
+
+ // Semaphore instructions
+ void swp(Register dst, Register src, Register base, Condition cond = al);
+ void swpb(Register dst, Register src, Register base, Condition cond = al);
+
+ // Exception-generating instructions and debugging support
+ void stop(const char* msg);
+
+ void bkpt(uint32_t imm16); // v5 and above
+ void swi(uint32_t imm24, Condition cond = al);
+
+ // Coprocessor instructions
+
+ void cdp(Coprocessor coproc, int opcode_1,
+ CRegister crd, CRegister crn, CRegister crm,
+ int opcode_2, Condition cond = al);
+
+ void cdp2(Coprocessor coproc, int opcode_1,
+ CRegister crd, CRegister crn, CRegister crm,
+ int opcode_2); // v5 and above
+
+ void mcr(Coprocessor coproc, int opcode_1,
+ Register rd, CRegister crn, CRegister crm,
+ int opcode_2 = 0, Condition cond = al);
+
+ void mcr2(Coprocessor coproc, int opcode_1,
+ Register rd, CRegister crn, CRegister crm,
+ int opcode_2 = 0); // v5 and above
+
+ void mrc(Coprocessor coproc, int opcode_1,
+ Register rd, CRegister crn, CRegister crm,
+ int opcode_2 = 0, Condition cond = al);
+
+ void mrc2(Coprocessor coproc, int opcode_1,
+ Register rd, CRegister crn, CRegister crm,
+ int opcode_2 = 0); // v5 and above
+
+ void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
+ LFlag l = Short, Condition cond = al);
+ void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
+ LFlag l = Short, Condition cond = al);
+
+ void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
+ LFlag l = Short); // v5 and above
+ void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
+ LFlag l = Short); // v5 and above
+
+ void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
+ LFlag l = Short, Condition cond = al);
+ void stc(Coprocessor coproc, CRegister crd, Register base, int option,
+ LFlag l = Short, Condition cond = al);
+
+ void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
+ LFlag l = Short); // v5 and above
+ void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
+ LFlag l = Short); // v5 and above
+
+ // Support for VFP.
+ // All these APIs support S0 to S31 and D0 to D15.
+ // Currently these APIs do not support extended D registers, i.e, D16 to D31.
+ // However, some simple modifications can allow
+ // these APIs to support D16 to D31.
+
+ void vmov(const DwVfpRegister dst,
+ const Register src1,
+ const Register src2,
+ const Condition cond = al);
+ void vmov(const Register dst1,
+ const Register dst2,
+ const DwVfpRegister src,
+ const Condition cond = al);
+ void vmov(const SwVfpRegister dst,
+ const Register src,
+ const Condition cond = al);
+ void vmov(const Register dst,
+ const SwVfpRegister src,
+ const Condition cond = al);
+ void vcvt(const DwVfpRegister dst,
+ const SwVfpRegister src,
+ const Condition cond = al);
+ void vcvt(const SwVfpRegister dst,
+ const DwVfpRegister src,
+ const Condition cond = al);
+
+ void vadd(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vsub(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vmul(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vdiv(const DwVfpRegister dst,
+ const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const Condition cond = al);
+ void vcmp(const DwVfpRegister src1,
+ const DwVfpRegister src2,
+ const SBit s = LeaveCC,
+ const Condition cond = al);
+ void vmrs(const Register dst,
+ const Condition cond = al);
+
+ // Pseudo instructions
+ void nop() { mov(r0, Operand(r0)); }
+
+ void push(Register src, Condition cond = al) {
+ str(src, MemOperand(sp, 4, NegPreIndex), cond);
+ }
+
+ void pop(Register dst, Condition cond = al) {
+ ldr(dst, MemOperand(sp, 4, PostIndex), cond);
+ }
+
+ void pop() {
+ add(sp, sp, Operand(kPointerSize));
+ }
+
+ // Load effective address of memory operand x into register dst
+ void lea(Register dst, const MemOperand& x,
+ SBit s = LeaveCC, Condition cond = al);
+
+ // Jump unconditionally to given label.
+ void jmp(Label* L) { b(L, al); }
+
+ // Check the code size generated from label to here.
+ int InstructionsGeneratedSince(Label* l) {
+ return (pc_offset() - l->pos()) / kInstrSize;
+ }
+
+ // Check whether an immediate fits an addressing mode 1 instruction.
+ bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
+
+ // Postpone the generation of the constant pool for the specified number of
+ // instructions.
+ void BlockConstPoolFor(int instructions);
+
+ // Debugging
+
+ // Mark address of the ExitJSFrame code.
+ void RecordJSReturn();
+
+ // Record a comment relocation entry that can be used by a disassembler.
+ // Use --debug_code to enable.
+ void RecordComment(const char* msg);
+
+ void RecordPosition(int pos);
+ void RecordStatementPosition(int pos);
+ void WriteRecordedPositions();
+
+ int pc_offset() const { return pc_ - buffer_; }
+ int current_position() const { return current_position_; }
+ int current_statement_position() const { return current_position_; }
+
+ protected:
+ int buffer_space() const { return reloc_info_writer.pos() - pc_; }
+
+ // Read/patch instructions
+ static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
+ void instr_at_put(byte* pc, Instr instr) {
+ *reinterpret_cast<Instr*>(pc) = instr;
+ }
+ 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;
+ }
+
+ // 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);
+
+ // Check if is time to emit a constant pool for pending reloc info entries
+ void CheckConstPool(bool force_emit, bool require_jump);
+
+ // Block the emission of the constant pool before pc_offset
+ void BlockConstPoolBefore(int pc_offset) {
+ if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
+ }
+
+ 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_;
+
+ // Buffer size and constant pool distance are checked together at regular
+ // intervals of kBufferCheckInterval emitted bytes
+ static const int kBufferCheckInterval = 1*KB/2;
+ int next_buffer_check_; // pc offset of next buffer check
+
+ // 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
+
+ // Constant pool generation
+ // Pools are emitted in the instruction stream, preferably after unconditional
+ // jumps or after returns from functions (in dead code locations).
+ // If a long code sequence does not contain unconditional jumps, it is
+ // necessary to emit the constant pool before the pool gets too far from the
+ // location it is accessed from. In this case, we emit a jump over the emitted
+ // constant pool.
+ // Constants in the pool may be addresses of functions that gets relocated;
+ // if so, a relocation info entry is associated to the constant pool entry.
+
+ // Repeated checking whether the constant pool should be emitted is rather
+ // expensive. By default we only check again once a number of instructions
+ // has been generated. That also means that the sizing of the buffers is not
+ // an exact science, and that we rely on some slop to not overrun buffers.
+ static const int kCheckConstIntervalInst = 32;
+ static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
+
+
+ // Pools are emitted after function return and in dead code at (more or less)
+ // regular intervals of kDistBetweenPools bytes
+ static const int kDistBetweenPools = 1*KB;
+
+ // Constants in pools are accessed via pc relative addressing, which can
+ // reach +/-4KB thereby defining a maximum distance between the instruction
+ // and the accessed constant. We satisfy this constraint by limiting the
+ // distance between pools.
+ static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
+
+ // Emission of the constant pool may be blocked in some code sequences
+ int no_const_pool_before_; // block emission before this pc offset
+
+ // Keep track of the last emitted pool to guarantee a maximal distance
+ int last_const_pool_end_; // pc offset following the last constant pool
+
+ // Relocation info generation
+ // Each relocation is encoded as a variable size value
+ static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
+ RelocInfoWriter reloc_info_writer;
+ // Relocation info records are also used during code generation as temporary
+ // containers for constants and code target addresses until they are emitted
+ // to the constant pool. These pending relocation info records are temporarily
+ // stored in a separate buffer until a constant pool is emitted.
+ // If every instruction in a long sequence is accessing the pool, we need one
+ // pending relocation entry per instruction.
+ static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
+ RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info
+ int num_prinfo_; // number of pending reloc info entries in the buffer
+
+ // The bound position, before this we cannot do instruction elimination.
+ int last_bound_pos_;
+
+ // source position information
+ int current_position_;
+ int current_statement_position_;
+ int written_position_;
+ int written_statement_position_;
+
+ // Code emission
+ inline void CheckBuffer();
+ void GrowBuffer();
+ inline void emit(Instr x);
+
+ // Instruction generation
+ void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
+ void addrmod2(Instr instr, Register rd, const MemOperand& x);
+ void addrmod3(Instr instr, Register rd, const MemOperand& x);
+ void addrmod4(Instr instr, Register rn, RegList rl);
+ void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
+
+ // Labels
+ void print(Label* L);