1 package com.tapina.robe.swi.clib;
2
3 import com.tapina.robe.runtime.*;
4 import com.tapina.robe.runtime.instruction.DataProcessingInstruction;
5 import com.tapina.robe.runtime.instruction.RegisterOperand;
6
7 import java.util.logging.Logger;
8
9 /***
10 * This class represents a SharedCLibrary routine as a code block.
11 * The code block has a set addres but does not have a physical length and the native ARM instructions do not exist.
12 */
13 public abstract class Stub extends CodeBlock {
14 public static final int A1 = 0, A2 = 1, A3 = 2, A4 = 3;
15 public static final int V1 = 4, V2 = 5, V3 = 6, V4 = 7, V5 = 8, V6 = 9;
16 public static final int SL = 10, FP = 11, IP = 12, SP = 13, LR = 14, PC = 15;
17
18 protected final Logger log = Logger.getLogger(getClass().getName());
19
20 public Stub() {
21 super(0);
22 }
23
24 public void execute(Environment environment) {
25 executeStub(environment);
26 unwind(environment);
27 }
28
29 void unwind(Environment environment) {
30 UNWIND_INSTRUCTION.checkAndExecute(environment);
31 }
32
33 public abstract void executeStub(Environment environment);
34
35 public void setAddress(int address) {
36 super.setAddress(address);
37 }
38
39 private final static Instruction UNWIND_INSTRUCTION =
40 new DataProcessingInstruction(Condition.AL, DataProcessingInstruction.MOV, 15, 0,
41 new RegisterOperand(14), true, true);
42
43 protected void executeSubroutine(Environment environment, CodeBlock codeBlock) {
44 final CPU cpu = environment.getCpu();
45 final int[] R = cpu.R;
46 final int routineAddress = codeBlock.getAddress();
47 final int R14save = R[14];
48 R[14] = this.getAddress() + 4;
49 R[15] = routineAddress + 8;
50 while (true) {
51 try {
52 codeBlock.execute(environment);
53 } catch (DecoderException e) {
54 throw new RuntimeException(e);
55 }
56 if (cpu.getPC() == this.getAddress() + 4) {
57
58 break;
59 }
60
61 final int pc = cpu.getPC();
62 codeBlock = environment.getMemoryMap().addEntryPoint(pc);
63 R[15] += 8;
64 }
65 R[14] = R14save;
66 }
67 }