1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * Test arithmetic operations. 19 */ 20 public class IntMath { 21 22 static void shiftTest1() { 23 System.out.println("IntMath.shiftTest1"); 24 25 final int[] mBytes = { 26 0x11, 0x22, 0x33, 0x44, 0x88, 0x99, 0xaa, 0xbb 27 }; 28 long l; 29 int i1, i2; 30 31 i1 = mBytes[0] | mBytes[1] << 8 | mBytes[2] << 16 | mBytes[3] << 24; 32 i2 = mBytes[4] | mBytes[5] << 8 | mBytes[6] << 16 | mBytes[7] << 24; 33 l = i1 | ((long)i2 << 32); 34 35 Main.assertTrue(i1 == 0x44332211); 36 Main.assertTrue(i2 == 0xbbaa9988); 37 Main.assertTrue(l == 0xbbaa998844332211L); 38 39 l = (long)mBytes[0] 40 | (long)mBytes[1] << 8 41 | (long)mBytes[2] << 16 42 | (long)mBytes[3] << 24 43 | (long)mBytes[4] << 32 44 | (long)mBytes[5] << 40 45 | (long)mBytes[6] << 48 46 | (long)mBytes[7] << 56; 47 48 Main.assertTrue(l == 0xbbaa998844332211L); 49 } 50 51 static void shiftTest2() { 52 System.out.println("IntMath.shiftTest2"); 53 54 long a = 0x11; 55 long b = 0x22; 56 long c = 0x33; 57 long d = 0x44; 58 long e = 0x55; 59 long f = 0x66; 60 long g = 0x77; 61 long h = 0x88; 62 63 long result = ((a << 56) | (b << 48) | (c << 40) | (d << 32) | 64 (e << 24) | (f << 16) | (g << 8) | h); 65 66 Main.assertTrue(result == 0x1122334455667788L); 67 } 68 69 static void unsignedShiftTest() { 70 System.out.println("IntMath.unsignedShiftTest"); 71 72 byte b = -4; 73 short s = -4; 74 char c = 0xfffc; 75 int i = -4; 76 77 b >>>= 4; 78 s >>>= 4; 79 c >>>= 4; 80 i >>>= 4; 81 82 Main.assertTrue((int) b == -1); 83 Main.assertTrue((int) s == -1); 84 Main.assertTrue((int) c == 0x0fff); 85 Main.assertTrue(i == 268435455); 86 } 87 88 static void shiftTest3(int thirtyTwo) { 89 System.out.println("IntMath.shiftTest3"); 90 91 int one = thirtyTwo / 32; 92 int sixteen = thirtyTwo / 2; 93 int thirtyThree = thirtyTwo + 1; 94 int sixtyFour = thirtyTwo * 2; 95 96 Main.assertTrue(1 << thirtyTwo == 1); 97 Main.assertTrue((1 << sixteen) << sixteen == 0); 98 Main.assertTrue(1 << thirtyThree == 2); 99 Main.assertTrue(1 << -one == -2147483648); 100 Main.assertTrue(1 << -thirtyTwo == 1); 101 Main.assertTrue(1 << -thirtyThree == -2147483648); 102 Main.assertTrue(1 << thirtyThree == 2); 103 104 Main.assertTrue(1 >> thirtyTwo == 1); 105 Main.assertTrue((1 >> sixteen) >> sixteen == 0); 106 Main.assertTrue(1 >> thirtyThree == 0); 107 Main.assertTrue(1 >> -one == 0); 108 Main.assertTrue(1 >> -thirtyTwo == 1); 109 Main.assertTrue(1 >> -thirtyThree == 0); 110 Main.assertTrue(-4 >> thirtyThree == -2); 111 112 Main.assertTrue(1 >>> thirtyTwo == 1); 113 Main.assertTrue((1 >>> sixteen) >>> sixteen == 0); 114 Main.assertTrue(1 >>> thirtyThree == 0); 115 Main.assertTrue(1 >>> -one == 0); 116 Main.assertTrue(1 >>> -thirtyTwo == 1); 117 Main.assertTrue(1 >>> -thirtyThree == 0); 118 Main.assertTrue(-4 >>> thirtyThree == 2147483646); 119 } 120 121 static void convTest() { 122 System.out.println("IntMath.convTest"); 123 124 float f; 125 double d; 126 int i; 127 long l; 128 129 /* int --> long */ 130 i = 7654; 131 l = (long) i; 132 Main.assertTrue(l == 7654L); 133 134 i = -7654; 135 l = (long) i; 136 Main.assertTrue(l == -7654L); 137 138 /* long --> int (with truncation) */ 139 l = 5678956789L; 140 i = (int) l; 141 Main.assertTrue(i == 1383989493); 142 143 l = -5678956789L; 144 i = (int) l; 145 Main.assertTrue(i == -1383989493); 146 } 147 148 static void charSubTest() { 149 System.out.println("IntMath.charSubTest"); 150 151 char char1 = 0x00e9; 152 char char2 = 0xffff; 153 int i; 154 155 /* chars are unsigned-expanded to ints before subtraction */ 156 i = char1 - char2; 157 Main.assertTrue(i == 0xffff00ea); 158 } 159 160 /* 161 * We pass in the arguments and return the results so the compiler 162 * doesn't do the math for us. (x=70000, y=-3) 163 */ 164 static int[] intOperTest(int x, int y) { 165 System.out.println("IntMath.intOperTest"); 166 167 int[] results = new int[10]; 168 169 /* this seems to generate "op-int" instructions */ 170 results[0] = x + y; 171 results[1] = x - y; 172 results[2] = x * y; 173 results[3] = x * x; 174 results[4] = x / y; 175 results[5] = x % -y; 176 results[6] = x & y; 177 results[7] = x | y; 178 results[8] = x ^ y; 179 180 /* this seems to generate "op-int/2addr" instructions */ 181 results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y); 182 183 return results; 184 } 185 static void intOperCheck(int[] results) { 186 System.out.println("IntMath.intOperCheck"); 187 188 /* check this edge case while we're here (div-int/2addr) */ 189 int minInt = -2147483648; 190 int negOne = -results[5]; 191 int plusOne = 1; 192 int result = (((minInt + plusOne) - plusOne) / negOne) / negOne; 193 Main.assertTrue(result == minInt); 194 195 Main.assertTrue(results[0] == 69997); 196 Main.assertTrue(results[1] == 70003); 197 Main.assertTrue(results[2] == -210000); 198 Main.assertTrue(results[3] == 605032704); // overflow / truncate 199 Main.assertTrue(results[4] == -23333); 200 Main.assertTrue(results[5] == 1); 201 Main.assertTrue(results[6] == 70000); 202 Main.assertTrue(results[7] == -3); 203 Main.assertTrue(results[8] == -70003); 204 Main.assertTrue(results[9] == 70000); 205 } 206 207 /* 208 * More operations, this time with 16-bit constants. (x=77777) 209 */ 210 static int[] lit16Test(int x) { 211 System.out.println("IntMath.lit16Test"); 212 213 int[] results = new int[8]; 214 215 /* try to generate op-int/lit16" instructions */ 216 results[0] = x + 1000; 217 results[1] = 1000 - x; 218 results[2] = x * 1000; 219 results[3] = x / 1000; 220 results[4] = x % 1000; 221 results[5] = x & 1000; 222 results[6] = x | -1000; 223 results[7] = x ^ -1000; 224 return results; 225 } 226 static void lit16Check(int[] results) { 227 Main.assertTrue(results[0] == 78777); 228 Main.assertTrue(results[1] == -76777); 229 Main.assertTrue(results[2] == 77777000); 230 Main.assertTrue(results[3] == 77); 231 Main.assertTrue(results[4] == 777); 232 Main.assertTrue(results[5] == 960); 233 Main.assertTrue(results[6] == -39); 234 Main.assertTrue(results[7] == -76855); 235 } 236 237 /* 238 * More operations, this time with 8-bit constants. (x=-55555) 239 */ 240 static int[] lit8Test(int x) { 241 System.out.println("IntMath.lit8Test"); 242 243 int[] results = new int[8]; 244 245 /* try to generate op-int/lit8" instructions */ 246 results[0] = x + 10; 247 results[1] = 10 - x; 248 results[2] = x * 10; 249 results[3] = x / 10; 250 results[4] = x % 10; 251 results[5] = x & 10; 252 results[6] = x | -10; 253 results[7] = x ^ -10; 254 return results; 255 } 256 static void lit8Check(int[] results) { 257 //for (int i = 0; i < results.length; i++) 258 // System.out.println(" " + i + ": " + results[i]); 259 260 /* check this edge case while we're here (div-int/lit8) */ 261 int minInt = -2147483648; 262 int result = minInt / -1; 263 Main.assertTrue(result == minInt); 264 265 Main.assertTrue(results[0] == -55545); 266 Main.assertTrue(results[1] == 55565); 267 Main.assertTrue(results[2] == -555550); 268 Main.assertTrue(results[3] == -5555); 269 Main.assertTrue(results[4] == -5); 270 Main.assertTrue(results[5] == 8); 271 Main.assertTrue(results[6] == -1); 272 Main.assertTrue(results[7] == 55563); 273 } 274 275 /* 276 * Make sure special-cased literal division matches 277 * normal division. 278 */ 279 static void divLiteralTestBody(int start, int count) { 280 int normal = 0; 281 int special = 0; 282 for (int i = 0; i < count; i++) { 283 for (int j = 3; j < 16; j++) { 284 switch(j) { 285 case 3: 286 normal = (start+i) / j; 287 special = (start+i) / 3; 288 break; 289 case 4: 290 normal = (start+i) / j; 291 special = (start+i) / 4; 292 break; 293 case 5: 294 normal = (start+i) / j; 295 special = (start+i) / 5; 296 break; 297 case 6: 298 normal = (start+i) / j; 299 special = (start+i) / 6; 300 break; 301 case 7: 302 normal = (start+i) / j; 303 special = (start+i) / 7; 304 break; 305 case 8: 306 normal = (start+i) / j; 307 special = (start+i) / 8; 308 break; 309 case 9: 310 normal = (start+i) / j; 311 special = (start+i) / 9; 312 break; 313 case 10: 314 normal = (start+i) / j; 315 special = (start+i) / 10; 316 break; 317 case 11: 318 normal = (start+i) / j; 319 special = (start+i) / 11; 320 break; 321 case 12: 322 normal = (start+i) / j; 323 special = (start+i) / 12; 324 break; 325 case 13: 326 normal = (start+i) / j; 327 special = (start+i) / 13; 328 break; 329 case 14: 330 normal = (start+i) / j; 331 special = (start+i) / 14; 332 break; 333 case 15: 334 normal = (start+i) / j; 335 special = (start+i) / 15; 336 break; 337 } 338 Main.assertTrue(normal == special); 339 } 340 } 341 } 342 343 static void divLiteralTest() { 344 System.out.println("IntMath.divLiteralTest"); 345 divLiteralTestBody(-1000, 2000); 346 divLiteralTestBody(0x7fffffff-2000, 2000); 347 divLiteralTestBody(0xfff0ffff, 2000); 348 } 349 350 /* 351 * Shift some data. (value=0xff00aa01, dist=8) 352 */ 353 static int[] intShiftTest(int value, int dist) { 354 System.out.println("IntMath.intShiftTest"); 355 356 int results[] = new int[4]; 357 358 results[0] = value << dist; 359 results[1] = value >> dist; 360 results[2] = value >>> dist; 361 362 results[3] = (((value << dist) >> dist) >>> dist) << dist; 363 return results; 364 } 365 static void intShiftCheck(int[] results) { 366 System.out.println("IntMath.intShiftCheck"); 367 368 Main.assertTrue(results[0] == 0x00aa0100); 369 Main.assertTrue(results[1] == 0xffff00aa); 370 Main.assertTrue(results[2] == 0x00ff00aa); 371 Main.assertTrue(results[3] == 0xaa00); 372 } 373 374 /* 375 * We pass in the arguments and return the results so the compiler 376 * doesn't do the math for us. (x=70000000000, y=-3) 377 */ 378 static long[] longOperTest(long x, long y) { 379 System.out.println("IntMath.longOperTest"); 380 381 long[] results = new long[10]; 382 383 /* this seems to generate "op-long" instructions */ 384 results[0] = x + y; 385 results[1] = x - y; 386 results[2] = x * y; 387 results[3] = x * x; 388 results[4] = x / y; 389 results[5] = x % -y; 390 results[6] = x & y; 391 results[7] = x | y; 392 results[8] = x ^ y; 393 394 /* this seems to generate "op-long/2addr" instructions */ 395 results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y); 396 397 return results; 398 } 399 static void longOperCheck(long[] results) { 400 System.out.println("IntMath.longOperCheck"); 401 402 /* check this edge case while we're here (div-long/2addr) */ 403 long minLong = -9223372036854775808L; 404 long negOne = -results[5]; 405 long plusOne = 1; 406 long result = (((minLong + plusOne) - plusOne) / negOne) / negOne; 407 Main.assertTrue(result == minLong); 408 409 Main.assertTrue(results[0] == 69999999997L); 410 Main.assertTrue(results[1] == 70000000003L); 411 Main.assertTrue(results[2] == -210000000000L); 412 Main.assertTrue(results[3] == -6833923606740729856L); // overflow 413 Main.assertTrue(results[4] == -23333333333L); 414 Main.assertTrue(results[5] == 1); 415 Main.assertTrue(results[6] == 70000000000L); 416 Main.assertTrue(results[7] == -3); 417 Main.assertTrue(results[8] == -70000000003L); 418 Main.assertTrue(results[9] == 70000000000L); 419 420 Main.assertTrue(results.length == 10); 421 } 422 423 /* 424 * Shift some data. (value=0xd5aa96deff00aa01, dist=8) 425 */ 426 static long[] longShiftTest(long value, int dist) { 427 System.out.println("IntMath.longShiftTest"); 428 429 long results[] = new long[4]; 430 431 results[0] = value << dist; 432 results[1] = value >> dist; 433 results[2] = value >>> dist; 434 435 results[3] = (((value << dist) >> dist) >>> dist) << dist; 436 return results; 437 } 438 static long longShiftCheck(long[] results) { 439 System.out.println("IntMath.longShiftCheck"); 440 441 Main.assertTrue(results[0] == 0x96deff00aa010000L); 442 Main.assertTrue(results[1] == 0xffffd5aa96deff00L); 443 Main.assertTrue(results[2] == 0x0000d5aa96deff00L); 444 Main.assertTrue(results[3] == 0xffff96deff000000L); 445 446 Main.assertTrue(results.length == 4); 447 448 return results[0]; // test return-long 449 } 450 451 452 /* 453 * Try to cause some unary operations. 454 */ 455 static int unopTest(int x) { 456 x = -x; 457 x ^= 0xffffffff; 458 return x; 459 } 460 static void unopCheck(int result) { 461 Main.assertTrue(result == 37); 462 } 463 464 static class Shorty { 465 public short mShort; 466 public char mChar; 467 public byte mByte; 468 }; 469 470 /* 471 * Truncate an int. 472 */ 473 static Shorty truncateTest(int x) { 474 System.out.println("IntMath.truncateTest"); 475 Shorty shorts = new Shorty(); 476 477 shorts.mShort = (short) x; 478 shorts.mChar = (char) x; 479 shorts.mByte = (byte) x; 480 return shorts; 481 } 482 static void truncateCheck(Shorty shorts) { 483 Main.assertTrue(shorts.mShort == -5597); // 0xea23 484 Main.assertTrue(shorts.mChar == 59939); // 0xea23 485 Main.assertTrue(shorts.mByte == 35); // 0x23 486 } 487 488 /* 489 * Verify that we get a divide-by-zero exception. 490 */ 491 static void divideByZero(int z) { 492 System.out.println("IntMath.divideByZero"); 493 494 try { 495 int x = 100 / z; 496 Main.assertTrue(false); 497 } catch (ArithmeticException ae) { 498 } 499 500 try { 501 int x = 100 % z; 502 Main.assertTrue(false); 503 } catch (ArithmeticException ae) { 504 } 505 506 try { 507 long x = 100L / z; 508 Main.assertTrue(false); 509 } catch (ArithmeticException ae) { 510 } 511 512 try { 513 long x = 100L % z; 514 Main.assertTrue(false); 515 } catch (ArithmeticException ae) { 516 } 517 } 518 519 /* 520 * Check an edge condition: dividing the most-negative integer by -1 521 * returns the most-negative integer, and doesn't cause an exception. 522 * 523 * Pass in -1, -1L. 524 */ 525 static void bigDivideOverflow(int idiv, long ldiv) { 526 System.out.println("IntMath.bigDivideOverflow"); 527 int mostNegInt = (int) 0x80000000; 528 long mostNegLong = (long) 0x8000000000000000L; 529 530 int intDivResult = mostNegInt / idiv; 531 int intModResult = mostNegInt % idiv; 532 long longDivResult = mostNegLong / ldiv; 533 long longModResult = mostNegLong % ldiv; 534 535 Main.assertTrue(intDivResult == mostNegInt); 536 Main.assertTrue(intModResult == 0); 537 Main.assertTrue(longDivResult == mostNegLong); 538 Main.assertTrue(longModResult == 0); 539 } 540 541 /* 542 * Check "const" instructions. We use negative values to ensure that 543 * sign-extension is happening. 544 */ 545 static void checkConsts(byte small, short medium, int large, long huge) { 546 System.out.println("IntMath.checkConsts"); 547 548 Main.assertTrue(small == 1); // const/4 549 Main.assertTrue(medium == -256); // const/16 550 Main.assertTrue(medium == -256L); // const-wide/16 551 Main.assertTrue(large == -88888); // const 552 Main.assertTrue(large == -88888L); // const-wide/32 553 Main.assertTrue(huge == 0x9922334455667788L); // const-wide 554 } 555 556 /* 557 * Test some java.lang.Math functions. 558 * 559 * The method arguments are positive values. 560 */ 561 static void jlmTests(int ii, long ll) { 562 System.out.println("IntMath.jlmTests"); 563 564 Main.assertTrue(Math.abs(ii) == ii); 565 Main.assertTrue(Math.abs(-ii) == ii); 566 Main.assertTrue(Math.min(ii, -5) == -5); 567 Main.assertTrue(Math.max(ii, -5) == ii); 568 569 Main.assertTrue(Math.abs(ll) == ll); 570 Main.assertTrue(Math.abs(-ll) == ll); 571 Main.assertTrue(Math.min(ll, -5L) == -5L); 572 Main.assertTrue(Math.max(ll, -5L) == ll); 573 } 574 575 public static void run() { 576 shiftTest1(); 577 shiftTest2(); 578 unsignedShiftTest(); 579 shiftTest3(32); 580 convTest(); 581 charSubTest(); 582 583 int[] intResults; 584 long[] longResults; 585 586 intResults = intOperTest(70000, -3); 587 intOperCheck(intResults); 588 longResults = longOperTest(70000000000L, -3L); 589 longOperCheck(longResults); 590 591 intResults = lit16Test(77777); 592 lit16Check(intResults); 593 intResults = lit8Test(-55555); 594 lit8Check(intResults); 595 divLiteralTest(); 596 597 intResults = intShiftTest(0xff00aa01, 8); 598 intShiftCheck(intResults); 599 longResults = longShiftTest(0xd5aa96deff00aa01L, 16); 600 long longRet = longShiftCheck(longResults); 601 Main.assertTrue(longRet == 0x96deff00aa010000L); 602 603 Shorty shorts = truncateTest(-16717277); // 0xff00ea23 604 truncateCheck(shorts); 605 606 divideByZero(0); 607 bigDivideOverflow(-1, -1L); 608 609 checkConsts((byte) 1, (short) -256, -88888, 0x9922334455667788L); 610 611 unopCheck(unopTest(38)); 612 613 jlmTests(12345, 0x1122334455667788L); 614 } 615 } 616