// Sets the registers with the alu's output according to // the given instruction // Throws ProgramException if destination contains M and A contains // an illegal address. protected void setDestination(short instruction) throws ProgramException { boolean destA = (instruction & 0x0020) > 0; boolean destD = (instruction & 0x0010) > 0; boolean destM = (instruction & 0x0008) > 0; if (destM) { int address = A.get(); if ((address < 0) || (address >= M.getSize())) { throw new ProgramException( "At line " + PC.get() + ": Destination is M but A=" + address + " is an illegal memory address."); } A.setUpdatePointer(true); bus.send(alu, 2, M, address); A.setUpdatePointer(false); } if (destA) { bus.send(alu, 2, A, 0); } if (destD) { bus.send(alu, 2, D, 0); } }
// computes the exp part of the given instruction. // The result will be at the alu's output. // Throws ProgramException if the calculation involves M and A contains // an illegal address. protected void computeExp(short instruction) throws ProgramException { boolean indirect = (instruction & 0x1000) > 0; boolean zd = (instruction & 0x0800) > 0; boolean nd = (instruction & 0x0400) > 0; boolean zm = (instruction & 0x0200) > 0; boolean nm = (instruction & 0x0100) > 0; boolean f = (instruction & 0x0080) > 0; boolean no = (instruction & 0x0040) > 0; try { alu.setCommand( assemblerTranslator.getExpByCode((short) (instruction & 0xffc0)), zd, nd, zm, nm, f, no); } catch (AssemblerException ae) { } bus.send(D, 0, alu, 0); // sends D to input0 of the alu // sends A or M[A] to input1 of the alu if (indirect) { int address = A.get(); if ((address < 0) || (address >= M.getSize())) { throw new ProgramException( "At line " + PC.get() + ": Expression involves M but A=" + address + " is an illegal memory address."); } A.setUpdatePointer(true); bus.send(M, address, alu, 1); A.setUpdatePointer(false); } else { bus.send(A, 0, alu, 1); } alu.compute(); }
public static void bootFromURI( ARMv5 cpu, RAM ramMain, String kimage, String initrd, String cmdline) { byte[] cmdlb = cmdline.getBytes(); // +1: need null char at the end of line byte[] cmdalign = new byte[(cmdlb.length + 1 + 3) & ~0x3]; System.arraycopy(cmdlb, 0, cmdalign, 0, cmdlb.length); final int addrRAM = 0x00000000; final int addrAtagsStart = addrRAM + 0x800000; int addrAtags = addrAtagsStart; final int addrImage = addrRAM + 0x00008000; int sizeImage = 0; final int addrInitrd = addrRAM + 0x00810000; int sizeInitrd = 0; boolean initrdExist = !initrd.equals(""); // tentative boot loader for ARM Linux try { // load Image file sizeImage = loadURIResource(new URI(kimage), cpu, addrImage); // load Initrd/InitramFS file if (initrdExist) { sizeInitrd = loadURIResource(new URI(initrd), cpu, addrInitrd); } } catch (URISyntaxException e) { e.printStackTrace(System.err); return; } // report address mapping System.out.printf( "Address mapping:\n" + " RAM : 0x%08x\n" + " Kernel: 0x%08x - 0x%08x\n" + " Initrd: 0x%08x - 0x%08x\n" + " ATAGS : 0x%08x - 0x%08x\n", addrRAM, addrImage, addrImage + sizeImage - 1, addrInitrd, addrInitrd + sizeInitrd - 1, addrAtags, addrAtags + 4096 - 1); // r0: 0 cpu.setReg(0, 0); // r1: machine type // ARM-Versatile PB cpu.setReg(1, 0x00000183); // ARM-Versatile AB // cpu.setReg(1, 0x0000025e); // r2: ATAGS pointer. cpu.setReg(2, addrAtags); { // ATAG_CORE, size, tag, [flags, pagesize, rootdev] cpu.write32_a32(addrAtags + 0x00, 0x00000005); cpu.write32_a32(addrAtags + 0x04, ATAG_CORE); // bit 0: read only cpu.write32(addrAtags + 0x08, 0x00000001); cpu.write32(addrAtags + 0x0c, 0x00001000); cpu.write32(addrAtags + 0x10, 0x00000000); addrAtags += 0x14; // ATAG_MEM, size, tag, size, start cpu.write32_a32(addrAtags + 0x00, 0x00000004); cpu.write32_a32(addrAtags + 0x04, ATAG_MEM); cpu.write32_a32(addrAtags + 0x08, ramMain.getSize()); cpu.write32_a32(addrAtags + 0x0c, addrRAM); addrAtags += 0x10; // ATAG_INITRD2, size, tag, size, start if (initrdExist) { cpu.write32_a32(addrAtags + 0x00, 0x00000004); cpu.write32_a32(addrAtags + 0x04, ATAG_INITRD2); cpu.write32_a32(addrAtags + 0x08, addrInitrd); cpu.write32_a32(addrAtags + 0x0c, sizeInitrd); addrAtags += 0x10; } // ATAG_CMDLINE cpu.write32_a32(addrAtags + 0x00, 0x00000002 + cmdalign.length / 4); cpu.write32_a32(addrAtags + 0x04, ATAG_CMDLINE); for (int i = 0; i < cmdalign.length; i++) { cpu.write8_a32(addrAtags + 0x08 + i, cmdalign[i]); } addrAtags += 0x08 + cmdalign.length; // ATAG_SERIAL, size, tag, low, high cpu.write32_a32(addrAtags + 0x00, 0x00000004); cpu.write32_a32(addrAtags + 0x04, ATAG_SERIAL); cpu.write32_a32(addrAtags + 0x08, 0x00000020); cpu.write32_a32(addrAtags + 0x0c, 0x00000030); addrAtags += 0x10; // ATAG_REVISION, size, tag, rev cpu.write32_a32(addrAtags + 0x00, 0x00000003); cpu.write32_a32(addrAtags + 0x04, ATAG_REVISION); cpu.write32_a32(addrAtags + 0x08, 0x00000010); addrAtags += 0x0c; // ATAG_NONE, size, tag // It is unique in that its size field in the header // should be set to 0 (not 2). cpu.write32_a32(addrAtags + 0x00, 0x00000000); cpu.write32_a32(addrAtags + 0x04, ATAG_NONE); addrAtags += 0x08; } // pc: entry of stext cpu.setPC(addrImage); cpu.setJumped(false); }