├── .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 |
--------------------------------------------------------------------------------