├── .classpath ├── .gitignore ├── .project ├── README.md ├── java-binutils-0.1.0.jar └── src ├── main └── java │ └── nl │ └── lxtreme │ └── arm │ ├── Arm.java │ ├── ConditionCode.java │ └── memory │ ├── Chunk.java │ └── Memory.java └── test ├── java └── nl │ └── lxtreme │ └── arm │ ├── ArmShiftTest.java │ ├── ArmTest.java │ ├── CpsrTest.java │ └── memory │ ├── ChunkTest.java │ └── MemoryTest.java └── resources ├── arm7tdmi_Blinky_iFlash.hex ├── blinkingLEDAndButton.hex ├── blinking_leds.hex ├── helloWorld_loop ├── helloWorld_static ├── led.hex ├── miniBench_neon └── rtcAndInterruptExample.hex /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | target 3 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | ARM-core 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ARM-core 2 | 3 | A *very* small ARM9 simulator project written in Java. 4 | 5 | ## Why? 6 | 7 | Why not! It is fun to emulate something in any language, if speed isn't a 8 | real deal. 9 | 10 | ## Status 11 | 12 | It does something, but is nowhere finished... 13 | 14 | ## License 15 | 16 | None yet, consider it publicware. 17 | 18 | ## Author 19 | 20 | Code written by J.W. Janssen. Inspired on code of waninkoko, see 21 | . 22 | 23 | -------------------------------------------------------------------------------- /java-binutils-0.1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jawi/java-ARM-core/c0610cf907ff6358d04c53e55320abe3a9e3d4d7/java-binutils-0.1.0.jar -------------------------------------------------------------------------------- /src/main/java/nl/lxtreme/arm/Arm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm; 7 | 8 | 9 | import java.util.*; 10 | 11 | import nl.lxtreme.arm.memory.*; 12 | 13 | 14 | /** 15 | * Provides a simplistic version of an ARM-core. 16 | */ 17 | public class Arm 18 | { 19 | // INNER TYPES 20 | 21 | /** 22 | * Denotes the "Current Program Status Register" (CPSR). 23 | */ 24 | static class Cpsr 25 | { 26 | // VARIABLES 27 | 28 | boolean n; // 31 29 | boolean z; // 30 30 | boolean c; // 29 31 | boolean v; // 28 32 | boolean q; // 27 33 | 34 | int it; // 26, 25 & 15..10 35 | 36 | boolean j; // 24 37 | 38 | // padding 23..20 39 | 40 | int ge; // 19..16 41 | 42 | boolean E; // 9 43 | boolean A; // 8 44 | boolean I; // 7 45 | boolean F; // 6 46 | boolean t; // 5 47 | 48 | // 5-bits mode 49 | 50 | int mode; // 4..0 51 | 52 | // METHODS 53 | 54 | /** 55 | * Returns the value of the CPSR as 32-bit value. 56 | * 57 | * @return a 32-bit value representation of the CPSR. 58 | */ 59 | int getValue() 60 | { 61 | long result = 0; 62 | result |= (this.n ? (1L << 31) : 0); 63 | result |= (this.z ? (1L << 30) : 0); 64 | result |= (this.c ? (1L << 29) : 0); 65 | result |= (this.v ? (1L << 28) : 0); 66 | result |= (this.q ? (1L << 27) : 0); 67 | result |= ((this.it & 0x03) << 25); 68 | result |= (this.j ? (1L << 24) : 0); 69 | result |= ((this.ge & 0x0F) << 16); 70 | result |= ((this.it & 0xFC) << 8); 71 | result |= (this.E ? (1L << 9) : 0); 72 | result |= (this.A ? (1L << 8) : 0); 73 | result |= (this.I ? (1L << 7) : 0); 74 | result |= (this.F ? (1L << 6) : 0); 75 | result |= (this.t ? (1L << 5) : 0); 76 | result |= (this.mode & 0x1F); 77 | return (int) (result & 0xFFFFFFFF); 78 | } 79 | 80 | /** 81 | * Sets this CPSR by means of a 32-bit value. 82 | * 83 | * @param aValue 84 | * the 32-bit representation of the CPSR to set. 85 | */ 86 | void setValue(int aValue) 87 | { 88 | long value = aValue; 89 | this.n = (value & (1L << 31)) != 0; 90 | this.z = (value & (1L << 30)) != 0; 91 | this.c = (value & (1L << 29)) != 0; 92 | this.v = (value & (1L << 28)) != 0; 93 | this.q = (value & (1L << 27)) != 0; 94 | this.it = (int) (((value >> 8) & 0xFC) | ((value >> 25) & 0x03)); 95 | this.j = (value & (1L << 24)) != 0; 96 | this.ge = (int) ((value >> 16) & 0x0F); 97 | this.E = (value & (1L << 9)) != 0; 98 | this.A = (value & (1L << 8)) != 0; 99 | this.I = (value & (1L << 7)) != 0; 100 | this.F = (value & (1L << 6)) != 0; 101 | this.t = (value & (1L << 5)) != 0; 102 | this.mode = (int) (value & 0x1f); 103 | } 104 | } 105 | 106 | // VARIABLES 107 | 108 | private final int[] r; 109 | private final Cpsr cpsr; 110 | private int spsr; 111 | 112 | private boolean finished; 113 | private int entryPoint; // initial PC value 114 | 115 | private final List breakpoints; 116 | private final Memory memory; 117 | 118 | // CONSTRUCTORS 119 | 120 | /** 121 | * Creates a new Arm instance. 122 | * 123 | * @param aMemory 124 | * the memory to use in the processor. 125 | */ 126 | public Arm(Memory aMemory) 127 | { 128 | this.r = new int[16]; 129 | this.cpsr = new Cpsr(); 130 | 131 | this.memory = aMemory; 132 | this.breakpoints = new ArrayList(32); 133 | this.entryPoint = 0; 134 | } 135 | 136 | // METHODS 137 | 138 | /** 139 | * Arithmetic Shift Right (ASR) moves each bit of a bitstring (x) right by a 140 | * specified number of bits (y). Copies of the leftmost bit are shifted in at 141 | * the left end of the bitstring. Bits that are shifted off the right end of 142 | * the bitstring are discarded, except that the last such bit can be produced 143 | * as a carry output. 144 | * 145 | * @param x 146 | * the bitstring to shift; 147 | * @param y 148 | * the number of bits to shift. 149 | * @return the bitshifted bitstring. 150 | */ 151 | static int ASR(int x, int y) 152 | { 153 | return (x >> y); 154 | } 155 | 156 | /** 157 | * Logical Shift Left (LSL) moves each bit of a bitstring (x) left by a 158 | * specified number of bits (y). Zeros are shifted in at the right end of the 159 | * bitstring. Bits that are shifted off the left end of the bitstring are 160 | * discarded, except that the last such bit can be produced as a carry output. 161 | * 162 | * @param x 163 | * the bitstring to shift; 164 | * @param y 165 | * the number of bits to shift. 166 | * @return the bitshifted bitstring. 167 | */ 168 | static int LSL(int x, int y) 169 | { 170 | return (x << y); 171 | } 172 | 173 | /** 174 | * Logical Shift Right (LSR) moves each bit of a bitstring (x) right by a 175 | * specified number of bits (y). Zeros are shifted in at the left end of the 176 | * bitstring. Bits that are shifted off the right end of the bitstring are 177 | * discarded, except that the last such bit can be produced as a carry output. 178 | * 179 | * @param x 180 | * the bitstring to shift; 181 | * @param y 182 | * the number of bits to shift. 183 | * @return the bitshifted bitstring. 184 | */ 185 | static int LSR(int x, int y) 186 | { 187 | return (x >>> y); 188 | } 189 | 190 | /** 191 | * Rotate Right (ROR) moves each bit of a bitstring (x) right by a specified 192 | * number of bits (y). Each bit that is shifted off the right end of the 193 | * bitstring is re-introduced at the left end. The last bit shifted off the 194 | * right end of the bitstring can be produced as a carry output. 195 | * 196 | * @param x 197 | * the bitstring to shift; 198 | * @param y 199 | * the number of bits to shift. 200 | * @return the bitshifted bitstring. 201 | */ 202 | static int ROR(int x, int y) 203 | { 204 | return ((x >>> y) | (x << (32 - y))); 205 | } 206 | 207 | /** 208 | * Rotate Right with Extend (RRX) moves each bit of a bitstring (x) right by 209 | * one bit. The carry input (c) is shifted in at the left end of the 210 | * bitstring. The bit shifted off the right end of the bitstring can be 211 | * produced as a carry output. 212 | * 213 | * @param x 214 | * the bitstring to shift; 215 | * @param c 216 | * the carry bit. 217 | * @return the bitshifted bitstring. 218 | */ 219 | static int RRX(int x, int c) 220 | { 221 | return ((x >>> 1) | ((c & 0x01) << 31)); 222 | } 223 | 224 | /** 225 | * Add breakpoint 226 | * 227 | * @param address 228 | */ 229 | public void breakAdd(int address) 230 | { 231 | if (!breakFind(address)) 232 | { 233 | this.breakpoints.add(address); 234 | } 235 | } 236 | 237 | /** 238 | * @param address 239 | */ 240 | public void breakDel(int address) 241 | { 242 | Iterator iter = this.breakpoints.iterator(); 243 | while (iter.hasNext()) 244 | { 245 | Integer addr = iter.next(); 246 | if ((addr != null) && (addr.intValue() == address)) 247 | { 248 | iter.remove(); 249 | break; 250 | } 251 | } 252 | } 253 | 254 | /** 255 | * @param address 256 | * @return 257 | */ 258 | public boolean breakFind(int address) 259 | { 260 | Iterator iter = this.breakpoints.iterator(); 261 | while (iter.hasNext()) 262 | { 263 | Integer addr = iter.next(); 264 | if ((addr != null) && (addr.intValue() == address)) 265 | { 266 | return true; 267 | } 268 | } 269 | return false; 270 | } 271 | 272 | /** 273 | * 274 | */ 275 | public void dumpRegs() 276 | { 277 | System.out.println("REGISTERS DUMP:"); 278 | System.out.println("==============="); 279 | 280 | /* Print GPRs */ 281 | for (int i = 0; i < 16; i += 2) 282 | { 283 | System.out.printf("r%-2d: 0x%08X\t\tr%-2d: 0x%08X\n", i, this.r[i], i + 1, this.r[i + 1]); 284 | } 285 | 286 | System.out.println(); 287 | 288 | /* Print CPSR */ 289 | System.out.printf("cpsr: 0x%x\n", this.cpsr.getValue()); 290 | System.out.println(" (z: " + this.cpsr.z + ", n: " + this.cpsr.n + ", c: " + this.cpsr.c + ", v: " + this.cpsr.v 291 | + ", I: " + this.cpsr.I + ", F: " + this.cpsr.F + ", t: " + this.cpsr.t + ", mode: " + this.cpsr.mode + ")"); 292 | 293 | /* Print SPSR */ 294 | System.out.printf("spsr: 0x%x\n", this.spsr); 295 | } 296 | 297 | /** 298 | * @param count 299 | */ 300 | public void dumpStack(int count) 301 | { 302 | System.out.println("STACK DUMP:"); 303 | System.out.println("==========="); 304 | 305 | /* Print stack */ 306 | for (int i = 0; i < count; i++) 307 | { 308 | int addr = this.r[13] + (i << 2); 309 | int value; 310 | 311 | /* Read stack */ 312 | value = this.memory.read32(addr); 313 | 314 | /* Print value */ 315 | System.out.printf("[%02d] 0x%08X\n", i, value); 316 | } 317 | } 318 | 319 | /** 320 | * @param idx 321 | * @return 322 | */ 323 | public int peekReg(int idx) 324 | { 325 | return this.r[idx]; 326 | } 327 | 328 | /** 329 | * @param idx 330 | * @param val 331 | */ 332 | public void pokeReg(int idx, int val) 333 | { 334 | this.r[idx] = val; 335 | } 336 | 337 | /** 338 | * Resets this CPU. 339 | */ 340 | public void reset() 341 | { 342 | Arrays.fill(this.r, 0); 343 | this.r[15] = this.entryPoint; 344 | this.cpsr.setValue(this.spsr = 0); 345 | this.finished = false; 346 | } 347 | 348 | /** 349 | * @param val 350 | */ 351 | public void setPC(int val) 352 | { 353 | this.r[15] = this.entryPoint = val; 354 | } 355 | 356 | /** 357 | * Steps through the instructions. 358 | * 359 | * @return true if a new instruction is available, 360 | * false otherwise. 361 | */ 362 | public boolean step() 363 | { 364 | boolean ret; 365 | 366 | /* Check finish flag */ 367 | if (this.finished) 368 | { 369 | System.out.printf("FINISHED! (return: %d)", this.r[0]); 370 | return false; 371 | } 372 | 373 | /* Remove thumb bit */ 374 | int pc = this.r[15] & ~1; 375 | 376 | /* Check breakpoint */ 377 | ret = breakFind(pc); 378 | if (ret) 379 | { 380 | System.out.printf("BREAKPOINT! (0x%x)\n", pc); 381 | return false; 382 | } 383 | 384 | /* Parse instruction */ 385 | if (this.cpsr.t) 386 | { 387 | parseThumb(); 388 | } 389 | else 390 | { 391 | parse(); 392 | } 393 | 394 | return true; 395 | } 396 | 397 | /** 398 | * 32-bit values. 399 | * 400 | * @param a 401 | * @param b 402 | * @return 403 | */ 404 | protected int addition(int a, int b) 405 | { 406 | /* Add values */ 407 | int result = a + b; 408 | 409 | /* Set flags */ 410 | this.cpsr.c = carryFrom(a, b); 411 | this.cpsr.v = overflowFrom(a, b); 412 | this.cpsr.z = result == 0; 413 | this.cpsr.n = ((result >> 31) != 0); 414 | 415 | return result; 416 | } 417 | 418 | /** 419 | * 32-bit values. 420 | * 421 | * @param a 422 | * @param b 423 | * @return 424 | */ 425 | protected boolean borrowFrom(int a, int b) 426 | { 427 | return (a < b) ? true : false; // TODO suspect! 428 | } 429 | 430 | /** 431 | * 32-bit values. 432 | * 433 | * @param a 434 | * @param b 435 | * @return 436 | */ 437 | protected boolean carryFrom(int a, int b) 438 | { 439 | return ((a + b) < a) ? true : false; // TODO suspect! 440 | } 441 | 442 | /** 443 | * 32-bit opcode. 444 | * 445 | * @param opcode 446 | * @return 447 | */ 448 | protected boolean condCheck(int opcode) 449 | { 450 | int condCheck = (opcode >> 28) & 0x0f; 451 | return conditionCheck(ConditionCode.values()[condCheck]); 452 | } 453 | 454 | /** 455 | * 16-bit opcode. 456 | * 457 | * @param opcode 458 | * @return 459 | */ 460 | protected boolean condCheck(short opcode) 461 | { 462 | int condCheck = (opcode >> 8) & 0x0f; 463 | return conditionCheck(ConditionCode.values()[condCheck]); 464 | } 465 | 466 | /** 467 | * 32-bit opcode. 468 | * 469 | * @param opcode 470 | * @return 471 | */ 472 | protected void condPrint(int opcode) 473 | { 474 | int condCheck = (opcode >> 28) & 0x0f; 475 | System.out.print(ConditionCode.values()[condCheck]); 476 | } 477 | 478 | /** 479 | * 16-bit opcode. 480 | * 481 | * @param opcode 482 | * @return 483 | */ 484 | protected void condPrint(short opcode) 485 | { 486 | int condCheck = (opcode >> 8) & 0x0f; 487 | System.out.print(ConditionCode.values()[condCheck]); 488 | } 489 | 490 | /** 491 | * 492 | */ 493 | protected void forceThumbMode() 494 | { 495 | this.cpsr.t = true; 496 | } 497 | 498 | /** 499 | * 32-bit values. 500 | * 501 | * @param a 502 | * @param b 503 | * @return 504 | */ 505 | protected boolean overflowFrom(int a, int b) 506 | { 507 | int s = a + b; 508 | 509 | if (((a & (1 << 31)) == (b & (1 << 31))) && 510 | ((s & (1 << 31)) != (a & (1 << 31)))) 511 | { 512 | return true; 513 | } 514 | 515 | return false; 516 | } 517 | 518 | /** 519 | * Parses the next ARM (32-bit) instruction. 520 | */ 521 | protected void parse() 522 | { 523 | System.out.printf("%08X [A] ", this.r[15]); 524 | 525 | /* Read opcode */ 526 | int opcode = this.memory.read32(this.r[15]); 527 | 528 | System.out.printf("(%08x) ", opcode); 529 | 530 | /* Update PC */ 531 | this.r[15] += 4; // 32-bit 532 | 533 | /* Registers */ 534 | int Rn = ((opcode >> 16) & 0xF); 535 | int Rd = ((opcode >> 12) & 0xF); 536 | int Rm = ((opcode >> 0) & 0xF); 537 | int Rs = ((opcode >> 8) & 0xF); 538 | int Imm = ((opcode >> 0) & 0xFF); 539 | int amt = Rs << 1; 540 | 541 | /* Flags */ 542 | boolean I = ((opcode >> 25) & 1) != 0; 543 | boolean P = ((opcode >> 24) & 1) != 0; 544 | boolean U = ((opcode >> 23) & 1) != 0; 545 | boolean B = ((opcode >> 22) & 1) != 0; 546 | boolean W = ((opcode >> 21) & 1) != 0; 547 | boolean S = ((opcode >> 20) & 1) != 0; 548 | boolean L = ((opcode >> 20) & 1) != 0; 549 | 550 | if (((opcode >> 8) & 0x0FFFFF) == 0x012FFF) 551 | { 552 | boolean link = ((opcode >> 5) & 1) != 0; 553 | 554 | System.out.printf("b%sx", (link) ? "l" : ""); 555 | condPrint(opcode); 556 | System.out.printf(" r%d\n", Rm); 557 | 558 | if (!condCheck(opcode)) 559 | { 560 | return; 561 | } 562 | 563 | if (link) 564 | { 565 | this.r[14] = this.r[15]; 566 | } 567 | 568 | this.cpsr.t = (this.r[Rm] & 1) == 1; 569 | 570 | this.r[15] = this.r[Rm] & ~1; 571 | 572 | return; 573 | } 574 | 575 | if ((opcode >>> 24) == 0xEF) 576 | { 577 | int ImmA = (opcode & 0xFFFFFF); 578 | 579 | System.out.printf("swi 0x%X\n", ImmA); 580 | parseSvc(ImmA & 0xFF); 581 | 582 | return; 583 | } 584 | 585 | if ((((opcode >> 22) & 0x3F) == 0) && 586 | (((opcode >> 4) & 0x0F) == 9)) 587 | { 588 | System.out.printf("%s", W ? "mla" : "mul"); 589 | condPrint(opcode); 590 | suffPrint(opcode); 591 | 592 | System.out.printf(" r%d, r%d, r%d", Rn, Rm, Rs); 593 | if (W) 594 | { 595 | System.out.printf(", r%d", Rd); 596 | } 597 | System.out.printf("\n"); 598 | 599 | if (!condCheck(opcode)) 600 | { 601 | return; 602 | } 603 | 604 | if (W) 605 | { 606 | this.r[Rn] = (this.r[Rm] * this.r[Rs] + this.r[Rd]) & 0xFFFFFFFF; 607 | } 608 | else 609 | { 610 | this.r[Rn] = (this.r[Rm] * this.r[Rs]) & 0xFFFFFFFF; 611 | } 612 | 613 | if (S) 614 | { 615 | this.cpsr.z = this.r[Rn] == 0; 616 | this.cpsr.n = (this.r[Rn] >> 31) != 0; 617 | } 618 | 619 | return; 620 | } 621 | 622 | switch ((opcode >> 26) & 0x3) 623 | { 624 | case 0: 625 | { 626 | switch ((opcode >> 21) & 0xF) 627 | { 628 | case 0: 629 | { // AND 630 | System.out.printf("and"); 631 | condPrint(opcode); 632 | suffPrint(opcode); 633 | 634 | if (!I) 635 | { 636 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 637 | shiftPrint(opcode); 638 | } 639 | else 640 | { 641 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 642 | } 643 | 644 | System.out.printf("\n"); 645 | 646 | if (!condCheck(opcode)) 647 | { 648 | return; 649 | } 650 | 651 | if (I) 652 | { 653 | this.r[Rd] = this.r[Rn] & ROR(Imm, amt); 654 | } 655 | else 656 | { 657 | this.r[Rd] = this.r[Rn] & shift(opcode, this.r[Rm]); 658 | } 659 | 660 | if (S) 661 | { 662 | this.cpsr.z = this.r[Rd] == 0; 663 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 664 | } 665 | 666 | return; 667 | } 668 | 669 | case 1: 670 | { // EOR 671 | System.out.printf("eor"); 672 | condPrint(opcode); 673 | suffPrint(opcode); 674 | 675 | if (!I) 676 | { 677 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 678 | shiftPrint(opcode); 679 | } 680 | else 681 | { 682 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 683 | } 684 | 685 | System.out.printf("\n"); 686 | 687 | if (!condCheck(opcode)) 688 | { 689 | return; 690 | } 691 | 692 | if (I) 693 | { 694 | this.r[Rd] = this.r[Rn] ^ ROR(Imm, amt); 695 | } 696 | else 697 | { 698 | this.r[Rd] = this.r[Rn] ^ shift(opcode, this.r[Rm]); 699 | } 700 | 701 | if (S) 702 | { 703 | this.cpsr.z = this.r[Rd] == 0; 704 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 705 | } 706 | 707 | return; 708 | } 709 | 710 | case 2: 711 | { // SUB 712 | System.out.printf("sub"); 713 | condPrint(opcode); 714 | suffPrint(opcode); 715 | 716 | if (!I) 717 | { 718 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 719 | shiftPrint(opcode); 720 | } 721 | else 722 | { 723 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 724 | } 725 | 726 | System.out.printf("\n"); 727 | 728 | if (!condCheck(opcode)) 729 | { 730 | return; 731 | } 732 | 733 | if (I) 734 | { 735 | this.r[Rd] = this.r[Rn] - ROR(Imm, amt); 736 | } 737 | else 738 | { 739 | this.r[Rd] = this.r[Rn] - shift(opcode, this.r[Rm]); 740 | } 741 | 742 | if (S) 743 | { 744 | this.cpsr.c = (I) ? (this.r[Rn] >= ROR(Imm, amt)) : (this.r[Rn] < this.r[Rd]); 745 | this.cpsr.v = (I) ? ((this.r[Rn] >> 31) & ~(this.r[Rd] >> 31)) != 0 746 | : ((this.r[Rn] >> 31) & ~(this.r[Rd] >> 31)) != 0; 747 | this.cpsr.z = this.r[Rd] == 0; 748 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 749 | } 750 | 751 | return; 752 | } 753 | 754 | case 3: 755 | { // RSB 756 | System.out.printf("rsb"); 757 | condPrint(opcode); 758 | suffPrint(opcode); 759 | 760 | if (!I) 761 | { 762 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 763 | shiftPrint(opcode); 764 | } 765 | else 766 | { 767 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 768 | } 769 | 770 | System.out.printf("\n"); 771 | 772 | if (!condCheck(opcode)) 773 | { 774 | return; 775 | } 776 | 777 | if (I) 778 | { 779 | this.r[Rd] = ROR(Imm, amt) - this.r[Rn]; 780 | } 781 | else 782 | { 783 | this.r[Rd] = shift(opcode, this.r[Rm]) - this.r[Rn]; 784 | } 785 | 786 | if (S) 787 | { 788 | this.cpsr.c = (I) ? (this.r[Rn] > Imm) : (this.r[Rn] > this.r[Rm]); 789 | this.cpsr.v = (I) ? ((Imm >> 31) & ~((Imm - this.r[Rn]) >> 31)) != 0 790 | : ((Imm >> 31) & ~((this.r[Rm] - this.r[Rn]) >> 31)) != 0; 791 | this.cpsr.z = this.r[Rd] == 0; 792 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 793 | } 794 | 795 | return; 796 | } 797 | 798 | case 4: 799 | { // ADD 800 | System.out.printf("add"); 801 | condPrint(opcode); 802 | suffPrint(opcode); 803 | 804 | if (!I) 805 | { 806 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 807 | shiftPrint(opcode); 808 | } 809 | else 810 | { 811 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 812 | } 813 | 814 | System.out.printf("\n"); 815 | 816 | if (!condCheck(opcode)) 817 | { 818 | return; 819 | } 820 | 821 | if (I) 822 | { 823 | this.r[Rd] = this.r[Rn] + ROR(Imm, amt); 824 | } 825 | else 826 | { 827 | this.r[Rd] = this.r[Rn] + shift(opcode, this.r[Rm]); 828 | } 829 | 830 | if (Rn == 15) 831 | { 832 | this.r[Rd] += 4; 833 | } 834 | 835 | if (S) 836 | { 837 | this.cpsr.c = this.r[Rd] < this.r[Rn]; 838 | this.cpsr.v = ((this.r[Rn] >> 31) & ~(this.r[Rd] >> 31)) != 0; 839 | this.cpsr.z = this.r[Rd] == 0; 840 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 841 | } 842 | 843 | return; 844 | } 845 | 846 | case 5: 847 | { // ADC 848 | System.out.printf("adc"); 849 | condPrint(opcode); 850 | suffPrint(opcode); 851 | 852 | if (!I) 853 | { 854 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 855 | shiftPrint(opcode); 856 | } 857 | else 858 | { 859 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 860 | } 861 | 862 | System.out.printf("\n"); 863 | 864 | if (!condCheck(opcode)) 865 | { 866 | return; 867 | } 868 | 869 | if (I) 870 | { 871 | this.r[Rd] = this.r[Rn] + ROR(Imm, amt) + (this.cpsr.c ? 1 : 0); 872 | } 873 | else 874 | { 875 | this.r[Rd] = this.r[Rn] + shift(opcode, this.r[Rm]) + (this.cpsr.c ? 1 : 0); 876 | } 877 | 878 | if (S) 879 | { 880 | this.cpsr.z = this.r[Rd] == 0; 881 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 882 | } 883 | 884 | return; 885 | } 886 | 887 | case 6: 888 | { // SBC 889 | System.out.printf("sbc"); 890 | condPrint(opcode); 891 | suffPrint(opcode); 892 | 893 | if (!I) 894 | { 895 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 896 | shiftPrint(opcode); 897 | } 898 | else 899 | { 900 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 901 | } 902 | 903 | System.out.printf("\n"); 904 | 905 | if (!condCheck(opcode)) 906 | { 907 | return; 908 | } 909 | 910 | if (I) 911 | { 912 | this.r[Rd] = this.r[Rn] - ROR(Imm, amt) - (this.cpsr.c ? 0 : 1); 913 | } 914 | else 915 | { 916 | this.r[Rd] = this.r[Rn] - shift(opcode, this.r[Rm]) - (this.cpsr.c ? 0 : 1); 917 | } 918 | 919 | if (S) 920 | { 921 | this.cpsr.c = this.r[Rd] > this.r[Rn]; 922 | this.cpsr.v = ((this.r[Rn] >> 31) & ~(this.r[Rd] >> 31)) != 0; 923 | this.cpsr.z = this.r[Rd] == 0; 924 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 925 | } 926 | 927 | return; 928 | } 929 | 930 | case 7: 931 | { // RSC 932 | System.out.printf("rsc"); 933 | condPrint(opcode); 934 | suffPrint(opcode); 935 | 936 | if (!I) 937 | { 938 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 939 | shiftPrint(opcode); 940 | } 941 | else 942 | { 943 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 944 | } 945 | 946 | System.out.printf("\n"); 947 | 948 | if (!condCheck(opcode)) 949 | { 950 | return; 951 | } 952 | 953 | if (I) 954 | { 955 | this.r[Rd] = ROR(Imm, amt) - this.r[Rn] - (this.cpsr.c ? 0 : 1); 956 | } 957 | else 958 | { 959 | this.r[Rd] = shift(opcode, this.r[Rm]) - this.r[Rn] - (this.cpsr.c ? 0 : 1); 960 | } 961 | 962 | if (S) 963 | { 964 | this.cpsr.c = (I) ? (this.r[Rd] > Imm) : (this.r[Rd] > this.r[Rm]); 965 | this.cpsr.v = (I) ? ((this.r[Rm] >> 31) & ~(this.r[Rd] >> 31)) != 0 966 | : ((this.r[Rn] >> 31) & ~(this.r[Rd] >> 31)) != 0; 967 | this.cpsr.z = this.r[Rd] == 0; 968 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 969 | } 970 | 971 | return; 972 | } 973 | 974 | case 8: 975 | { // TST/MRS 976 | if (S) 977 | { 978 | int result; 979 | 980 | System.out.printf("tst"); 981 | condPrint(opcode); 982 | 983 | if (!I) 984 | { 985 | System.out.printf(" r%d, r%d\n", Rn, Rm); 986 | shiftPrint(opcode); 987 | 988 | result = this.r[Rn] & shift(opcode, this.r[Rm]); 989 | } 990 | else 991 | { 992 | System.out.printf(" r%d, #0x%X\n", Rn, ROR(Imm, amt)); 993 | result = this.r[Rn] & ROR(Imm, amt); 994 | } 995 | 996 | this.cpsr.z = result == 0; 997 | this.cpsr.n = (result >> 31) != 0; 998 | } 999 | else 1000 | { 1001 | System.out.printf("mrs r%d, cpsr\n", Rd); 1002 | this.r[Rd] = this.cpsr.getValue(); 1003 | } 1004 | 1005 | return; 1006 | } 1007 | 1008 | case 9: 1009 | { // TEQ/MSR 1010 | if (S) 1011 | { 1012 | int result; 1013 | 1014 | System.out.printf("teq"); 1015 | condPrint(opcode); 1016 | 1017 | if (!I) 1018 | { 1019 | System.out.printf(" r%d, r%d\n", Rn, Rm); 1020 | shiftPrint(opcode); 1021 | 1022 | result = this.r[Rn] ^ shift(opcode, this.r[Rm]); 1023 | } 1024 | else 1025 | { 1026 | System.out.printf(" r%d, #0x%X\n", Rn, ROR(Imm, amt)); 1027 | result = this.r[Rn] ^ ROR(Imm, amt); 1028 | } 1029 | 1030 | this.cpsr.z = result == 0; 1031 | this.cpsr.n = (result >> 31) != 0; 1032 | } 1033 | else 1034 | { 1035 | if (I) 1036 | { 1037 | System.out.printf("msr cpsr, r%d\n", Rm); 1038 | this.cpsr.setValue(this.r[Rm]); 1039 | } 1040 | else 1041 | { 1042 | System.out.printf("msr cpsr, 0x%08X\n", Imm); 1043 | this.cpsr.setValue(Imm); 1044 | } 1045 | } 1046 | 1047 | return; 1048 | } 1049 | 1050 | case 10: 1051 | { // CMP/MRS2 1052 | if (S) 1053 | { 1054 | int value; 1055 | 1056 | System.out.printf("cmp"); 1057 | condPrint(opcode); 1058 | 1059 | if (I) 1060 | { 1061 | value = ROR(Imm, amt); 1062 | System.out.printf(" r%d, 0x%08X\n", Rn, value); 1063 | } 1064 | else 1065 | { 1066 | value = this.r[Rm]; 1067 | System.out.printf(" r%d, r%d\n", Rn, Rm); 1068 | } 1069 | 1070 | if (condCheck(opcode)) 1071 | { 1072 | subtract(this.r[Rn], value); 1073 | } 1074 | } 1075 | else 1076 | { 1077 | System.out.printf("mrs2\n"); 1078 | } 1079 | 1080 | return; 1081 | } 1082 | 1083 | case 11: 1084 | { // CMN/MSR2 1085 | if (S) 1086 | { 1087 | int value; 1088 | 1089 | System.out.printf("cmn"); 1090 | condPrint(opcode); 1091 | 1092 | if (I) 1093 | { 1094 | value = ROR(Imm, amt); 1095 | System.out.printf(" r%d, 0x%08X\n", Rn, value); 1096 | } 1097 | else 1098 | { 1099 | value = this.r[Rm]; 1100 | System.out.printf(" r%d, r%d\n", Rn, Rm); 1101 | } 1102 | 1103 | if (condCheck(opcode)) 1104 | { 1105 | addition(this.r[Rn], value); 1106 | } 1107 | } 1108 | else 1109 | { 1110 | System.out.printf("msr2\n"); 1111 | } 1112 | 1113 | return; 1114 | } 1115 | 1116 | case 12: 1117 | { // ORR 1118 | System.out.printf("orr"); 1119 | condPrint(opcode); 1120 | suffPrint(opcode); 1121 | 1122 | if (!I) 1123 | { 1124 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 1125 | shiftPrint(opcode); 1126 | } 1127 | else 1128 | { 1129 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 1130 | } 1131 | 1132 | System.out.printf("\n"); 1133 | 1134 | if (!condCheck(opcode)) 1135 | { 1136 | return; 1137 | } 1138 | 1139 | if (I) 1140 | { 1141 | this.r[Rd] = this.r[Rn] | ROR(Imm, amt); 1142 | } 1143 | else 1144 | { 1145 | this.r[Rd] = this.r[Rn] | shift(opcode, this.r[Rm]); 1146 | } 1147 | 1148 | if (S) 1149 | { 1150 | this.cpsr.z = this.r[Rd] == 0; 1151 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1152 | } 1153 | 1154 | return; 1155 | } 1156 | 1157 | case 13: 1158 | { // MOV 1159 | System.out.printf("mov"); 1160 | condPrint(opcode); 1161 | suffPrint(opcode); 1162 | 1163 | if (!I) 1164 | { 1165 | System.out.printf(" r%d, r%d", Rd, Rm); 1166 | shiftPrint(opcode); 1167 | } 1168 | else 1169 | { 1170 | System.out.printf(" r%d, #0x%X", Rd, ROR(Imm, amt)); 1171 | } 1172 | 1173 | System.out.printf("\n"); 1174 | 1175 | if (!condCheck(opcode)) 1176 | { 1177 | return; 1178 | } 1179 | 1180 | if (I) 1181 | { 1182 | this.r[Rd] = ROR(Imm, amt); 1183 | } 1184 | else 1185 | { 1186 | this.r[Rd] = (Rm == 15) ? (this.r[15] + 4 /* 32-bit */) : shift(opcode, this.r[Rm]); 1187 | } 1188 | 1189 | if (S) 1190 | { 1191 | this.cpsr.z = this.r[Rd] == 0; 1192 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1193 | } 1194 | 1195 | return; 1196 | } 1197 | 1198 | case 14: 1199 | { // BIC 1200 | System.out.printf("bic"); 1201 | condPrint(opcode); 1202 | suffPrint(opcode); 1203 | 1204 | if (!I) 1205 | { 1206 | System.out.printf(" r%d, r%d, r%d", Rd, Rn, Rm); 1207 | shiftPrint(opcode); 1208 | } 1209 | else 1210 | { 1211 | System.out.printf(" r%d, r%d, #0x%X", Rd, Rn, ROR(Imm, amt)); 1212 | } 1213 | 1214 | System.out.printf("\n"); 1215 | 1216 | if (!condCheck(opcode)) 1217 | { 1218 | return; 1219 | } 1220 | 1221 | if (I) 1222 | { 1223 | this.r[Rd] = this.r[Rn] & ~(ROR(Imm, amt)); 1224 | } 1225 | else 1226 | { 1227 | this.r[Rd] = this.r[Rd] & ~shift(opcode, this.r[Rm]); 1228 | } 1229 | 1230 | if (S) 1231 | { 1232 | this.cpsr.z = this.r[Rd] == 0; 1233 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1234 | } 1235 | 1236 | return; 1237 | } 1238 | 1239 | case 15: 1240 | { // MVN 1241 | System.out.printf("mvn"); 1242 | condPrint(opcode); 1243 | suffPrint(opcode); 1244 | 1245 | if (!I) 1246 | { 1247 | System.out.printf(" r%d, r%d", Rd, Rm); 1248 | shiftPrint(opcode); 1249 | } 1250 | else 1251 | { 1252 | System.out.printf(" r%d, #0x%X", Rd, ROR(Imm, amt)); 1253 | } 1254 | 1255 | System.out.printf("\n"); 1256 | 1257 | if (!condCheck(opcode)) 1258 | { 1259 | return; 1260 | } 1261 | 1262 | if (I) 1263 | { 1264 | this.r[Rd] = ~ROR(Imm, amt); 1265 | } 1266 | else 1267 | { 1268 | this.r[Rd] = ~shift(opcode, this.r[Rm]); 1269 | } 1270 | 1271 | if (S) 1272 | { 1273 | this.cpsr.z = this.r[Rd] == 0; 1274 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1275 | } 1276 | 1277 | return; 1278 | } 1279 | } 1280 | } 1281 | 1282 | case 1: 1283 | { // LDR/STR 1284 | int addr, value = 0, wb; 1285 | 1286 | System.out.printf("%s%s", (L) ? "ldr" : "str", (B) ? "b" : ""); 1287 | condPrint(opcode); 1288 | System.out.printf(" r%d,", Rd); 1289 | 1290 | Imm = opcode & 0xFFF; 1291 | 1292 | if (L && (Rn == 15)) 1293 | { 1294 | addr = this.r[15] + Imm + 4; 1295 | value = this.memory.read32(addr); 1296 | 1297 | if (condCheck(opcode)) 1298 | { 1299 | this.r[Rd] = value; 1300 | } 1301 | 1302 | System.out.printf(" =0x%X\n", value); 1303 | return; 1304 | } 1305 | 1306 | System.out.printf(" [r%d", Rn); 1307 | 1308 | if (I) 1309 | { 1310 | value = shift(opcode, this.r[Rm]); 1311 | 1312 | System.out.printf(", %sr%d", (U) ? "" : "-", Rm); 1313 | shiftPrint(opcode); 1314 | } 1315 | else 1316 | { 1317 | value = Imm; 1318 | System.out.printf(", #%s0x%X", (U) ? "" : "-", value); 1319 | } 1320 | System.out.printf("]%s\n", (W) ? "!" : ""); 1321 | 1322 | if (!condCheck(opcode)) 1323 | { 1324 | return; 1325 | } 1326 | 1327 | if (U) 1328 | { 1329 | wb = this.r[Rn] + value; 1330 | } 1331 | else 1332 | { 1333 | wb = this.r[Rn] - value; 1334 | } 1335 | 1336 | addr = (P) ? wb : this.r[Rn]; 1337 | 1338 | if (L) 1339 | { 1340 | if (B) 1341 | { 1342 | this.r[Rd] = this.memory.read8(addr); 1343 | } 1344 | else 1345 | { 1346 | this.r[Rd] = this.memory.read32(addr); 1347 | } 1348 | } 1349 | else 1350 | { 1351 | value = this.r[Rd]; 1352 | if (Rd == 15) 1353 | { 1354 | value += 8; 1355 | } 1356 | 1357 | if (B) 1358 | { 1359 | this.memory.write8(addr, (byte) (value & 0xFF)); 1360 | } 1361 | else 1362 | { 1363 | this.memory.write32(addr, value); 1364 | } 1365 | } 1366 | 1367 | if (W || !P) 1368 | { 1369 | this.r[Rn] = wb; 1370 | } 1371 | return; 1372 | } 1373 | 1374 | default: 1375 | break; 1376 | } 1377 | 1378 | switch ((opcode >> 25) & 7) 1379 | { 1380 | case 4: 1381 | { // LDM/STM 1382 | int start = this.r[Rn]; 1383 | boolean pf = false; 1384 | 1385 | if (L) 1386 | { 1387 | System.out.printf("ldm"); 1388 | if (Rn == 13) 1389 | { 1390 | System.out.printf("%c%c", (P) ? 'e' : 'f', (U) ? 'd' : 'a'); 1391 | } 1392 | else 1393 | { 1394 | System.out.printf("%c%c", (U) ? 'i' : 'd', (P) ? 'b' : 'a'); 1395 | } 1396 | } 1397 | else 1398 | { 1399 | System.out.printf("stm"); 1400 | if (Rn == 13) 1401 | { 1402 | System.out.printf("%c%c", (P) ? 'f' : 'e', (U) ? 'a' : 'd'); 1403 | } 1404 | else 1405 | { 1406 | System.out.printf("%c%c", (U) ? 'i' : 'd', (P) ? 'b' : 'a'); 1407 | } 1408 | } 1409 | 1410 | if (Rn == 13) 1411 | { 1412 | System.out.printf(" sp"); 1413 | } 1414 | else 1415 | { 1416 | System.out.printf(" r%d", Rn); 1417 | } 1418 | 1419 | if (W) 1420 | { 1421 | System.out.printf("!"); 1422 | } 1423 | System.out.printf(", {"); 1424 | 1425 | for (int i = 0; i < 16; i++) 1426 | { 1427 | if (((opcode >> i) & 1) != 0) 1428 | { 1429 | if (pf) 1430 | { 1431 | System.out.printf(", "); 1432 | } 1433 | System.out.printf("r%d", i); 1434 | 1435 | pf = true; 1436 | } 1437 | } 1438 | 1439 | System.out.printf("}"); 1440 | if (B) 1441 | { 1442 | System.out.printf("^"); 1443 | if ((opcode & (1 << 15)) != 0) 1444 | { 1445 | this.cpsr.setValue(this.spsr); 1446 | } 1447 | } 1448 | System.out.printf("\n"); 1449 | 1450 | if (L) 1451 | { 1452 | for (int i = 0; i < 16; i++) 1453 | { 1454 | if (((opcode >> i) & 1) != 0) 1455 | { 1456 | if (P) 1457 | { 1458 | start += U ? 4 : -4; // 32-bit 1459 | } 1460 | this.r[i] = this.memory.read32(start); 1461 | if (!P) 1462 | { 1463 | start += U ? 4 : -4; // 32-bit 1464 | } 1465 | } 1466 | } 1467 | } 1468 | else 1469 | { 1470 | for (int i = 15; i >= 0; i--) 1471 | { 1472 | if (((opcode >> i) & 1) != 0) 1473 | { 1474 | if (P) 1475 | { 1476 | start += U ? 4 : -4; // 32-bit 1477 | } 1478 | this.memory.write32(start, this.r[i]); 1479 | if (!P) 1480 | { 1481 | start += U ? 4 : -4; // 32-bit 1482 | } 1483 | } 1484 | } 1485 | } 1486 | 1487 | if (W) 1488 | { 1489 | this.r[Rn] = start; 1490 | } 1491 | return; 1492 | } 1493 | 1494 | case 5: 1495 | { // B/BL 1496 | boolean link = (opcode & (1 << 24)) != 0; 1497 | 1498 | System.out.printf("b%s", (link) ? "l" : ""); 1499 | condPrint(opcode); 1500 | 1501 | Imm = (opcode & 0xFFFFFF) << 2; 1502 | if ((Imm & (1 << 25)) != 0) 1503 | { 1504 | Imm = ~(~Imm & 0xFFFFFF); 1505 | } 1506 | Imm += 4; // 32-bit 1507 | 1508 | System.out.printf(" 0x%08X\n", this.r[15] + Imm); 1509 | 1510 | if (!condCheck(opcode)) 1511 | { 1512 | return; 1513 | } 1514 | 1515 | if (link) 1516 | { 1517 | this.r[14] = this.r[15]; 1518 | } 1519 | this.r[15] += Imm; 1520 | 1521 | return; 1522 | } 1523 | 1524 | case 7: 1525 | { // MRC 1526 | System.out.printf("mrc ...\n"); 1527 | return; 1528 | } 1529 | } 1530 | 1531 | System.out.printf("Unknown opcode! (0x%08X)\n", opcode); 1532 | 1533 | } 1534 | 1535 | /** 1536 | * 8-bit value 1537 | * 1538 | * @param num 1539 | */ 1540 | protected void parseSvc(int num) 1541 | { 1542 | /* Parse syscall */ 1543 | switch (num) 1544 | { 1545 | case 0: 1546 | { // exit 1547 | /* Set finish flag */ 1548 | this.finished = true; 1549 | break; 1550 | } 1551 | 1552 | case 4: 1553 | { // write 1554 | int fd = this.r[0]; 1555 | int addr = this.r[1]; 1556 | int len = this.r[2]; 1557 | 1558 | /* No output descriptor */ 1559 | if ((fd < 1) || (fd > 2)) 1560 | { 1561 | break; 1562 | } 1563 | 1564 | /* Print string */ 1565 | for (int i = 0; i < len; i++) 1566 | { 1567 | System.out.printf("0x%x", this.memory.read8(addr + i)); 1568 | } 1569 | 1570 | /* Return value */ 1571 | this.r[0] = len; 1572 | 1573 | break; 1574 | } 1575 | 1576 | default: 1577 | System.out.printf(" [S] Unhandled syscall! (%02X)\n", num); 1578 | } 1579 | } 1580 | 1581 | /** 1582 | * Parses a THUMB (16-bit) instruction. 1583 | */ 1584 | protected void parseThumb() 1585 | { 1586 | System.out.printf("%08X [T] ", this.r[15]); 1587 | 1588 | /* Read opcode */ 1589 | int opcode = this.memory.read16(this.r[15]) & 0xFFFF; 1590 | 1591 | System.out.printf("(%04x) ", opcode); 1592 | 1593 | /* Update PC */ 1594 | this.r[15] += 2; // 16-bit 1595 | 1596 | if ((opcode >> 13) == 0) 1597 | { 1598 | int Imm = (opcode >> 6) & 0x1F; 1599 | int Rn = (opcode >> 6) & 7; 1600 | int Rm = (opcode >> 3) & 7; 1601 | int Rd = (opcode >> 0) & 7; 1602 | 1603 | switch ((opcode >> 11) & 3) 1604 | { 1605 | case 0: 1606 | { // LSL 1607 | if ((Imm > 0) && (Imm <= 32)) 1608 | { 1609 | this.cpsr.c = (this.r[Rd] & (1 << (32 - Imm))) != 0; 1610 | this.r[Rd] = LSL(this.r[Rd], Imm); 1611 | } 1612 | 1613 | if (Imm > 32) 1614 | { 1615 | this.cpsr.c = false; 1616 | this.r[Rd] = 0; 1617 | } 1618 | 1619 | this.cpsr.z = this.r[Rd] == 0; 1620 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1621 | 1622 | System.out.printf("lsl r%d, r%d, #0x%02X\n", Rd, Rm, Imm); 1623 | return; 1624 | } 1625 | 1626 | case 1: 1627 | { // LSR 1628 | if ((Imm > 0) && (Imm <= 32)) 1629 | { 1630 | this.cpsr.c = (this.r[Rd] & (1 << (Imm - 1))) != 0; 1631 | this.r[Rd] = LSR(this.r[Rd], Imm); 1632 | } 1633 | 1634 | if (Imm > 32) 1635 | { 1636 | this.cpsr.c = false; 1637 | this.r[Rd] = 0; 1638 | } 1639 | 1640 | this.cpsr.z = this.r[Rd] == 0; 1641 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1642 | 1643 | System.out.printf("lsr r%d, r%d, #0x%02X\n", Rd, Rm, Imm); 1644 | return; 1645 | } 1646 | 1647 | case 2: 1648 | { // ASR 1649 | if ((Imm > 0) && (Imm <= 32)) 1650 | { 1651 | this.cpsr.c = (this.r[Rd] & (1 << (Imm - 1))) != 0; 1652 | this.r[Rd] = ASR(this.r[Rd], Imm); 1653 | } 1654 | 1655 | if (Imm > 32) 1656 | { 1657 | this.cpsr.c = false; 1658 | this.r[Rd] = 0; 1659 | } 1660 | 1661 | this.cpsr.z = this.r[Rd] == 0; 1662 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1663 | 1664 | System.out.printf("asr r%d, r%d, #0x%02X\n", Rd, Rm, Imm); 1665 | return; 1666 | } 1667 | 1668 | case 3: 1669 | { // ADD, SUB 1670 | if ((opcode & 0x400) != 0) 1671 | { 1672 | Imm &= 7; 1673 | 1674 | if ((opcode & 0x200) != 0) 1675 | { 1676 | this.r[Rd] = subtract(this.r[Rm], Imm); 1677 | 1678 | System.out.printf("sub r%d, r%d, #0x%02X\n", Rd, Rm, Imm); 1679 | return; 1680 | } 1681 | else 1682 | { 1683 | this.r[Rd] = addition(this.r[Rm], Imm); 1684 | 1685 | System.out.printf("add r%d, r%d, #0x%02X\n", Rd, Rm, Imm); 1686 | } 1687 | } 1688 | else 1689 | { 1690 | if ((opcode & 0x200) != 0) 1691 | { 1692 | this.r[Rd] = subtract(this.r[Rm], this.r[Rn]); 1693 | 1694 | System.out.printf("sub r%d, r%d, r%d\n", Rd, Rm, Rn); 1695 | return; 1696 | } 1697 | else 1698 | { 1699 | this.r[Rd] = addition(this.r[Rm], this.r[Rn]); 1700 | 1701 | System.out.printf("add r%d, r%d, r%d\n", Rd, Rm, Rn); 1702 | return; 1703 | } 1704 | } 1705 | 1706 | return; 1707 | } 1708 | } 1709 | } 1710 | 1711 | if ((opcode >> 13) == 1) 1712 | { 1713 | int Imm = (opcode & 0xFF); 1714 | int Rn = (opcode >> 8) & 7; 1715 | 1716 | switch ((opcode >> 11) & 3) 1717 | { 1718 | case 0: 1719 | { // MOV 1720 | this.r[Rn] = Imm; 1721 | 1722 | this.cpsr.z = this.r[Rn] == 0; 1723 | this.cpsr.n = (this.r[Rn] >> 31) != 0; 1724 | 1725 | System.out.printf("mov r%d, #0x%02X\n", Rn, Imm); 1726 | return; 1727 | } 1728 | 1729 | case 1: 1730 | { // CMP 1731 | subtract(this.r[Rn], Imm); 1732 | 1733 | System.out.printf("cmp r%d, #0x%02X\n", Rn, Imm); 1734 | return; 1735 | } 1736 | 1737 | case 2: 1738 | { // ADD 1739 | this.r[Rn] = addition(this.r[Rn], Imm); 1740 | 1741 | System.out.printf("add r%d, #0x%02X\n", Rn, Imm); 1742 | return; 1743 | } 1744 | 1745 | case 3: 1746 | { // SUB 1747 | this.r[Rn] = subtract(this.r[Rn], Imm); 1748 | 1749 | System.out.printf("sub r%d, #0x%02X\n", Rn, Imm); 1750 | return; 1751 | } 1752 | } 1753 | } 1754 | 1755 | if ((opcode >> 10) == 0x10) 1756 | { 1757 | int Rd = opcode & 7; 1758 | int Rm = (opcode >> 3) & 7; 1759 | 1760 | switch ((opcode >> 6) & 0xF) 1761 | { 1762 | case 0: 1763 | { // AND 1764 | this.r[Rd] &= this.r[Rm]; 1765 | 1766 | this.cpsr.z = this.r[Rd] == 0; 1767 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1768 | 1769 | System.out.printf("and r%d, r%d\n", Rd, Rm); 1770 | return; 1771 | } 1772 | 1773 | case 1: 1774 | { // EOR 1775 | this.r[Rd] ^= this.r[Rm]; 1776 | 1777 | this.cpsr.z = this.r[Rd] == 0; 1778 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1779 | 1780 | System.out.printf("eor r%d, r%d\n", Rd, Rm); 1781 | return; 1782 | } 1783 | 1784 | case 2: 1785 | { // LSL 1786 | int shift = this.r[Rm] & 0xFF; 1787 | 1788 | if ((shift > 0) && (shift <= 32)) 1789 | { 1790 | this.cpsr.c = (this.r[Rd] & (1 << (32 - shift))) != 0; 1791 | this.r[Rd] = LSL(this.r[Rd], shift); 1792 | } 1793 | 1794 | if (shift > 32) 1795 | { 1796 | this.cpsr.c = false; 1797 | this.r[Rd] = 0; 1798 | } 1799 | 1800 | this.cpsr.z = this.r[Rd] == 0; 1801 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1802 | 1803 | System.out.printf("lsl r%d, r%d\n", Rd, Rm); 1804 | return; 1805 | } 1806 | 1807 | case 3: 1808 | { // LSR 1809 | int shift = this.r[Rm] & 0xFF; 1810 | 1811 | if ((shift > 0) && (shift <= 32)) 1812 | { 1813 | this.cpsr.c = (this.r[Rd] & (1 << (shift - 1))) != 0; 1814 | this.r[Rd] = LSR(this.r[Rd], shift); 1815 | } 1816 | 1817 | if (shift > 32) 1818 | { 1819 | this.cpsr.c = false; 1820 | this.r[Rd] = 0; 1821 | } 1822 | 1823 | this.cpsr.z = this.r[Rd] == 0; 1824 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1825 | 1826 | System.out.printf("lsr r%d, r%d\n", Rd, Rm); 1827 | return; 1828 | } 1829 | 1830 | case 4: 1831 | { // ASR 1832 | int shift = this.r[Rm] & 0xFF; 1833 | 1834 | if ((shift > 0) && (shift < 32)) 1835 | { 1836 | this.cpsr.c = (this.r[Rd] & (1 << (shift - 1))) != 0; 1837 | this.r[Rd] = ASR(this.r[Rd], shift); 1838 | } 1839 | 1840 | if (shift == 32) 1841 | { 1842 | this.cpsr.c = (this.r[Rd] >> 31) != 0; 1843 | this.r[Rd] = 0; 1844 | } 1845 | 1846 | if (shift > 32) 1847 | { 1848 | this.cpsr.c = false; 1849 | this.r[Rd] = 0; 1850 | } 1851 | 1852 | this.cpsr.z = this.r[Rd] == 0; 1853 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1854 | 1855 | System.out.printf("asr r%d, r%d\n", Rd, Rm); 1856 | return; 1857 | } 1858 | 1859 | case 5: 1860 | { // ADC 1861 | this.r[Rd] = addition(this.r[Rd], this.r[Rm]); 1862 | this.r[Rd] = addition(this.r[Rd], this.cpsr.c ? 1 : 0); 1863 | 1864 | this.cpsr.z = this.r[Rd] == 0; 1865 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1866 | 1867 | System.out.printf("adc r%d, r%d\n", Rd, Rm); 1868 | return; 1869 | } 1870 | 1871 | case 6: 1872 | { // SBC 1873 | this.r[Rd] = subtract(this.r[Rd], this.r[Rm]); 1874 | this.r[Rd] = subtract(this.r[Rd], this.cpsr.c ? 0 : 1); 1875 | 1876 | this.cpsr.z = this.r[Rd] == 0; 1877 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1878 | 1879 | System.out.printf("sbc r%d, r%d\n", Rd, Rm); 1880 | return; 1881 | } 1882 | 1883 | case 7: 1884 | { // ROR 1885 | int shift = this.r[Rm] & 0xFF; 1886 | 1887 | while (shift >= 32) 1888 | { 1889 | shift -= 32; 1890 | } 1891 | 1892 | if (shift != 0) 1893 | { 1894 | this.cpsr.c = (this.r[Rd] & (1 << (shift - 1))) != 0; 1895 | this.r[Rd] = ROR(this.r[Rd], shift); 1896 | } 1897 | 1898 | this.cpsr.z = this.r[Rd] == 0; 1899 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1900 | 1901 | System.out.printf("ror r%d, r%d\n", Rd, Rm); 1902 | return; 1903 | } 1904 | 1905 | case 8: 1906 | { // TST 1907 | int result = this.r[Rd] & this.r[Rm]; 1908 | 1909 | this.cpsr.z = result == 0; 1910 | this.cpsr.n = (result >> 31) != 0; 1911 | 1912 | System.out.printf("tst r%d, r%d\n", Rd, Rm); 1913 | return; 1914 | } 1915 | 1916 | case 9: 1917 | { // NEG 1918 | this.r[Rd] = -this.r[Rm]; 1919 | 1920 | this.cpsr.z = this.r[Rd] == 0; 1921 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1922 | 1923 | System.out.printf("neg r%d, r%d\n", Rd, Rm); 1924 | return; 1925 | } 1926 | 1927 | case 10: 1928 | { // CMP 1929 | subtract(this.r[Rd], this.r[Rm]); 1930 | 1931 | System.out.printf("cmp r%d, r%d\n", Rd, Rm); 1932 | return; 1933 | } 1934 | 1935 | case 11: 1936 | { // CMN/MVN 1937 | if ((opcode & 0x100) != 0) 1938 | { 1939 | this.r[Rd] = ~this.r[Rm]; 1940 | 1941 | this.cpsr.z = this.r[Rd] == 0; 1942 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1943 | 1944 | System.out.printf("mvn r%d, r%d\n", Rd, Rm); 1945 | } 1946 | else 1947 | { 1948 | addition(this.r[Rd], this.r[Rm]); 1949 | 1950 | System.out.printf("cmn r%d, r%d\n", Rd, Rm); 1951 | } 1952 | 1953 | return; 1954 | } 1955 | 1956 | case 12: 1957 | { // ORR 1958 | this.r[Rd] |= this.r[Rm]; 1959 | 1960 | this.cpsr.z = this.r[Rd] == 0; 1961 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1962 | 1963 | System.out.printf("orr r%d, r%d\n", Rd, Rm); 1964 | return; 1965 | } 1966 | 1967 | case 13: 1968 | { // MUL 1969 | this.r[Rd] *= this.r[Rm]; 1970 | 1971 | this.cpsr.z = this.r[Rd] == 0; 1972 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1973 | 1974 | System.out.printf("mul r%d, r%d\n", Rd, Rm); 1975 | return; 1976 | } 1977 | 1978 | case 14: 1979 | { // BIC 1980 | this.r[Rd] &= ~this.r[Rm]; 1981 | 1982 | this.cpsr.z = this.r[Rd] == 0; 1983 | this.cpsr.n = (this.r[Rd] >> 31) != 0; 1984 | 1985 | System.out.printf("bic r%d, r%d\n", Rd, Rm); 1986 | return; 1987 | } 1988 | } 1989 | } 1990 | 1991 | if ((opcode >> 7) == 0x8F) 1992 | { 1993 | int Rm = (opcode >> 3) & 0xF; 1994 | 1995 | this.r[14] = this.r[15] | 1; 1996 | 1997 | this.cpsr.t = (this.r[Rm] & 1) != 0; 1998 | 1999 | this.r[15] = this.r[Rm] & ~1; 2000 | 2001 | System.out.printf("blx r%d\n", Rm); 2002 | return; 2003 | } 2004 | 2005 | if ((opcode >> 10) == 0x11) 2006 | { 2007 | int Rd = ((opcode >> 4) & 8) | (opcode & 7); 2008 | int Rm = ((opcode >> 3) & 0xF); 2009 | 2010 | switch ((opcode >> 8) & 3) 2011 | { 2012 | case 0: 2013 | { // ADD 2014 | this.r[Rd] = addition(this.r[Rd], this.r[Rm]); 2015 | 2016 | System.out.printf("add r%d, r%d\n", Rd, Rm); 2017 | return; 2018 | } 2019 | 2020 | case 1: 2021 | { // CMP 2022 | subtract(this.r[Rd], this.r[Rm]); 2023 | 2024 | System.out.printf("cmp r%d, r%d\n", Rd, Rm); 2025 | return; 2026 | } 2027 | 2028 | case 2: 2029 | { // MOV (NOP) 2030 | if ((Rd == 8) && (Rm == 8)) 2031 | { 2032 | System.out.printf("nop\n"); 2033 | return; 2034 | } 2035 | 2036 | this.r[Rd] = this.r[Rm]; 2037 | 2038 | System.out.printf("mov r%d, r%d\n", Rd, Rm); 2039 | return; 2040 | } 2041 | 2042 | case 3: 2043 | { // BX 2044 | this.cpsr.t = (this.r[Rm] & 1) != 0; 2045 | 2046 | if (Rm == 15) 2047 | { 2048 | this.r[15] += 2; // 16-bit 2049 | } 2050 | else 2051 | { 2052 | this.r[15] = this.r[Rm] & ~1; 2053 | } 2054 | 2055 | System.out.printf("bx r%d\n", Rm); 2056 | return; 2057 | } 2058 | } 2059 | } 2060 | 2061 | if ((opcode >> 11) == 9) 2062 | { 2063 | int Rd = (opcode >> 8) & 7; 2064 | int Imm = (opcode & 0xFF); 2065 | int addr = this.r[15] + (Imm << 2) + 2; // 16-bit 2066 | 2067 | this.r[Rd] = this.memory.read32(addr); 2068 | 2069 | System.out.printf("ldr r%d, =0x%08X\n", Rd, this.r[Rd]); 2070 | return; 2071 | } 2072 | 2073 | if ((opcode >> 12) == 5) 2074 | { 2075 | int Rd = (opcode >> 0) & 7; 2076 | int Rn = (opcode >> 3) & 7; 2077 | int Rm = (opcode >> 6) & 7; 2078 | 2079 | switch ((opcode >> 9) & 7) 2080 | { 2081 | case 0: 2082 | { // STR 2083 | int addr = this.r[Rn] + this.r[Rm]; 2084 | int value = this.r[Rd]; 2085 | 2086 | this.memory.write32(addr, value); 2087 | 2088 | System.out.printf("str r%d, [r%d, r%d]\n", Rd, Rn, Rm); 2089 | return; 2090 | } 2091 | 2092 | case 2: 2093 | { // STRB 2094 | int addr = this.r[Rn] + this.r[Rm]; 2095 | byte value = (byte) (this.r[Rd] & 0xFF); 2096 | 2097 | this.memory.write8(addr, value); 2098 | 2099 | System.out.printf("strb r%d, [r%d, r%d]\n", Rd, Rn, Rm); 2100 | return; 2101 | } 2102 | 2103 | case 4: 2104 | { // LDR 2105 | int addr = this.r[Rn] + this.r[Rm]; 2106 | 2107 | this.r[Rd] = this.memory.read32(addr); 2108 | 2109 | System.out.printf("ldr r%d, [r%d, r%d]\n", Rd, Rn, Rm); 2110 | return; 2111 | } 2112 | 2113 | case 6: 2114 | { // LDRB 2115 | int addr = this.r[Rn] + this.r[Rm]; 2116 | 2117 | this.r[Rd] = this.memory.read8(addr); 2118 | 2119 | System.out.printf("ldrb r%d, [r%d, r%d]\n", Rd, Rn, Rm); 2120 | return; 2121 | } 2122 | } 2123 | } 2124 | 2125 | if ((opcode >> 13) == 3) 2126 | { 2127 | int Rd = (opcode >> 0) & 7; 2128 | int Rn = (opcode >> 3) & 7; 2129 | int Imm = (opcode >> 6) & 7; 2130 | 2131 | if ((opcode & 0x1000) != 0) 2132 | { 2133 | if ((opcode & 0x800) != 0) 2134 | { 2135 | int addr = this.r[Rn] + (Imm << 2); 2136 | 2137 | this.r[Rd] = this.memory.read8(addr); 2138 | 2139 | System.out.printf("ldrb r%d, [r%d, 0x%02X]\n", Rd, Rn, Imm); 2140 | } 2141 | else 2142 | { 2143 | int addr = this.r[Rn] + (Imm << 2); 2144 | byte value = (byte) (this.r[Rd] & 0xFF); 2145 | 2146 | this.memory.write8(addr, value); 2147 | 2148 | System.out.printf("strb r%d, [r%d, 0x%02X]\n", Rd, Rn, Imm); 2149 | } 2150 | } 2151 | else 2152 | { 2153 | if ((opcode & 0x800) != 0) 2154 | { 2155 | int addr = this.r[Rn] + (Imm << 2); 2156 | 2157 | this.r[Rd] = this.memory.read32(addr); 2158 | 2159 | System.out.printf("ldr r%d, [r%d, 0x%02X]\n", Rd, Rn, Imm << 2); 2160 | } 2161 | else 2162 | { 2163 | int addr = this.r[Rn] + (Imm << 2); 2164 | int value = this.r[Rd]; 2165 | 2166 | this.memory.write32(addr, value); 2167 | 2168 | System.out.printf("str r%d, [r%d, 0x%02X]\n", Rd, Rn, Imm << 2); 2169 | } 2170 | } 2171 | 2172 | return; 2173 | } 2174 | 2175 | if ((opcode >> 12) == 8) 2176 | { 2177 | int Rd = (opcode >> 0) & 7; 2178 | int Rn = (opcode >> 3) & 7; 2179 | int Imm = (opcode >> 6) & 7; 2180 | 2181 | if ((opcode & 0x800) != 0) 2182 | { 2183 | int addr = this.r[Rn] + (Imm << 1); 2184 | 2185 | this.r[Rd] = this.memory.read16(addr); 2186 | 2187 | System.out.printf("ldrh r%d, [r%d, 0x%02X]\n", Rd, Rn, Imm << 1); 2188 | } 2189 | else 2190 | { 2191 | int addr = this.r[Rn] + (Imm << 1); 2192 | short value = (short) (this.r[Rd] & 0xFFFF); 2193 | 2194 | this.memory.write16(addr, value); 2195 | 2196 | System.out.printf("strh r%d, [r%d, 0x%02X]\n", Rd, Rn, Imm << 1); 2197 | } 2198 | 2199 | return; 2200 | } 2201 | 2202 | if ((opcode >> 12) == 9) 2203 | { 2204 | int Rd = (opcode >> 8) & 7; 2205 | int Imm = (opcode & 0xFF); 2206 | 2207 | if ((opcode & 0x800) != 0) 2208 | { 2209 | int addr = this.r[13] + (Imm << 2); 2210 | 2211 | this.r[Rd] = this.memory.read32(addr); 2212 | 2213 | System.out.printf("ldr r%d, [sp, 0x%02X]\n", Rd, Imm << 2); 2214 | } 2215 | else 2216 | { 2217 | int addr = this.r[13] + (Imm << 2); 2218 | int value = this.r[Rd]; 2219 | 2220 | this.memory.write32(addr, value); 2221 | 2222 | System.out.printf("str r%d, [sp, 0x%02X]\n", Rd, Imm << 2); 2223 | } 2224 | 2225 | return; 2226 | } 2227 | 2228 | if ((opcode >> 12) == 10) 2229 | { 2230 | int Rd = (opcode >> 8) & 7; 2231 | int Imm = (opcode & 0xFF); 2232 | 2233 | if ((opcode & 0x800) != 0) 2234 | { 2235 | this.r[Rd] = this.r[13] + (Imm << 2); 2236 | 2237 | System.out.printf("add r%d, sp, #0x%02X\n", Rd, Imm << 2); 2238 | } 2239 | else 2240 | { 2241 | this.r[Rd] = (this.r[15] & ~2) + (Imm << 2); 2242 | 2243 | System.out.printf("add r%d, pc, #0x%02X\n", Rd, Imm << 2); 2244 | } 2245 | 2246 | return; 2247 | } 2248 | 2249 | if ((opcode >> 12) == 11) 2250 | { 2251 | switch ((opcode >> 9) & 7) 2252 | { 2253 | case 0: 2254 | { // ADD/SUB 2255 | int Imm = (opcode & 0x7F); 2256 | 2257 | if ((opcode & 0x80) != 0) 2258 | { 2259 | this.r[13] -= Imm << 2; 2260 | System.out.printf("sub sp, #0x%02X\n", Imm << 2); 2261 | } 2262 | else 2263 | { 2264 | this.r[13] += Imm << 2; 2265 | System.out.printf("add sp, #0x%02X\n", Imm << 2); 2266 | } 2267 | 2268 | return; 2269 | } 2270 | 2271 | case 2: 2272 | { // PUSH 2273 | boolean lrf = (opcode & 0x100) != 0; 2274 | boolean pf = false; 2275 | 2276 | if (lrf) 2277 | { 2278 | push(this.r[14]); 2279 | } 2280 | 2281 | for (int i = 7; i >= 0; i--) 2282 | { 2283 | if (((opcode >> i) & 1) != 0) 2284 | { 2285 | push(this.r[i]); 2286 | } 2287 | } 2288 | 2289 | System.out.printf("push {"); 2290 | 2291 | for (int i = 0; i < 8; i++) 2292 | { 2293 | if (((opcode >> i) & 1) != 0) 2294 | { 2295 | if (pf) 2296 | { 2297 | System.out.printf(","); 2298 | } 2299 | System.out.printf("r%d", i); 2300 | 2301 | pf = true; 2302 | } 2303 | } 2304 | 2305 | if (lrf) 2306 | { 2307 | if (pf) 2308 | { 2309 | System.out.printf(","); 2310 | } 2311 | System.out.printf("lr"); 2312 | } 2313 | 2314 | System.out.printf("}\n"); 2315 | return; 2316 | } 2317 | 2318 | case 6: 2319 | { // POP 2320 | boolean pcf = (opcode & 0x100) != 0; 2321 | boolean pf = false; 2322 | 2323 | System.out.printf("pop {"); 2324 | 2325 | for (int i = 0; i < 8; i++) 2326 | { 2327 | if (((opcode >> i) & 1) != 0) 2328 | { 2329 | if (pf) 2330 | { 2331 | System.out.printf(","); 2332 | } 2333 | System.out.printf("r%d", i); 2334 | 2335 | this.r[i] = pop(); 2336 | pf = true; 2337 | } 2338 | } 2339 | 2340 | if (pcf) 2341 | { 2342 | if (pf) 2343 | { 2344 | System.out.printf(","); 2345 | } 2346 | System.out.printf("pc"); 2347 | 2348 | this.r[15] = pop(); 2349 | this.cpsr.t = (this.r[15] & 1) != 0; 2350 | } 2351 | 2352 | System.out.printf("}\n"); 2353 | return; 2354 | } 2355 | } 2356 | } 2357 | 2358 | if ((opcode >> 12) == 12) 2359 | { 2360 | int Rn = (opcode >> 8) & 7; 2361 | 2362 | if ((opcode & 0x800) != 0) 2363 | { 2364 | System.out.printf("ldmia r%d!, {", Rn); 2365 | 2366 | for (int i = 0; i < 8; i++) 2367 | { 2368 | if (((opcode >> i) & 1) != 0) 2369 | { 2370 | this.r[i] = this.memory.read32(this.r[Rn]); 2371 | this.r[Rn] += 4; 2372 | 2373 | System.out.printf("r%d,", i); 2374 | } 2375 | } 2376 | 2377 | System.out.printf("}\n"); 2378 | return; 2379 | } 2380 | else 2381 | { 2382 | System.out.printf("stmia r%d!, {", Rn); 2383 | 2384 | for (int i = 0; i < 8; i++) 2385 | { 2386 | if (((opcode >> i) & 1) != 0) 2387 | { 2388 | this.memory.write32(this.r[Rn], this.r[i]); 2389 | this.r[Rn] += 4; 2390 | 2391 | System.out.printf("r%d,", i); 2392 | } 2393 | } 2394 | 2395 | System.out.printf("}\n"); 2396 | return; 2397 | } 2398 | } 2399 | 2400 | if ((opcode >> 12) == 13) 2401 | { 2402 | int Imm = (opcode & 0xFF) << 1; 2403 | 2404 | if ((Imm & 0x100) != 0) 2405 | { 2406 | Imm = ~((~Imm) & 0xFF); 2407 | } 2408 | 2409 | Imm += 2; 2410 | 2411 | System.out.printf("b"); 2412 | condPrint(opcode); 2413 | System.out.printf(" 0x%08X\n", (this.r[15] + Imm)); 2414 | 2415 | if (condCheck(opcode)) 2416 | { 2417 | this.r[15] += Imm; 2418 | } 2419 | 2420 | return; 2421 | } 2422 | 2423 | if ((opcode >> 11) == 28) 2424 | { 2425 | int Imm = (opcode & 0x7FF) << 1; 2426 | 2427 | if ((Imm & (1 << 11)) != 0) 2428 | { 2429 | Imm = (~Imm) & 0xFFE; 2430 | this.r[15] -= Imm; 2431 | } 2432 | else 2433 | { 2434 | this.r[15] += Imm + 2; // 16-bit 2435 | } 2436 | 2437 | System.out.printf("b 0x%08X, 0x%X\n", this.r[15], Imm); 2438 | return; 2439 | } 2440 | 2441 | if ((opcode >> 11) == 0x1E) 2442 | { 2443 | boolean blx = false; 2444 | if ((opcode & (1 << 11)) == 0) 2445 | { 2446 | // H = 0 2447 | int Imm = ((opcode & 0x7FF) << 12); 2448 | 2449 | this.r[14] = this.r[15] + Imm; 2450 | } 2451 | else 2452 | { 2453 | // H = 1 2454 | int temp = this.r[15]; 2455 | 2456 | int Imm = ((opcode & 0x7FF) << 1); 2457 | 2458 | this.r[15] = this.r[14] + Imm; 2459 | this.r[14] = temp | 1; 2460 | 2461 | if ((Imm & (1 << 22)) != 0) 2462 | { 2463 | Imm = (~Imm) & 0x7FFFFE; 2464 | this.r[15] -= Imm; 2465 | } 2466 | else 2467 | { 2468 | this.r[15] += Imm + 2; 2469 | } 2470 | } 2471 | 2472 | if (blx) 2473 | { 2474 | this.cpsr.t = false; 2475 | System.out.printf("blx 0x%08X\n", this.r[15]); 2476 | } 2477 | else 2478 | { 2479 | System.out.printf("bl 0x%08X\n", this.r[15]); 2480 | } 2481 | 2482 | return; 2483 | } 2484 | 2485 | System.out.printf("Unknown opcode! (0x%04X)\n", opcode); 2486 | } 2487 | 2488 | /** 2489 | * @return 32-bit value. 2490 | */ 2491 | protected int pop() 2492 | { 2493 | int addr = this.r[13]; 2494 | 2495 | this.r[13] += 4; // 32-bit 2496 | 2497 | /* Read value */ 2498 | return this.memory.read32(addr); 2499 | } 2500 | 2501 | /** 2502 | * 32-bit value. 2503 | * 2504 | * @param value 2505 | */ 2506 | protected void push(int value) 2507 | { 2508 | /* Update SP */ 2509 | this.r[13] -= 4; // 32-bit 2510 | 2511 | /* Write value */ 2512 | this.memory.write32(this.r[13], value); 2513 | } 2514 | 2515 | /** 2516 | * 32-bit value/opcode. 2517 | * 2518 | * @param opcode 2519 | * @param value 2520 | * @return 2521 | */ 2522 | protected int shift(int opcode, int value) 2523 | { 2524 | boolean signed = ((opcode >> 20) & 1) == 1; 2525 | 2526 | int amt = (opcode >> 7) & 0x1F; 2527 | int result; 2528 | 2529 | if (amt == 0) 2530 | { 2531 | return value; 2532 | } 2533 | 2534 | switch ((opcode >> 5) & 3) 2535 | { 2536 | case 0: 2537 | if (signed) 2538 | { 2539 | this.cpsr.c = (value & (1 << (32 - amt))) == 1; 2540 | } 2541 | 2542 | result = LSL(value, amt); 2543 | break; 2544 | case 1: 2545 | if (signed) 2546 | { 2547 | this.cpsr.c = (value & (1 << (amt - 1))) == 1; 2548 | } 2549 | 2550 | result = LSR(value, amt); 2551 | break; 2552 | case 2: 2553 | if (signed) 2554 | { 2555 | this.cpsr.c = (value & (1 << (amt - 1))) == 1; 2556 | } 2557 | 2558 | result = ASR(value, amt); 2559 | break; 2560 | case 3: 2561 | result = ROR(value, amt); 2562 | break; 2563 | 2564 | default: 2565 | result = value; 2566 | } 2567 | 2568 | return result; 2569 | } 2570 | 2571 | /** 2572 | * 32-bit opcode. 2573 | * 2574 | * @param opcode 2575 | */ 2576 | protected void shiftPrint(int opcode) 2577 | { 2578 | int amt = (opcode >> 7) & 0x1F; 2579 | if (amt == 0) 2580 | { 2581 | return; 2582 | } 2583 | 2584 | switch ((opcode >> 5) & 3) 2585 | { 2586 | case 0: 2587 | System.out.printf(",LSL#%d", amt); 2588 | break; 2589 | case 1: 2590 | System.out.printf(",LSR#%d", amt); 2591 | break; 2592 | case 2: 2593 | System.out.printf(",ASR#%d", amt); 2594 | break; 2595 | case 3: 2596 | System.out.printf(",ROR#%d", amt); 2597 | break; 2598 | } 2599 | } 2600 | 2601 | /** 2602 | * 32-bit values. 2603 | * 2604 | * @param a 2605 | * @param b 2606 | * @return 2607 | */ 2608 | protected int subtract(int a, int b) 2609 | { 2610 | /* Subtract values */ 2611 | int result = a - b; 2612 | 2613 | /* Set flags */ 2614 | this.cpsr.c = !borrowFrom(a, b); 2615 | this.cpsr.v = overflowFrom(a, -b); 2616 | this.cpsr.z = result == 0; 2617 | this.cpsr.n = ((result >> 31) == 1); 2618 | 2619 | return result; 2620 | } 2621 | 2622 | /** 2623 | * 32-bit opcode. 2624 | * 2625 | * @param opcode 2626 | */ 2627 | protected void suffPrint(int opcode) 2628 | { 2629 | if (((opcode >> 20) & 1) != 0) 2630 | { 2631 | System.out.print("s"); 2632 | } 2633 | } 2634 | 2635 | /** 2636 | * @param aOpcode 2637 | * @return 2638 | */ 2639 | private boolean conditionCheck(ConditionCode aCode) 2640 | { 2641 | /* Check condition */ 2642 | switch (aCode) 2643 | { 2644 | case EQ: 2645 | return this.cpsr.z; 2646 | case NE: 2647 | return !this.cpsr.z; 2648 | case CS: 2649 | return this.cpsr.c; 2650 | case CC: 2651 | return !this.cpsr.c; 2652 | case MI: 2653 | return this.cpsr.n; 2654 | case PL: 2655 | return !this.cpsr.n; 2656 | case VS: 2657 | return this.cpsr.v; 2658 | case VC: 2659 | return !this.cpsr.v; 2660 | case HI: 2661 | return (this.cpsr.c && !this.cpsr.z); 2662 | case LS: 2663 | return (!this.cpsr.c || this.cpsr.z); 2664 | case GE: 2665 | return (this.cpsr.n == this.cpsr.v); 2666 | case LT: 2667 | return (this.cpsr.n != this.cpsr.v); 2668 | case GT: 2669 | return ((this.cpsr.n == this.cpsr.v) && !this.cpsr.z); 2670 | case LE: 2671 | return ((this.cpsr.n != this.cpsr.v) || this.cpsr.z); 2672 | case AL: 2673 | return true; 2674 | } 2675 | 2676 | return false; 2677 | } 2678 | } 2679 | -------------------------------------------------------------------------------- /src/main/java/nl/lxtreme/arm/ConditionCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm; 7 | 8 | 9 | /** 10 | * Represents the various condition codes. 11 | */ 12 | public enum ConditionCode 13 | { 14 | EQ, // 15 | NE, // 16 | CS, // 17 | CC, // 18 | MI, // 19 | PL, // 20 | VS, // 21 | VC, // 22 | HI, // 23 | LS, // 24 | GE, // 25 | LT, // 26 | GT, // 27 | LE, // 28 | AL; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/nl/lxtreme/arm/memory/Chunk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm.memory; 7 | 8 | 9 | import java.io.*; 10 | import java.util.*; 11 | 12 | 13 | /** 14 | * Denotes a "chunk" of memory, located at a certain address and with a certain 15 | * size. 16 | */ 17 | public class Chunk extends OutputStream 18 | { 19 | // VARIABLES 20 | 21 | private final long address; 22 | private final byte[] data; 23 | 24 | private long writePtr = 0L; 25 | 26 | // CONSTRUCTORS 27 | 28 | /** 29 | * Creates a new Chunk instance. 30 | * 31 | * @param aAddress 32 | * @param aSize 33 | */ 34 | public Chunk( long aAddress, int aSize ) 35 | { 36 | if ( aSize <= 0 ) 37 | { 38 | throw new IllegalArgumentException( "Illegal memory size!" ); 39 | } 40 | 41 | this.address = aAddress; 42 | this.data = new byte[aSize]; 43 | 44 | Arrays.fill( this.data, ( byte )0xff ); 45 | } 46 | 47 | // METHODS 48 | 49 | /** 50 | * {@inheritDoc} 51 | */ 52 | @Override 53 | public void close() throws IOException 54 | { 55 | // NO-op 56 | this.writePtr = -1; 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | */ 62 | @Override 63 | public void flush() throws IOException 64 | { 65 | // NO-op 66 | } 67 | 68 | /** 69 | * Returns the base address for this chunk. 70 | * 71 | * @return the base address, >= 0. 72 | */ 73 | public long getBaseAddress() 74 | { 75 | return this.address; 76 | } 77 | 78 | /** 79 | * Returns the size of this chunk. 80 | * 81 | * @return a chunk size, > 0. 82 | */ 83 | public int getSize() 84 | { 85 | return this.data.length; 86 | } 87 | 88 | /** 89 | * Returns whether the given address is mapped by this chunk. 90 | * 91 | * @param aAddress 92 | * the address that should map to this chunk. 93 | * @return true if the given address maps to this chunk, 94 | * false otherwise. 95 | */ 96 | public boolean maps( long aAddress ) 97 | { 98 | int addr = mapAddress( aAddress ); 99 | return ( addr >= 0 ) && ( addr < getSize() ); 100 | } 101 | 102 | /** 103 | * Reads a 16-bit value from this memory at the given address. 104 | * 105 | * @param aAddr 106 | * the memory location to read. 107 | * @return the 16-bit value at the given memory location. 108 | */ 109 | public short read16( int aAddr ) 110 | { 111 | int addr = mapAddress( aAddr ); 112 | if ( validAddress( addr ) ) 113 | { 114 | int msb = ( this.data[addr + 0] & 0xFF ); 115 | int lsb = ( this.data[addr + 1] & 0xFF ); 116 | return ( short )( ( msb << 8 ) | lsb ); 117 | } 118 | else 119 | { 120 | throw new IllegalArgumentException( String.format( "Invalid address to read: 0x%08x", aAddr ) ); 121 | } 122 | } 123 | 124 | /** 125 | * Reads a 32-bit value from this memory at the given address. 126 | * 127 | * @param aAddr 128 | * the memory location to read. 129 | * @return the 32-bit value at the given memory location. 130 | */ 131 | public int read32( int aAddr ) 132 | { 133 | int addr = mapAddress( aAddr ); 134 | if ( validAddress( addr ) ) 135 | { 136 | int b1 = this.data[addr + 0] & 0xff; 137 | int b2 = this.data[addr + 1] & 0xff; 138 | int b3 = this.data[addr + 2] & 0xff; 139 | int b4 = this.data[addr + 3] & 0xff; 140 | return ( b1 << 24 ) | ( b2 << 16 ) | ( b3 << 8 ) | b4; 141 | } 142 | else 143 | { 144 | throw new IllegalArgumentException( String.format( "Invalid address to read: 0x%08x", aAddr ) ); 145 | } 146 | } 147 | 148 | /** 149 | * Reads a 8-bit value from this memory at the given address. 150 | * 151 | * @param aAddr 152 | * the memory location to read. 153 | * @return the 8-bit value at the given memory location. 154 | */ 155 | public byte read8( int aAddr ) 156 | { 157 | int addr = mapAddress( aAddr ); 158 | if ( validAddress( addr ) ) 159 | { 160 | return this.data[addr]; 161 | } 162 | else 163 | { 164 | throw new IllegalArgumentException( String.format( "Invalid address to read: 0x%08x", aAddr ) ); 165 | } 166 | } 167 | 168 | /** 169 | * {@inheritDoc} 170 | */ 171 | @Override 172 | public String toString() 173 | { 174 | return String.format( "Chunk @ 0x%08x: %d bytes", this.address, this.data.length ); 175 | } 176 | 177 | @Override 178 | public void write( int aByte ) throws IOException 179 | { 180 | if ( this.writePtr < 0 ) 181 | { 182 | throw new IOException( "Writer is closed!" ); 183 | } 184 | 185 | this.data[( int )this.writePtr++] = ( byte )aByte; 186 | } 187 | 188 | /** 189 | * Writes a 16-bit value to the memory denoted by the given address. 190 | * 191 | * @param aAddr 192 | * the memory location to write; 193 | * @param aValue 194 | * the 16-bit value to write. 195 | */ 196 | public void write16( int aAddr, short aValue ) 197 | { 198 | int addr = mapAddress( aAddr ); 199 | if ( validAddress( addr ) ) 200 | { 201 | this.data[addr + 0] = ( byte )( ( aValue >> 8 ) & 0xff ); 202 | this.data[addr + 1] = ( byte )( aValue & 0xff ); 203 | } 204 | else 205 | { 206 | throw new IllegalArgumentException( String.format( "Invalid address to write: 0x%08x", aAddr ) ); 207 | } 208 | } 209 | 210 | /** 211 | * Writes a 32-bit value to the memory denoted by the given address. 212 | * 213 | * @param aAddr 214 | * the memory location to write; 215 | * @param aValue 216 | * the 32-bit value to write. 217 | */ 218 | public void write32( int aAddr, int aValue ) 219 | { 220 | int addr = mapAddress( aAddr ); 221 | if ( validAddress( addr ) ) 222 | { 223 | this.data[addr + 0] = ( byte )( ( aValue >> 24 ) & 0xff ); 224 | this.data[addr + 1] = ( byte )( ( aValue >> 16 ) & 0xff ); 225 | this.data[addr + 2] = ( byte )( ( aValue >> 8 ) & 0xff ); 226 | this.data[addr + 3] = ( byte )( aValue & 0xff ); 227 | } 228 | else 229 | { 230 | throw new IllegalArgumentException( String.format( "Invalid address to write: 0x%08x", aAddr ) ); 231 | } 232 | } 233 | 234 | /** 235 | * Writes a 8-bit value to the memory denoted by the given address. 236 | * 237 | * @param aAddr 238 | * the memory location to write; 239 | * @param aValue 240 | * the 8-bit value to write. 241 | */ 242 | public void write8( int aAddr, byte aValue ) 243 | { 244 | int addr = mapAddress( aAddr ); 245 | if ( validAddress( addr ) ) 246 | { 247 | this.data[addr] = aValue; 248 | } 249 | else 250 | { 251 | throw new IllegalArgumentException( String.format( "Invalid address to write: 0x%08x", aAddr ) ); 252 | } 253 | } 254 | 255 | /** 256 | * @param aAddr 257 | * @return 258 | */ 259 | private int mapAddress( long aAddr ) 260 | { 261 | long addr = aAddr - this.address; 262 | if ( addr < 0 ) 263 | { 264 | addr -= 1; 265 | } 266 | return ( int )( addr & 0xFFFFFFFF ); 267 | } 268 | 269 | /** 270 | * @param aAddr 271 | * @return 272 | */ 273 | private boolean validAddress( int aAddr ) 274 | { 275 | long addr = aAddr & 0xFFFFFFFF; 276 | return ( addr >= 0 ) && ( addr < this.data.length ); 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /src/main/java/nl/lxtreme/arm/memory/Memory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm.memory; 7 | 8 | 9 | import java.util.*; 10 | 11 | 12 | /** 13 | * Denotes a memory map, containing various chunks of data. 14 | */ 15 | public class Memory 16 | { 17 | // VARIABLES 18 | 19 | private final List chunks; 20 | 21 | // CONSTRUCTORS 22 | 23 | /** 24 | * Creates a new Memory instance. 25 | */ 26 | public Memory() 27 | { 28 | this.chunks = new ArrayList(); 29 | } 30 | 31 | // METHODS 32 | 33 | /** 34 | * Creates a new chunk of memory and adds this to this map. If there is 35 | * already a chunk of memory for the given address range, this method will do 36 | * nothing. 37 | * 38 | * @param aAddress 39 | * the base address of the memory chunk; 40 | * @param aSize 41 | * the size of the memory chunk. 42 | * @return the (newly created) memory chunk, never null. 43 | */ 44 | public synchronized Chunk create(long aAddress, int aSize) 45 | { 46 | Chunk result = find(aAddress); 47 | if (result == null) 48 | { 49 | result = new Chunk(aAddress, aSize); 50 | this.chunks.add(result); 51 | } 52 | return result; 53 | } 54 | 55 | /** 56 | * Finds a chunk of memory that maps the given address. 57 | * 58 | * @param aAddress 59 | * the address to return the memory chunk for. 60 | * @return a memory chunk for the given address, can be null if 61 | * no chunk maps to the given address. 62 | */ 63 | public Chunk find(long aAddress) 64 | { 65 | for (Chunk c : this.chunks) 66 | { 67 | if (c.maps(aAddress)) 68 | { 69 | return c; 70 | } 71 | } 72 | return null; 73 | } 74 | 75 | /** 76 | * Reads a 16-bit value from this memory at the given address. 77 | * 78 | * @param aAddr 79 | * the memory location to read. 80 | * @return the 16-bit value at the given memory location. 81 | */ 82 | public short read16(int aAddr) 83 | { 84 | Chunk chunk = find(aAddr); 85 | if (chunk != null) 86 | { 87 | return chunk.read16(aAddr); 88 | } 89 | else 90 | { 91 | System.out.printf("Ignoring read from invalid address: 0x%08x\n", aAddr); 92 | return 0x0; 93 | } 94 | } 95 | 96 | /** 97 | * Reads a 32-bit value from this memory at the given address. 98 | * 99 | * @param aAddr 100 | * the memory location to read. 101 | * @return the 32-bit value at the given memory location. 102 | */ 103 | public int read32(int aAddr) 104 | { 105 | Chunk chunk = find(aAddr); 106 | if (chunk != null) 107 | { 108 | return chunk.read32(aAddr); 109 | } 110 | else 111 | { 112 | System.out.printf("Ignoring read from invalid address: 0x%08x\n", aAddr); 113 | return 0x00; 114 | } 115 | } 116 | 117 | /** 118 | * Reads a 8-bit value from this memory at the given address. 119 | * 120 | * @param aAddr 121 | * the memory location to read. 122 | * @return the 8-bit value at the given memory location. 123 | */ 124 | public byte read8(int aAddr) 125 | { 126 | Chunk chunk = find(aAddr); 127 | if (chunk != null) 128 | { 129 | return chunk.read8(aAddr); 130 | } 131 | else 132 | { 133 | System.out.printf("Ignoring read from invalid address: 0x%08x\n", aAddr); 134 | return 0x00; 135 | } 136 | } 137 | 138 | /** 139 | * Writes a 16-bit value to the memory denoted by the given address. 140 | * 141 | * @param aAddr 142 | * the memory location to write; 143 | * @param aValue 144 | * the 16-bit value to write. 145 | */ 146 | public void write16(int aAddr, short aValue) 147 | { 148 | Chunk chunk = find(aAddr); 149 | if (chunk != null) 150 | { 151 | chunk.write16(aAddr, aValue); 152 | } 153 | else 154 | { 155 | System.out.printf("Ignoring write to invalid address: 0x%08x\n", aAddr); 156 | } 157 | } 158 | 159 | /** 160 | * Writes a 32-bit value to the memory denoted by the given address. 161 | * 162 | * @param aAddr 163 | * the memory location to write; 164 | * @param aValue 165 | * the 32-bit value to write. 166 | */ 167 | public void write32(int aAddr, int aValue) 168 | { 169 | Chunk chunk = find(aAddr); 170 | if (chunk != null) 171 | { 172 | chunk.write32(aAddr, aValue); 173 | } 174 | else 175 | { 176 | System.out.printf("Ignoring write to invalid address: 0x%08x\n", aAddr); 177 | } 178 | } 179 | 180 | /** 181 | * Writes a 8-bit value to the memory denoted by the given address. 182 | * 183 | * @param aAddr 184 | * the memory location to write; 185 | * @param aValue 186 | * the 8-bit value to write. 187 | */ 188 | public void write8(int aAddr, byte aValue) 189 | { 190 | Chunk chunk = find(aAddr); 191 | if (chunk != null) 192 | { 193 | chunk.write8(aAddr, aValue); 194 | } 195 | else 196 | { 197 | System.out.printf("Ignoring write to invalid address: 0x%08x\n", aAddr); 198 | } 199 | } 200 | 201 | } 202 | -------------------------------------------------------------------------------- /src/test/java/nl/lxtreme/arm/ArmShiftTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm; 7 | 8 | 9 | import static nl.lxtreme.arm.Arm.*; 10 | import static org.junit.Assert.*; 11 | 12 | import org.junit.*; 13 | 14 | 15 | /** 16 | * Tests the various shifting operations. 17 | */ 18 | public class ArmShiftTest 19 | { 20 | // METHODS 21 | 22 | /** 23 | * Test method for {@link nl.lxtreme.arm.Arm#ASR(int, int)}. 24 | */ 25 | @Test 26 | public void testASR() 27 | { 28 | assertEquals(0xC0000000, ASR(0x80000000, 1)); 29 | assertEquals(0xE0000000, ASR(0x80000000, 2)); 30 | assertEquals(0xF0000000, ASR(0x80000000, 3)); 31 | assertEquals(0xF8000000, ASR(0x80000000, 4)); 32 | assertEquals(0x04000000, ASR(0x08000000, 1)); 33 | assertEquals(0x02000000, ASR(0x08000000, 2)); 34 | assertEquals(0x01000000, ASR(0x08000000, 3)); 35 | assertEquals(0x00000004, ASR(0x00000008, 1)); 36 | } 37 | 38 | /** 39 | * Test method for {@link nl.lxtreme.arm.Arm#LSL(int, int)}. 40 | */ 41 | @Test 42 | public void testLSL() 43 | { 44 | assertEquals(0x80000000, LSL(0xC0000000, 1)); 45 | assertEquals(0x80000000, LSL(0xE0000000, 2)); 46 | assertEquals(0x80000000, LSL(0xF0000000, 3)); 47 | assertEquals(0x80000000, LSL(0xF8000000, 4)); 48 | assertEquals(0x08000000, LSL(0x04000000, 1)); 49 | assertEquals(0x08000000, LSL(0x02000000, 2)); 50 | assertEquals(0x08000000, LSL(0x01000000, 3)); 51 | assertEquals(0x00000008, LSL(0x00000004, 1)); 52 | } 53 | 54 | /** 55 | * Test method for {@link nl.lxtreme.arm.Arm#LSR(int, int)}. 56 | */ 57 | @Test 58 | public void testLSR() 59 | { 60 | assertEquals(0x40000000, LSR(0x80000000, 1)); 61 | assertEquals(0x20000000, LSR(0x80000000, 2)); 62 | assertEquals(0x10000000, LSR(0x80000000, 3)); 63 | assertEquals(0x08000000, LSR(0x80000000, 4)); 64 | assertEquals(0x04000000, LSR(0x08000000, 1)); 65 | assertEquals(0x02000000, LSR(0x08000000, 2)); 66 | assertEquals(0x01000000, LSR(0x08000000, 3)); 67 | assertEquals(0x00000004, LSR(0x00000008, 1)); 68 | } 69 | 70 | /** 71 | * Test method for {@link nl.lxtreme.arm.Arm#ROR(int, int)}. 72 | */ 73 | @Test 74 | public void testROR() 75 | { 76 | assertEquals(0x80000000, ROR(0x00000001, 1)); 77 | assertEquals(0x40000000, ROR(0x00000001, 2)); 78 | assertEquals(0x20000000, ROR(0x00000001, 3)); 79 | assertEquals(0x20000000, ROR(0x80000000, 2)); 80 | assertEquals(0x10000000, ROR(0x80000000, 3)); 81 | assertEquals(0x08000000, ROR(0x80000000, 4)); 82 | assertEquals(0x04000000, ROR(0x08000000, 1)); 83 | assertEquals(0x02000000, ROR(0x08000000, 2)); 84 | assertEquals(0x01000000, ROR(0x08000000, 3)); 85 | assertEquals(0x00000004, ROR(0x00000008, 1)); 86 | } 87 | 88 | /** 89 | * Test method for {@link nl.lxtreme.arm.Arm#RRX(int, int)}. 90 | */ 91 | @Test 92 | public void testRRX() 93 | { 94 | assertEquals(0x80000000, RRX(0x00000000, 1)); 95 | assertEquals(0x80000000, RRX(0x00000001, 1)); 96 | assertEquals(0x00000000, RRX(0x00000000, 0)); 97 | assertEquals(0x00000000, RRX(0x00000001, 0)); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/nl/lxtreme/arm/ArmTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm; 7 | 8 | 9 | import static org.junit.Assert.*; 10 | 11 | import java.io.*; 12 | import java.net.*; 13 | 14 | import nl.lxtreme.arm.memory.*; 15 | import nl.lxtreme.binutils.elf.*; 16 | import nl.lxtreme.binutils.hex.*; 17 | 18 | import org.junit.*; 19 | 20 | 21 | /** 22 | * 23 | */ 24 | public class ArmTest 25 | { 26 | // CONSTANTS 27 | 28 | private static final int STACK_SIZE = (8 * 1024); 29 | 30 | private final int[] thumb = { 31 | 0xb410, // push {r4} 32 | 0xf64f, 0x7cee, // movw ip, #65518 ; 0xffee 33 | 0xf243, 0x3444, // movw r4, #13124 ; 0x3344 34 | 0x2300, // movs r3, #0 35 | 0xf2c1, 0x1422, // movt r4, #4386 ; 0x1122 36 | 0xf2c0, 0x0cc0, // movt ip, #192 ; 0xc0 37 | 0x43d8, // mvns r0, r3 38 | 0x6023, // str r3, [r4, #0] 39 | 0x3301, // adds r3, #1 40 | 0xf243, 0x3144, // movw r1, #13124 ; 0x3344 41 | 0xf000, 0x00c3, // and.w r0, r0, #195 ; 0xc3 42 | 0xf64f, 0x72ee, // movw r2, #65518 ; 0xffee 43 | 0x2b80, // cmp r3, #128 ; 0x80 44 | 0xf2c1, 0x1122, // movt r1, #4386 ; 0x1122 45 | 0xf2c0, 0x02c0, // movt r2, #192 ; 0xc0 46 | 0xf8cc, 0x0000, // str.w r0, [ip] 47 | 0xd1ee, // bne.n 8014 48 | 0x680b, // ldr r3, [r1, #0] 49 | 0x6810, // ldr r0, [r2, #0] 50 | 0x4218, // tst r0, r3 51 | 0xd104, // bne.n 8048 52 | 0x2399, // movs r3, #153 ; 0x99 53 | 0x6013, // str r3, [r2, #0] 54 | 0x2000, // movs r0, #0 55 | 0xbc10, // pop {r4} 56 | 0x4770, // bx lr 57 | 0x2377, // movs r3, #119 ; 0x77 58 | 0x600b, // str r3, [r1, #0] 59 | 0xe7f9, // b.n 8042 60 | 0xbf00 // nop 61 | }; 62 | 63 | // VARIABLES 64 | 65 | private Memory m; 66 | private Arm arm; 67 | 68 | // METHODS 69 | 70 | /** 71 | * @throws java.lang.Exception 72 | */ 73 | @Before 74 | public void setUp() throws Exception 75 | { 76 | this.m = new Memory(); 77 | // Initial stack of 8Kb... 78 | this.m.create(0xFFFFFFFFL - STACK_SIZE, STACK_SIZE); 79 | this.arm = new Arm(this.m); 80 | } 81 | 82 | /** 83 | * 84 | */ 85 | @Test 86 | public void testB() 87 | { 88 | this.m.create(0, 4096); 89 | 90 | this.m.write32(0, 0xEA000006); 91 | this.arm.step(); 92 | 93 | this.arm.reset(); 94 | 95 | this.m.write32(0, 0xDA000009); 96 | this.arm.step(); 97 | 98 | this.arm.reset(); 99 | 100 | this.m.write32(0, 0x112fffff); 101 | this.arm.step(); 102 | } 103 | 104 | /** 105 | * @throws Exception 106 | */ 107 | @Test 108 | public void testElfExample1() throws Exception 109 | { 110 | File elfFile = getFileResource("helloWorld_static"); 111 | Elf elf = new Elf(elfFile); 112 | 113 | for (ProgramHeader ph : elf.getProgramHeaders()) 114 | { 115 | int size = (int) ph.getMemorySize(); 116 | if (size <= 0) 117 | { 118 | continue; 119 | } 120 | 121 | Chunk chunk = this.m.create(ph.getVirtualAddress(), size); 122 | elf.readSegment(ph, chunk); 123 | } 124 | 125 | this.arm = new Arm(this.m); 126 | this.arm.setPC((int) elf.getHeader().getEntryPoint()); 127 | 128 | int i = 500; 129 | while (i-- >= 0) 130 | { 131 | this.arm.step(); 132 | } 133 | } 134 | 135 | /** 136 | * @throws Exception 137 | */ 138 | @Test 139 | public void testElfExample2() throws Exception 140 | { 141 | File elfFile = getFileResource("helloWorld_loop"); 142 | Elf elf = new Elf(elfFile); 143 | 144 | for (ProgramHeader ph : elf.getProgramHeaders()) 145 | { 146 | int size = (int) ph.getMemorySize(); 147 | if (size <= 0) 148 | { 149 | continue; 150 | } 151 | 152 | Chunk chunk = this.m.create(ph.getVirtualAddress(), size); 153 | elf.readSegment(ph, chunk); 154 | } 155 | 156 | this.arm = new Arm(this.m); 157 | this.arm.setPC((int) elf.getHeader().getEntryPoint()); 158 | 159 | int i = 500; 160 | while (i-- >= 0) 161 | { 162 | this.arm.step(); 163 | } 164 | } 165 | 166 | /** 167 | * 168 | */ 169 | @Test 170 | public void testExample1() throws Exception 171 | { 172 | this.m.create(0, 4096); 173 | 174 | loadIntelHexResource("blinkingLEDAndButton.hex"); 175 | 176 | int i = 250; 177 | while (i-- >= 0) 178 | { 179 | this.arm.step(); 180 | } 181 | } 182 | 183 | /** 184 | * 185 | */ 186 | @Test 187 | public void testExample2() throws Exception 188 | { 189 | this.m.create(0, 4096); 190 | 191 | loadIntelHexResource("arm7tdmi_Blinky_iFlash.hex"); 192 | 193 | int i = 250; 194 | while (i-- >= 0) 195 | { 196 | this.arm.step(); 197 | } 198 | } 199 | 200 | /** 201 | * 202 | */ 203 | @Test 204 | public void testExample3() throws Exception 205 | { 206 | this.m.create(0, 4096); 207 | 208 | loadIntelHexResource("led.hex"); 209 | 210 | int i = 250; 211 | while (i-- >= 0) 212 | { 213 | this.arm.step(); 214 | } 215 | } 216 | 217 | /** 218 | * 219 | */ 220 | @Test 221 | public void testExample4() throws Exception 222 | { 223 | this.m.create(0, 4096); 224 | 225 | loadIntelHexResource("rtcAndInterruptExample.hex"); 226 | 227 | int i = 250; 228 | while (i-- >= 0) 229 | { 230 | this.arm.step(); 231 | } 232 | } 233 | 234 | /** 235 | * 236 | */ 237 | @Test 238 | public void testExample5() throws Exception 239 | { 240 | this.m.create(0, 4096); 241 | 242 | loadIntelHexResource("blinking_leds.hex"); 243 | 244 | int i = 250; 245 | while (i-- >= 0) 246 | { 247 | this.arm.step(); 248 | } 249 | } 250 | 251 | /** 252 | * 253 | */ 254 | @Test 255 | public void testThumbOk() throws Exception 256 | { 257 | this.m.create(0, 9216); 258 | 259 | for (int i = 0, address = 0; i < this.thumb.length; i++) 260 | { 261 | this.m.write16(address, (short) (this.thumb[i] & 0xFFFF)); 262 | address += 2; 263 | } 264 | 265 | this.arm.forceThumbMode(); 266 | 267 | int i = 250; 268 | while (i-- >= 0) 269 | { 270 | this.arm.step(); 271 | } 272 | } 273 | 274 | /** 275 | * @param aName 276 | * @throws IOException 277 | */ 278 | private File getFileResource(final String aName) throws IOException 279 | { 280 | URL url = getClass().getClassLoader().getResource(aName); 281 | if ((url != null) && "file".equals(url.getProtocol())) 282 | { 283 | return new File(url.getPath()).getCanonicalFile(); 284 | } 285 | fail("Resource " + aName + " not found!"); 286 | return null; // to keep compiler happy... 287 | } 288 | 289 | /** 290 | * @param aName 291 | * @throws IOException 292 | */ 293 | private void loadIntelHexResource(final String aName) throws IOException 294 | { 295 | InputStream is = getClass().getClassLoader().getResourceAsStream(aName); 296 | if (is != null) 297 | { 298 | IntelHexReader reader = new IntelHexReader(new InputStreamReader(is)); 299 | 300 | int instr = -1; 301 | int address = 0x00; 302 | while ((instr = reader.readLongWord()) != -1) 303 | { 304 | this.m.write32(address, instr); 305 | address += 4; 306 | } 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /src/test/java/nl/lxtreme/arm/CpsrTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm; 7 | 8 | 9 | import static org.junit.Assert.*; 10 | import nl.lxtreme.arm.Arm.Cpsr; 11 | 12 | import org.junit.*; 13 | 14 | 15 | /** 16 | * Test cases for {@link Cpsr}. 17 | */ 18 | public class CpsrTest 19 | { 20 | // VARIABLES 21 | 22 | private Cpsr cpsr; 23 | 24 | // METHODS 25 | 26 | /** 27 | * @throws java.lang.Exception 28 | */ 29 | @Before 30 | public void setUp() throws Exception 31 | { 32 | this.cpsr = new Cpsr(); 33 | } 34 | 35 | /** 36 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 37 | */ 38 | @Test 39 | public void testGetValue_A() 40 | { 41 | this.cpsr.A = true; 42 | assertEquals(1 << 8, this.cpsr.getValue()); 43 | } 44 | 45 | /** 46 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 47 | */ 48 | @Test 49 | public void testGetValue_c() 50 | { 51 | this.cpsr.c = true; 52 | assertEquals(1 << 29, this.cpsr.getValue()); 53 | } 54 | 55 | /** 56 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 57 | */ 58 | @Test 59 | public void testGetValue_E() 60 | { 61 | this.cpsr.E = true; 62 | assertEquals(1 << 9, this.cpsr.getValue()); 63 | } 64 | 65 | /** 66 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 67 | */ 68 | @Test 69 | public void testGetValue_F() 70 | { 71 | this.cpsr.F = true; 72 | assertEquals(1 << 6, this.cpsr.getValue()); 73 | } 74 | 75 | /** 76 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 77 | */ 78 | @Test 79 | public void testGetValue_ge() 80 | { 81 | this.cpsr.ge = 0x0F; 82 | assertEquals(0xF0000, this.cpsr.getValue()); 83 | } 84 | 85 | /** 86 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 87 | */ 88 | @Test 89 | public void testGetValue_I() 90 | { 91 | this.cpsr.I = true; 92 | assertEquals(1 << 7, this.cpsr.getValue()); 93 | } 94 | 95 | /** 96 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 97 | */ 98 | @Test 99 | public void testGetValue_it() 100 | { 101 | this.cpsr.it = 0xFF; 102 | assertEquals(0x600FC00, this.cpsr.getValue()); 103 | } 104 | 105 | /** 106 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 107 | */ 108 | @Test 109 | public void testGetValue_mode() 110 | { 111 | this.cpsr.mode = 0x1F; 112 | assertEquals(0x1F, this.cpsr.getValue()); 113 | } 114 | 115 | /** 116 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 117 | */ 118 | @Test 119 | public void testGetValue_n() 120 | { 121 | this.cpsr.n = true; 122 | assertEquals(1 << 31, this.cpsr.getValue()); 123 | } 124 | 125 | /** 126 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 127 | */ 128 | @Test 129 | public void testGetValue_q() 130 | { 131 | this.cpsr.q = true; 132 | assertEquals(1 << 27, this.cpsr.getValue()); 133 | } 134 | 135 | /** 136 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 137 | */ 138 | @Test 139 | public void testGetValue_t() 140 | { 141 | this.cpsr.t = true; 142 | assertEquals(1 << 5, this.cpsr.getValue()); 143 | } 144 | 145 | /** 146 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 147 | */ 148 | @Test 149 | public void testGetValue_v() 150 | { 151 | this.cpsr.v = true; 152 | assertEquals(1 << 28, this.cpsr.getValue()); 153 | } 154 | 155 | /** 156 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#getValue()}. 157 | */ 158 | @Test 159 | public void testGetValue_z() 160 | { 161 | this.cpsr.z = true; 162 | assertEquals(1 << 30, this.cpsr.getValue()); 163 | } 164 | 165 | /** 166 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 167 | */ 168 | @Test 169 | public void testSetValue_A() 170 | { 171 | this.cpsr.setValue(1 << 8); 172 | assertTrue(this.cpsr.A); 173 | } 174 | 175 | /** 176 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 177 | */ 178 | @Test 179 | public void testSetValue_c() 180 | { 181 | this.cpsr.setValue(1 << 29); 182 | assertTrue(this.cpsr.c); 183 | } 184 | 185 | /** 186 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 187 | */ 188 | @Test 189 | public void testSetValue_E() 190 | { 191 | this.cpsr.setValue(1 << 9); 192 | assertTrue(this.cpsr.E); 193 | } 194 | 195 | /** 196 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 197 | */ 198 | @Test 199 | public void testSetValue_F() 200 | { 201 | this.cpsr.setValue(1 << 6); 202 | assertTrue(this.cpsr.F); 203 | } 204 | 205 | /** 206 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 207 | */ 208 | @Test 209 | public void testSetValue_ge() 210 | { 211 | this.cpsr.setValue(0xF0000); 212 | assertEquals(0x0F, this.cpsr.ge); 213 | } 214 | 215 | /** 216 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 217 | */ 218 | @Test 219 | public void testSetValue_I() 220 | { 221 | this.cpsr.setValue(1 << 7); 222 | assertTrue(this.cpsr.I); 223 | } 224 | 225 | /** 226 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 227 | */ 228 | @Test 229 | public void testSetValue_it() 230 | { 231 | this.cpsr.setValue(0x600FC00); 232 | assertEquals(0xFF, this.cpsr.it); 233 | 234 | this.cpsr.setValue(0xFC00); 235 | assertEquals(0xFC, this.cpsr.it); 236 | 237 | this.cpsr.setValue(0x6000000); 238 | assertEquals(0x3, this.cpsr.it); 239 | } 240 | 241 | /** 242 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 243 | */ 244 | @Test 245 | public void testSetValue_mode() 246 | { 247 | this.cpsr.setValue(0x1F); 248 | assertEquals(0x1F, this.cpsr.mode); 249 | } 250 | 251 | /** 252 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 253 | */ 254 | @Test 255 | public void testSetValue_n() 256 | { 257 | this.cpsr.setValue(1 << 31); 258 | assertTrue(this.cpsr.n); 259 | } 260 | 261 | /** 262 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 263 | */ 264 | @Test 265 | public void testSetValue_q() 266 | { 267 | this.cpsr.setValue(1 << 27); 268 | assertTrue(this.cpsr.q); 269 | } 270 | 271 | /** 272 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 273 | */ 274 | @Test 275 | public void testSetValue_t() 276 | { 277 | this.cpsr.setValue(1 << 5); 278 | assertTrue(this.cpsr.t); 279 | } 280 | 281 | /** 282 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 283 | */ 284 | @Test 285 | public void testSetValue_v() 286 | { 287 | this.cpsr.setValue(1 << 28); 288 | assertTrue(this.cpsr.v); 289 | } 290 | 291 | /** 292 | * Test method for {@link nl.lxtreme.arm.Arm.Cpsr#setValue(int)}. 293 | */ 294 | @Test 295 | public void testSetValue_z() 296 | { 297 | this.cpsr.setValue(1 << 30); 298 | assertTrue(this.cpsr.z); 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /src/test/java/nl/lxtreme/arm/memory/ChunkTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm.memory; 7 | 8 | 9 | import static org.junit.Assert.*; 10 | 11 | import org.junit.*; 12 | 13 | 14 | /** 15 | * Test cases for {@link Chunk}. 16 | */ 17 | public class ChunkTest 18 | { 19 | // VARIABLES 20 | 21 | private Chunk chunk; 22 | 23 | // METHODS 24 | 25 | /** 26 | * @throws java.lang.Exception 27 | */ 28 | @Before 29 | public void setUp() throws Exception 30 | { 31 | this.chunk = new Chunk(0x0, 32); 32 | } 33 | 34 | /** 35 | * Test method for {@link nl.lxtreme.arm.Memory#write16(int, short)}. 36 | */ 37 | @Test 38 | public void testReadWrite16() 39 | { 40 | short v1 = (short) 0xabcd; 41 | short v2 = (short) 0x1234; 42 | 43 | this.chunk.write16(0, v1); 44 | this.chunk.write16(2, v2); 45 | 46 | assertEquals(v1, this.chunk.read16(0)); 47 | assertEquals(v2, this.chunk.read16(2)); 48 | } 49 | 50 | /** 51 | * Test method for {@link nl.lxtreme.arm.Memory#write32(int, int)}. 52 | */ 53 | @Test 54 | public void testReadWrite32() 55 | { 56 | int v1 = 0x12345678; 57 | int v2 = 0x9abcdef0; 58 | 59 | this.chunk.write32(0, v1); 60 | this.chunk.write32(4, v2); 61 | 62 | assertEquals(v1, this.chunk.read32(0)); 63 | assertEquals(v2, this.chunk.read32(4)); 64 | } 65 | 66 | /** 67 | * Test method for {@link nl.lxtreme.arm.Memory#write8(int, byte)}. 68 | */ 69 | @Test 70 | public void testReadWrite8() 71 | { 72 | byte v1 = (byte) 0xAA; 73 | byte v2 = (byte) 0x55; 74 | 75 | this.chunk.write8(0, v1); 76 | this.chunk.write8(1, v2); 77 | 78 | assertEquals(v2, this.chunk.read8(1)); 79 | assertEquals(v1, this.chunk.read8(0)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/nl/lxtreme/arm/memory/MemoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Java ARM-emu. 3 | * 4 | * (C) Copyright 2011-2012, J.W. Janssen 5 | */ 6 | package nl.lxtreme.arm.memory; 7 | 8 | 9 | import static org.junit.Assert.*; 10 | 11 | import org.junit.*; 12 | 13 | 14 | /** 15 | * Test cases for {@link Memory}. 16 | */ 17 | public class MemoryTest 18 | { 19 | // VARIABLES 20 | 21 | private Memory memory; 22 | 23 | // METHODS 24 | 25 | /** 26 | * @throws java.lang.Exception 27 | */ 28 | @Before 29 | public void setUp() throws Exception 30 | { 31 | this.memory = new Memory(); 32 | } 33 | 34 | /** 35 | * Test method for {@link nl.lxtreme.arm.memory.Memory#create(long, int)}. 36 | */ 37 | @Test 38 | public void testCreate() 39 | { 40 | Chunk c1 = this.memory.create(0, 100); 41 | assertNotNull(c1); 42 | 43 | Chunk c2 = this.memory.create(200, 100); 44 | assertNotSame(c1, c2); 45 | 46 | Chunk c3 = this.memory.create(300, 100); 47 | assertNotSame(c2, c3); 48 | 49 | Chunk c4 = this.memory.create(210, 100); 50 | assertSame(c4, c2); 51 | } 52 | 53 | /** 54 | * Test method for {@link nl.lxtreme.arm.memory.Memory#find(long)}. 55 | */ 56 | @Test 57 | public void testFind() 58 | { 59 | Chunk c1 = this.memory.create(0, 100); 60 | Chunk c2 = this.memory.create(200, 100); 61 | Chunk c3 = this.memory.create(300, 100); 62 | 63 | assertNull(this.memory.find(-1)); 64 | assertSame(c1, this.memory.find(0)); 65 | assertSame(c1, this.memory.find(50)); 66 | assertSame(c1, this.memory.find(99)); 67 | assertNull(this.memory.find(100)); 68 | assertSame(c2, this.memory.find(200)); 69 | assertSame(c2, this.memory.find(250)); 70 | assertSame(c2, this.memory.find(299)); 71 | assertSame(c3, this.memory.find(300)); 72 | assertSame(c3, this.memory.find(350)); 73 | assertSame(c3, this.memory.find(399)); 74 | assertNull(this.memory.find(400)); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/resources/arm7tdmi_Blinky_iFlash.hex: -------------------------------------------------------------------------------- 1 | :020000040000FA 2 | :1000000018F09FE518F09FE518F09FE518F09FE5C0 3 | :1000100018F09FE50000A0E1F0FF1FE518F09FE554 4 | :10002000400000007C020000780200007402000022 5 | :1000300070020000000000006C0200006802000076 6 | :10004000D0009FE5D0109FE5001080E5CC109FE523 7 | :10005000041080E5C8009FE5AA10A0E35520A0E3A6 8 | :100060002530A0E3043080E50130A0E3003080E5D6 9 | :100070000C1080E50C2080E5083090E5013B13E290 10 | :10008000FCFFFF0A0330A0E3003080E50C1080E5A0 11 | :100090000C2080E58C009FE50410A0E3041080E5AF 12 | :1000A0000210A0E3001080E57C009FE50110A0E3B2 13 | :1000B000001080E574009FE5DBF021E300D0A0E1B3 14 | :1000C000040040E2D7F021E300D0A0E1040040E2C8 15 | :1000D000D1F021E300D0A0E1040040E2D2F021E31E 16 | :1000E00000D0A0E1800040E2D3F021E300D0A0E105 17 | :1000F000040040E210F021E300D0A0E130009FE5D1 18 | :10010000010010E32CE09F052CE09F1510FF2FE16C 19 | :10011000FEFFFFEAFEE7C0460000E0FFE3380020F4 20 | :10012000E33C002080C01FE000C01FE040C01FE093 21 | :100130009004004071010000100100001501000052 22 | :100140009004004094040040000000000000000003 23 | :10015000000000000000000004480068021C034981 24 | :100160000968891A0A29F9D17047C04690040040ED 25 | :10017000154806C80B1C134305D000230B70491CFF 26 | :100180009142FBD1F5E71148C01C0323984306C8F0 27 | :100190000B1C134306D00378401C0B70491C914282 28 | :1001A000F9D1F1E700B500F03BF8094909480160D1 29 | :1001B000074B09480360FFF7CFFF08480360FFF7CC 30 | :1001C000CBFFF5E700BDC046400100005001000034 31 | :1001D00000010000088002E00C8002E0048002E0E0 32 | :1001E00003002DE928009FE5001090E5011081E251 33 | :1001F000001080E50110A0E318009FE5001080E5E5 34 | :100200000010A0E310009FE5001080E50300BDE8AA 35 | :1002100004F05EE290040040004000E030F0FFFF98 36 | :1002200009490A4801600321094801600121094880 37 | :100230000160094909480160242109480160102131 38 | :10024000084801607047C046EF490200184000E0CE 39 | :10025000144000E0044000E0E001000000F1FFFF76 40 | :1002600000F2FFFF10F0FFFFFEFFFFEAFEFFFFEAD4 41 | :10027000FEFFFFEAFEFFFFEAFEFFFFEAFEFFFFEAE6 42 | :00000001FF 43 | -------------------------------------------------------------------------------- /src/test/resources/blinkingLEDAndButton.hex: -------------------------------------------------------------------------------- 1 | :020000040000FA 2 | :0400000018F09FE570 3 | :040020008800000054 4 | :100040000120704770B50E4E0E4C82B03500361D43 5 | :1000500005E00100306800F01BF90C350C36A542B4 6 | :1000600009D2706831682A688842F2D1306800216C 7 | :1000700000F01CF9F1E702B070BC01BC0047C046BB 8 | :10008000D0020000DC02000000000FE11F00C0E30E 9 | :10009000120080E300F021E114D09FE51F00C0E3CF 10 | :1000A0001F0080E300F021E108D09FE508009FE5F4 11 | :1000B00010FF2FE10006004000050040C0000000D6 12 | :1000C00001C08FE21CFF2FE1044C054D054E064F89 13 | :1000D000AE462047002809D0BE4630474100000008 14 | :1000E000D500000045000000ED000000044C054D67 15 | :1000F0000020AE462047044C044DAE462047000089 16 | :100100008D010000F700000081020000C502000020 17 | :1001100000B564214843401E0028FCD101BC0047C3 18 | :100120000748074909688022D2040A43026013483D 19 | :10013000124909688022D2040A4302607047C0460F 20 | :10014000088002E000B50C480B4909688022D204FF 21 | :100150000A4302600748FFF7DBFF084807490968C0 22 | :100160008022D2040A4302600248FFF7D1FF01BC9B 23 | :1001700000470000102700000C8002E0048002E02D 24 | :1001800000B5401E0028FCD101BC004700B500F0BE 25 | :100190000BF8FFF7C5FFFFF7D5FF0248FFF7F0FFA9 26 | :1001A000F9E7C0468813000000B52B482A490968C2 27 | :1001B0001F22914302220A43026027482649096808 28 | :1001C0006022914320220A4302602448234909689F 29 | :1001D000FF229143AA220A43026020481F4909686E 30 | :1001E000FF22914355220A4302601D481C490968B9 31 | :1001F00001220A430260194818490968FF22914305 32 | :10020000AA220A430260154814490968FF22914353 33 | :1002100055220A430260134800688021C90001404A 34 | :100220000800800A0028F6D00D480D49096802220E 35 | :100230000A430260094809490968FF229143AA223A 36 | :100240000A430260054805490968FF229143552287 37 | :100250000A43026001BC004784C01FE08CC01FE05D 38 | :1002600080C01FE088C01FE07047000010B582B05A 39 | :100270000400009469460120FFF7F6FFF9E700004B 40 | :1002800000B581B000F01EF801B001BC00470000CD 41 | :1002900010B40300002A05D00C78491C1C705B1CAC 42 | :1002A000521EF9D110BC00B0704700000906090EBB 43 | :1002B0000300002A03D019705B1C521EFBD100B052 44 | :1002C00070470000014CA646204700006D02000068 45 | :0C02D000000000000000004000000040A2 46 | :0400000500000000F7 47 | :00000001FF 48 | -------------------------------------------------------------------------------- /src/test/resources/blinking_leds.hex: -------------------------------------------------------------------------------- 1 | :0400000500000000F7 2 | :020000040000FA 3 | :1000000018F09FE518F09FE518F09FE518F09FE5C0 4 | :1000100018F09FE50000A0E1F0FF1FE518F09FE554 5 | :1000200058000000400000004400000048000000AC 6 | :100030004C000000000000005000000054000000D0 7 | :10004000FEFFFFEAFEFFFFEAFEFFFFEAFEFFFFEA18 8 | :10005000FEFFFFEAFEFFFFEAAC009FE51110A0E300 9 | :10006000001080E5A4009FE5AA10A0E35520A0E3BE 10 | :100070002430A0E3043080E50130A0E3003080E5C7 11 | :100080000C1080E50C2080E5083090E5013B13E280 12 | :10009000FCFFFF0A0330A0E3003080E50C1080E590 13 | :1000A0000C2080E568009FE50410A0E3041080E5C3 14 | :1000B0000210A0E3001080E558009FE5DBF021E38B 15 | :1000C00000D0A0E1000040E2D7F021E300D0A0E1A1 16 | :1000D000000040E2D1F021E300D0A0E1000040E2C6 17 | :1000E000D2F021E300D0A0E1800040E2D3F021E390 18 | :1000F00000D0A0E1080040E210F021E300D0A0E130 19 | :1001000001AB4DE210009FE510FF2FE100C11FE0A1 20 | :1001100080C01FE000C01FE0E80400402001000094 21 | :10012000000000EA580000EA28008FE2000C90E886 22 | :1001300000A08AE000B08BE001704AE20B005AE1B7 23 | :100140005100000A0F00BAE814E04FE2010013E387 24 | :1001500003F0471013FF2FE1A4030000B4030000D5 25 | :100160000030A0E30040A0E30050A0E30060A0E363 26 | :10017000102052E27800A128FCFFFF8A822EB0E115 27 | :100180003000A128003081451EFF2FE17847C0468E 28 | :1001900004309FE503308FE013FF2FE119030000C7 29 | :1001A0000C009FE50C109FE504209FE508309FE5BB 30 | :1001B0001EFF2FE16000004060040040600000402E 31 | :1001C000031BA0E360209FE5081082E5150000EA0C 32 | :1001D0000000A0E3000000EA010080E24C109FE56F 33 | :1001E000010050E1FBFFFFBA021BA0E338209FE5AE 34 | :1001F000041082E5011BA0E30C1082E50000A0E3DF 35 | :10020000000000EA010080E220109FE5010050E1BB 36 | :10021000FBFFFFBA011BA0E30C209FE5041082E561 37 | :10022000021BA0E30C1082E5E8FFFFEA008002E079 38 | :1002300040420F001EFF2FE10E40A0E12C0000EB1A 39 | :1002400004E0A0E10D402DE9410000EB0040A0E1F9 40 | :100250000D40BDE81F402DE90100A0E3121DA0E301 41 | :10026000081084E5040084E51F40BDE80210A0E109 42 | :100270001EFF2FE110402DE90020A0E10000A0E3C7 43 | :100280000000A0E11040BDE81EFF2FE10000A0E14A 44 | :10029000E8FFFFEB03002DE9780000EB0300BDE869 45 | :1002A0003E0000EB0F002DE9770000EB0F00BDE8EA 46 | :1002B0001CC09FE50FC08CE001001CE30DE08F1215 47 | :1002C0000FE0A0011CFF2FE101C08FE21CFF2FE116 48 | :1002D00000F05AF804FFFFFF01402DE90000A0E103 49 | :1002E000790000EB0140BDE8000000EA0000E0E317 50 | :1002F0001B0000EA0E50A0E11F0000EB05E0A0E1AA 51 | :100300000050A0E10700C0E30D10A0E10A30A0E119 52 | :1003100000D0A0E160D08DE220402DE99FFFFFEBEF 53 | :100320002040BDE80060A0E30070A0E30080A0E3EF 54 | :1003300000B0A0E30710C1E305C0A0E1C009ACE82C 55 | :10034000C009ACE8C009ACE8C009ACE801D0A0E144 56 | :100350001EFF2FE104009FE51EFF2FE11EFF2FE18E 57 | :10036000100000400C109FE51800A0E3563412EF77 58 | :100370001EFF2FE1280100002600020000009FE57B 59 | :100380001EFF2FE10000004010B5C046C04604002B 60 | :10039000C046C046200000F09FF810BC08BC1847BB 61 | :1003A00001C08FE21CFF2FE1F0B585B0C046C0460A 62 | :1003B00005000C0000F094F8002001950294C0465E 63 | :1003C000C046039001A8FFF7E1FE040001A80D005C 64 | :1003D000009303C81600C046C046C046C046C0468B 65 | :1003E000C04600210800C046C046070000F058F88B 66 | :1003F0000490002107600800C046C046411C0498D4 67 | :10040000416000210800C046C04601000498816098 68 | :1004100000210800C046C04601000498C1600021C8 69 | :100420000800C046C046010004980161C046C046AD 70 | :10043000C046C046C046C046C046C046C046C0468C 71 | :10044000C046C046C046C046C046C046C046C0467C 72 | :10045000009B05B02000049C29003200A646F0BC99 73 | :1004600001B0704710B5C046C0460020C046C04627 74 | :10047000C046C046C046C04610BC08BC1847000075 75 | :100480000000E0E30210E0E31EFF2FE110402DE941 76 | :100490000000A0E11040BDE81EFF2FE11EFF2FE18C 77 | :1004A0007847C04604009FE51EFF2FE11EFF2FE1A5 78 | :1004B0002000004010B410BC7047000004009FE50D 79 | :1004C0001EFF2FE11EFF2FE10400004000C09FE54A 80 | :1004D0001CFF2FE1650400007847C0467DFFFFEA5E 81 | :1004E0007847C04610402DE9F3FFFFEB0010A0E372 82 | :1004F000001080E51040BDE81EFF2FE10C05000054 83 | :0C05000000000040E80400006001000062 84 | :00000001FF 85 | -------------------------------------------------------------------------------- /src/test/resources/helloWorld_loop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jawi/java-ARM-core/c0610cf907ff6358d04c53e55320abe3a9e3d4d7/src/test/resources/helloWorld_loop -------------------------------------------------------------------------------- /src/test/resources/helloWorld_static: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jawi/java-ARM-core/c0610cf907ff6358d04c53e55320abe3a9e3d4d7/src/test/resources/helloWorld_static -------------------------------------------------------------------------------- /src/test/resources/led.hex: -------------------------------------------------------------------------------- 1 | :10000000060000EAFEFFFFEAFEFFFFEAFEFFFFEA4E 2 | :10001000FEFFFFEAFEFFFFEAFEFFFFEAFEFFFFEA48 3 | :100020004C109FE50020A0E3002081E544109FE5EF 4 | :10003000012AA0E3002081E53C009FE5011AA0E32E 5 | :10004000001080E534409FE50000A0E1014054E24B 6 | :10005000FCFFFF1A28009FE5011AA0E3001080E5CD 7 | :1000600018409FE50000A0E1014054E2FCFFFF1AA8 8 | :10007000F0FFFFEA00C002E0088002E00C8002E02E 9 | :08008000A0860100048002E0EB 10 | :00000001FF 11 | -------------------------------------------------------------------------------- /src/test/resources/miniBench_neon: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jawi/java-ARM-core/c0610cf907ff6358d04c53e55320abe3a9e3d4d7/src/test/resources/miniBench_neon -------------------------------------------------------------------------------- /src/test/resources/rtcAndInterruptExample.hex: -------------------------------------------------------------------------------- 1 | :020000040000FA 2 | :0400000018F09FE570 3 | :0400180018F09FE558 4 | :040020008800000054 5 | :04003800C8010000FB 6 | :100040000120704770B50E4E0E4C82B03500361D43 7 | :1000500005E00100306800F0A3F90C350C36A5422C 8 | :1000600009D2706831682A688842F2D1306800216C 9 | :1000700000F0A4F9F1E702B070BC01BC0047C04633 10 | :10008000140400002004000000000FE11F00C0E382 11 | :10009000120080E300F021E114D09FE51F00C0E3CF 12 | :1000A0001F0080E300F021E108D09FE508009FE5F4 13 | :1000B00010FF2FE10006004000050040C0000000D6 14 | :1000C00001C08FE21CFF2FE1044C054D054E064F89 15 | :1000D000AE462047002809D0BE4630474100000008 16 | :1000E000D500000045000000ED000000044C054D67 17 | :1000F0000020AE462047044C044DAE462047000089 18 | :1001000021020000F700000091030000D503000069 19 | :100110000A4908600E480E490968094A0A40026007 20 | :1001200008480949016009482D2101600948094929 21 | :100130000968802292010A43026070470000004073 22 | :10014000FFDFFFFF14F1FFFFF901000014F2FFFFD2 23 | :100150000CF0FFFF10F0FFFF00B564214843401E84 24 | :100160000028FCD101BC00470748074909688022E4 25 | :10017000D2040A4302601348124909688022D2045B 26 | :100180000A4302607047C046088002E000B50C4890 27 | :100190000B4909688022D2040A4302600748FFF72E 28 | :1001A000DBFF0848074909688022D2040A4302603D 29 | :1001B0000248FFF7D1FF01BC0047000010270000F4 30 | :1001C0000C8002E0048002E004E04EE20F502DE9D2 31 | :1001D000CF00E0E3F00EC0E3000090E50FE0A0E107 32 | :1001E00010FF2FE1CF00E0E3F00EC0E30010A0E32A 33 | :1001F000001080E50F90FDE800B50348006800F0AE 34 | :10020000C5F801BC0047C0460000004000B5FFF73C 35 | :10021000BDFF02480321016001BC0047004002E02D 36 | :1002200000B500F047F800F011F8FFF79DFF054812 37 | :100230000121016000F0DEF80348FFF769FF00F0DC 38 | :10024000CFF8FEE740C01FE00D0200001548154939 39 | :10025000096801229143016012481249096802228B 40 | :10026000914301600F480F4909680C2291430160D6 41 | :100270000C480C49096810220A4302600A48002110 42 | :1002800001600A480949096801220A4302600848D6 43 | :100290000321016003480349096801220A430260FF 44 | :1002A0007047C046084002E0104002E00C4002E007 45 | :1002B000004002E000B52B482A4909681F229143FB 46 | :1002C00002220A43026027482649096860229143B6 47 | :1002D00020220A430260244823490968FF229143EF 48 | :1002E000AA220A43026020481F490968FF2291435D 49 | :1002F00055220A4302601D481C49096801220A432D 50 | :100300000260194818490968FF229143AA220A434A 51 | :100310000260154814490968FF22914355220A4397 52 | :100320000260134800688021C90001400800800A6B 53 | :100330000028F6D00D480D49096802220A430260E0 54 | :10034000094809490968FF229143AA220A43026029 55 | :10035000054805490968FF22914355220A43026076 56 | :1003600001BC004784C01FE08CC01FE080C01FE0BC 57 | :1003700088C01FE07047000010B582B004000094F0 58 | :1003800069460120FFF7F6FFF9E70000004700008B 59 | :1003900000B581B000F01EF801B001BC00470000BC 60 | :1003A00010B40300002A05D00C78491C1C705B1C9B 61 | :1003B000521EF9D110BC00B0704700000906090EAA 62 | :1003C0000300002A03D019705B1C521EFBD100B041 63 | :1003D00070470000014CA64620470000790300004A 64 | :1003E0007847C04600C00FE1C0C0CCE30CF021E16B 65 | :1003F0001EFF2FE17847C04600C00FE1C0C08CE36C 66 | :100400000CF021E100C00FE1C0C01CE2F9FFFF0ABF 67 | :100410001EFF2FE10400000000000040000000402B 68 | :0400000500000000F7 69 | :00000001FF 70 | --------------------------------------------------------------------------------