Leon Clarke | 888f672 | 2010-01-27 15:57:47 +0000 | [diff] [blame^] | 1 | // Copyright 2010 the V8 project authors. All rights reserved. |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | |
| 28 | #include "v8.h" |
| 29 | |
| 30 | #include "disassembler.h" |
| 31 | #include "factory.h" |
| 32 | #include "arm/simulator-arm.h" |
| 33 | #include "arm/assembler-arm-inl.h" |
| 34 | #include "cctest.h" |
| 35 | |
| 36 | using namespace v8::internal; |
| 37 | |
| 38 | |
| 39 | // Define these function prototypes to match JSEntryFunction in execution.cc. |
| 40 | typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
| 41 | typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
| 42 | typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); |
| 43 | |
| 44 | |
| 45 | static v8::Persistent<v8::Context> env; |
| 46 | |
| 47 | |
| 48 | // The test framework does not accept flags on the command line, so we set them |
| 49 | static void InitializeVM() { |
| 50 | // disable compilation of natives by specifying an empty natives file |
| 51 | FLAG_natives_file = ""; |
| 52 | |
| 53 | // enable generation of comments |
| 54 | FLAG_debug_code = true; |
| 55 | |
| 56 | if (env.IsEmpty()) { |
| 57 | env = v8::Context::New(); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | |
| 62 | #define __ assm. |
| 63 | |
| 64 | TEST(0) { |
| 65 | InitializeVM(); |
| 66 | v8::HandleScope scope; |
| 67 | |
| 68 | Assembler assm(NULL, 0); |
| 69 | |
| 70 | __ add(r0, r0, Operand(r1)); |
| 71 | __ mov(pc, Operand(lr)); |
| 72 | |
| 73 | CodeDesc desc; |
| 74 | assm.GetCode(&desc); |
| 75 | Object* code = Heap::CreateCode(desc, |
| 76 | NULL, |
| 77 | Code::ComputeFlags(Code::STUB), |
| 78 | Handle<Object>(Heap::undefined_value())); |
| 79 | CHECK(code->IsCode()); |
| 80 | #ifdef DEBUG |
| 81 | Code::cast(code)->Print(); |
| 82 | #endif |
| 83 | F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry()); |
| 84 | int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0)); |
| 85 | ::printf("f() = %d\n", res); |
| 86 | CHECK_EQ(7, res); |
| 87 | } |
| 88 | |
| 89 | |
| 90 | TEST(1) { |
| 91 | InitializeVM(); |
| 92 | v8::HandleScope scope; |
| 93 | |
| 94 | Assembler assm(NULL, 0); |
| 95 | Label L, C; |
| 96 | |
| 97 | __ mov(r1, Operand(r0)); |
| 98 | __ mov(r0, Operand(0)); |
| 99 | __ b(&C); |
| 100 | |
| 101 | __ bind(&L); |
| 102 | __ add(r0, r0, Operand(r1)); |
| 103 | __ sub(r1, r1, Operand(1)); |
| 104 | |
| 105 | __ bind(&C); |
| 106 | __ teq(r1, Operand(0)); |
| 107 | __ b(ne, &L); |
| 108 | __ mov(pc, Operand(lr)); |
| 109 | |
| 110 | CodeDesc desc; |
| 111 | assm.GetCode(&desc); |
| 112 | Object* code = Heap::CreateCode(desc, |
| 113 | NULL, |
| 114 | Code::ComputeFlags(Code::STUB), |
| 115 | Handle<Object>(Heap::undefined_value())); |
| 116 | CHECK(code->IsCode()); |
| 117 | #ifdef DEBUG |
| 118 | Code::cast(code)->Print(); |
| 119 | #endif |
| 120 | F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 121 | int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0)); |
| 122 | ::printf("f() = %d\n", res); |
| 123 | CHECK_EQ(5050, res); |
| 124 | } |
| 125 | |
| 126 | |
| 127 | TEST(2) { |
| 128 | InitializeVM(); |
| 129 | v8::HandleScope scope; |
| 130 | |
| 131 | Assembler assm(NULL, 0); |
| 132 | Label L, C; |
| 133 | |
| 134 | __ mov(r1, Operand(r0)); |
| 135 | __ mov(r0, Operand(1)); |
| 136 | __ b(&C); |
| 137 | |
| 138 | __ bind(&L); |
| 139 | __ mul(r0, r1, r0); |
| 140 | __ sub(r1, r1, Operand(1)); |
| 141 | |
| 142 | __ bind(&C); |
| 143 | __ teq(r1, Operand(0)); |
| 144 | __ b(ne, &L); |
| 145 | __ mov(pc, Operand(lr)); |
| 146 | |
| 147 | // some relocated stuff here, not executed |
| 148 | __ RecordComment("dead code, just testing relocations"); |
| 149 | __ mov(r0, Operand(Factory::true_value())); |
| 150 | __ RecordComment("dead code, just testing immediate operands"); |
| 151 | __ mov(r0, Operand(-1)); |
| 152 | __ mov(r0, Operand(0xFF000000)); |
| 153 | __ mov(r0, Operand(0xF0F0F0F0)); |
| 154 | __ mov(r0, Operand(0xFFF0FFFF)); |
| 155 | |
| 156 | CodeDesc desc; |
| 157 | assm.GetCode(&desc); |
| 158 | Object* code = Heap::CreateCode(desc, |
| 159 | NULL, |
| 160 | Code::ComputeFlags(Code::STUB), |
| 161 | Handle<Object>(Heap::undefined_value())); |
| 162 | CHECK(code->IsCode()); |
| 163 | #ifdef DEBUG |
| 164 | Code::cast(code)->Print(); |
| 165 | #endif |
| 166 | F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 167 | int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0)); |
| 168 | ::printf("f() = %d\n", res); |
| 169 | CHECK_EQ(3628800, res); |
| 170 | } |
| 171 | |
| 172 | |
| 173 | TEST(3) { |
| 174 | InitializeVM(); |
| 175 | v8::HandleScope scope; |
| 176 | |
| 177 | typedef struct { |
| 178 | int i; |
| 179 | char c; |
| 180 | int16_t s; |
| 181 | } T; |
| 182 | T t; |
| 183 | |
| 184 | Assembler assm(NULL, 0); |
| 185 | Label L, C; |
| 186 | |
| 187 | __ mov(ip, Operand(sp)); |
| 188 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 189 | __ sub(fp, ip, Operand(4)); |
| 190 | __ mov(r4, Operand(r0)); |
| 191 | __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i))); |
| 192 | __ mov(r2, Operand(r0, ASR, 1)); |
| 193 | __ str(r2, MemOperand(r4, OFFSET_OF(T, i))); |
| 194 | __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c))); |
| 195 | __ add(r0, r2, Operand(r0)); |
| 196 | __ mov(r2, Operand(r2, LSL, 2)); |
| 197 | __ strb(r2, MemOperand(r4, OFFSET_OF(T, c))); |
| 198 | __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s))); |
| 199 | __ add(r0, r2, Operand(r0)); |
| 200 | __ mov(r2, Operand(r2, ASR, 3)); |
| 201 | __ strh(r2, MemOperand(r4, OFFSET_OF(T, s))); |
| 202 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 203 | |
| 204 | CodeDesc desc; |
| 205 | assm.GetCode(&desc); |
| 206 | Object* code = Heap::CreateCode(desc, |
| 207 | NULL, |
| 208 | Code::ComputeFlags(Code::STUB), |
| 209 | Handle<Object>(Heap::undefined_value())); |
| 210 | CHECK(code->IsCode()); |
| 211 | #ifdef DEBUG |
| 212 | Code::cast(code)->Print(); |
| 213 | #endif |
| 214 | F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 215 | t.i = 100000; |
| 216 | t.c = 10; |
| 217 | t.s = 1000; |
| 218 | int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0)); |
| 219 | ::printf("f() = %d\n", res); |
| 220 | CHECK_EQ(101010, res); |
| 221 | CHECK_EQ(100000/2, t.i); |
| 222 | CHECK_EQ(10*4, t.c); |
| 223 | CHECK_EQ(1000/8, t.s); |
| 224 | } |
| 225 | |
| 226 | |
Leon Clarke | 888f672 | 2010-01-27 15:57:47 +0000 | [diff] [blame^] | 227 | TEST(4) { |
| 228 | // Test the VFP floating point instructions. |
| 229 | InitializeVM(); |
| 230 | v8::HandleScope scope; |
| 231 | |
| 232 | typedef struct { |
| 233 | double a; |
| 234 | double b; |
| 235 | double c; |
| 236 | } T; |
| 237 | T t; |
| 238 | |
| 239 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 240 | // the doubles t.a, t.b, and t.c. |
| 241 | Assembler assm(NULL, 0); |
| 242 | Label L, C; |
| 243 | |
| 244 | |
| 245 | if (CpuFeatures::IsSupported(VFP3)) { |
| 246 | CpuFeatures::Scope scope(VFP3); |
| 247 | |
| 248 | __ mov(ip, Operand(sp)); |
| 249 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 250 | __ sub(fp, ip, Operand(4)); |
| 251 | |
| 252 | __ mov(r4, Operand(r0)); |
| 253 | __ vldr(d6, r4, OFFSET_OF(T, a)); |
| 254 | __ vldr(d7, r4, OFFSET_OF(T, b)); |
| 255 | __ vadd(d5, d6, d7); |
| 256 | __ vstr(d5, r4, OFFSET_OF(T, c)); |
| 257 | |
| 258 | __ vmov(r2, r3, d5); |
| 259 | __ vmov(d4, r2, r3); |
| 260 | __ vstr(d4, r4, OFFSET_OF(T, b)); |
| 261 | |
| 262 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 263 | |
| 264 | CodeDesc desc; |
| 265 | assm.GetCode(&desc); |
| 266 | Object* code = Heap::CreateCode(desc, |
| 267 | NULL, |
| 268 | Code::ComputeFlags(Code::STUB), |
| 269 | Handle<Object>(Heap::undefined_value())); |
| 270 | CHECK(code->IsCode()); |
| 271 | #ifdef DEBUG |
| 272 | Code::cast(code)->Print(); |
| 273 | #endif |
| 274 | F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 275 | t.a = 1.5; |
| 276 | t.b = 2.75; |
| 277 | t.c = 17.17; |
| 278 | Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 279 | USE(dummy); |
| 280 | CHECK_EQ(4.25, t.c); |
| 281 | CHECK_EQ(4.25, t.b); |
| 282 | CHECK_EQ(1.5, t.a); |
| 283 | } |
| 284 | } |
| 285 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 286 | #undef __ |