From 1b3aa68fba9e2ebe43709c34d6f2d7fcdda399b2 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 31 Jan 2012 06:42:21 +0100 Subject: [PATCH] merge of latest MSP430X code for mspsim --- se/sics/mspsim/core/BasicClockModule.java | 32 +- se/sics/mspsim/core/ClockSystem.java | 54 +++ se/sics/mspsim/core/MSP430Core.java | 420 +++++++++++++++----- se/sics/mspsim/core/UnifiedClockSystem.java | 396 ++++++++++++++++++ se/sics/mspsim/util/MapTable.java | 6 +- se/sics/mspsim/util/StackMonitor.java | 2 +- 6 files changed, 794 insertions(+), 116 deletions(-) create mode 100644 se/sics/mspsim/core/ClockSystem.java create mode 100644 se/sics/mspsim/core/UnifiedClockSystem.java diff --git a/se/sics/mspsim/core/BasicClockModule.java b/se/sics/mspsim/core/BasicClockModule.java index feead23..595c1d5 100644 --- a/se/sics/mspsim/core/BasicClockModule.java +++ b/se/sics/mspsim/core/BasicClockModule.java @@ -42,24 +42,24 @@ package se.sics.mspsim.core; import se.sics.mspsim.util.Utils; -public class BasicClockModule extends IOUnit { +public class BasicClockModule extends ClockSystem { - public static final int DCOCTL = 0x56; // 0x60 - public static final int BCSCTL1 = 0x57; // 0x84 - public static final int BCSCTL2 = 0x58; + private static final int DCOCTL = 0x56; // 0x60 + private static final int BCSCTL1 = 0x57; // 0x84 + private static final int BCSCTL2 = 0x58; - public static final int ACLK_FRQ = 32768; + private static final int ACLK_FRQ = 32768; // DCO_FRQ what default frq is the DCO running at??? - public static final int DCO_FRQ = 2500000; + private static final int DCO_FRQ = 2500000; // What frequency steps to take for the DCO? // We have 8 bits + 3 => 11 bits => 2048 combinations... // => What is lowest frq??? (zero) // Max speed is 8Mhz (CPU limits it) - is max DCO 8Mhz? // Based on the scatterweb code it looks like less than // 5Mhz is more correct... - public static final int MAX_DCO_FRQ = 4915200; - public static final int MIN_DCO_FRQ = 1000; - public static final int DCO_FACTOR = (MAX_DCO_FRQ - MIN_DCO_FRQ) / 2048; + private static final int MAX_DCO_FRQ = 4915200; + private static final int MIN_DCO_FRQ = 1000; + private static final int DCO_FACTOR = (MAX_DCO_FRQ - MIN_DCO_FRQ) / 2048; private MSP430Core core; @@ -87,7 +87,19 @@ public class BasicClockModule extends IOUnit { super("BasicClockModule", memory, offset); this.core = core; this.timers = timers; - reset(0); + // reset(0); + } + + public int getMaxDCOFrequency() { + return MAX_DCO_FRQ; + } + + public int getAddressRangeMin() { + return DCOCTL; + } + + public int getAddressRangeMax() { + return BCSCTL2; } public void reset(int type) { diff --git a/se/sics/mspsim/core/ClockSystem.java b/se/sics/mspsim/core/ClockSystem.java new file mode 100644 index 0000000..a3ff883 --- /dev/null +++ b/se/sics/mspsim/core/ClockSystem.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of MSPSim. + * + * $Id$ + * + * ----------------------------------------------------------------- + * + * ClockSystem + * + * Author : Joakim Eriksson + * Created : Sun Oct 21 22:00:00 2007 + * Updated : $Date$ + * $Revision$ + */ + +package se.sics.mspsim.core; + +public abstract class ClockSystem extends IOUnit { + + public abstract int getMaxDCOFrequency(); + public abstract int getAddressRangeMin(); + public abstract int getAddressRangeMax(); + + public ClockSystem(String type, int[] memory, int offset) { + super(type, memory, offset); + } + +} diff --git a/se/sics/mspsim/core/MSP430Core.java b/se/sics/mspsim/core/MSP430Core.java index 107ddc9..8f535e5 100644 --- a/se/sics/mspsim/core/MSP430Core.java +++ b/se/sics/mspsim/core/MSP430Core.java @@ -27,12 +27,16 @@ * * This file is part of MSPSim. * + * $Id$ + * * ----------------------------------------------------------------- * * MSP430Core * * Author : Joakim Eriksson * Created : Sun Oct 21 22:00:00 2007 + * Updated : $Date$ + * $Revision$ */ package se.sics.mspsim.core; @@ -132,7 +136,9 @@ public class MSP430Core extends Chip implements MSP430Constants { private Flash flash; boolean isFlashBusy; - + + ClockSystem bcs; + public void setIO(int adr, IOUnit io, boolean word) { memOut[adr] = io; memIn[adr] = io; @@ -224,13 +230,19 @@ public class MSP430Core extends Chip implements MSP430Constants { timers[i] = t; } - BasicClockModule bcs = new BasicClockModule(this, memory, 0, timers); - for (int i = 0x56, n = 0x59; i < n; i++) { + // XXX this should be handled by the config, but we do it here to + // avoid changing too much of the mspsim architecture for now + if (MSP430XArch) { + bcs = new UnifiedClockSystem(this, memory, 0, timers); + } else { + bcs = new BasicClockModule(this, memory, 0, timers); + } + for (int i = bcs.getAddressRangeMin(), n = bcs.getAddressRangeMax(); + i <= n; i++) { memOut[i] = bcs; memIn[i] = bcs; } - - + // SFR and Basic clock system. ioUnits.add(sfr); ioUnits.add(bcs); @@ -247,6 +259,8 @@ public class MSP430Core extends Chip implements MSP430Constants { memIn[config.watchdogOffset] = watchdog; ioUnits.add(watchdog); + + bcs.reset(0); } public Profiler getProfiler() { @@ -349,7 +363,7 @@ public class MSP430Core extends Chip implements MSP430Constants { @Deprecated public boolean hasBreakPoint(int address) { - return watchPoints[address] != null; + return watchPoints[address] != null; } @Deprecated @@ -470,7 +484,7 @@ public class MSP430Core extends Chip implements MSP430Constants { public int incRegister(int r, int value) { CPUMonitor rm = regReadMonitors[r]; if (rm != null) { - rm.cpuAction(CPUMonitor.REGISTER_READ, r, reg[r]); + rm.cpuAction(CPUMonitor.REGISTER_READ, r, reg[r]); } rm = regWriteMonitors[r]; if (rm != null) { @@ -491,11 +505,11 @@ public class MSP430Core extends Chip implements MSP430Constants { lastVTime = getTime(); lastCyclesTime = cycles; lastMicrosDelta = 0; - - currentDCOFactor = 1.0 * BasicClockModule.MAX_DCO_FRQ / frequency; -// System.out.println("*** DCO: MAX:" + BasicClockModule.MAX_DCO_FRQ + -// " current: " + frequency + " DCO_FAC = " + currentDCOFactor); + currentDCOFactor = 1.0 * bcs.getMaxDCOFrequency() / frequency; + + /* System.out.println("*** DCO: MAX:" + bcs.getMaxDCOFrequency() + + " current: " + frequency + " DCO_FAC = " + currentDCOFactor);*/ if (DEBUG) log("Set smclkFrq: " + smclkFrq); dcoReset(); @@ -521,7 +535,7 @@ public class MSP430Core extends Chip implements MSP430Constants { // get elapsed time in seconds public double getTimeMillis() { - return 1000.0 * getTime() / BasicClockModule.MAX_DCO_FRQ; + return 1000.0 * getTime() / bcs.getMaxDCOFrequency(); } private void executeEvents() { @@ -610,7 +624,8 @@ public class MSP430Core extends Chip implements MSP430Constants { * @param time */ public long scheduleTimeEventMillis(TimeEvent event, double msec) { - long time = (long) (getTime() + msec / 1000 * BasicClockModule.MAX_DCO_FRQ); + /* System.out.println("MAX_DCO " + bcs.getMaxDCOFrequency());*/ + long time = (long) (getTime() + msec / 1000 * bcs.getMaxDCOFrequency()); // System.out.println("Scheduling at: " + time + " (" + msec + ") getTime: " + getTime()); scheduleTimeEvent(event, time); return time; @@ -786,7 +801,7 @@ public class MSP430Core extends Chip implements MSP430Constants { dstAddress %= MAX_MEM; } - CPUMonitor wp = watchPoints[dstAddress]; + CPUMonitor wp = watchPoints[dstAddress]; if (wp != null) { wp.cpuAction(CPUMonitor.MEMORY_WRITE, dstAddress, dst); } @@ -824,7 +839,6 @@ public class MSP430Core extends Chip implements MSP430Constants { if (wp != null) { wp.cpuAction(CPUMonitor.MEMORY_WRITE, dstAddress, dst); } - } void profileCall(int dst, int pc) { @@ -981,7 +995,7 @@ public class MSP430Core extends Chip implements MSP430Constants { CPUMonitor wp = watchPoints[pc]; if (wp != null) { if (breakpointActive) { - wp.cpuAction(CPUMonitor.EXECUTE, pc, 0); + wp.cpuAction(CPUMonitor.EXECUTE, pc, 0); breakpointActive = false; return -1; } @@ -992,15 +1006,33 @@ public class MSP430Core extends Chip implements MSP430Constants { if (wp != null) { wp.cpuAction(CPUMonitor.EXECUTE, pc, 0); } - + int pcBefore = pc; instruction = read(pc, MODE_WORD); int ext3_0 = 0; + boolean repeatsInDstReg = false; + boolean wordx20 = false; + /* check for extension words */ if ((instruction & 0xf800) == 0x1800) { extWord = instruction; ext3_0 = instruction & 0xf; /* bit 3 - 0 - either repeat count or dest 19-16 */ pc += 2; + // Bit 7 in the extension word indicates that the number of + // repeats is found in the register pointed to by ext3_0. If + // the bit is 0, ext3_0 contains the number of repeats. If the + // bit is 1, ext3_0 contains the register number that holds + // the number of repeats. + if ((instruction & 0x80) == 0x80) { + repeatsInDstReg = true; + } + // Bit 6 indicates whether or not the data length mode should + // be 20 bits. A one means traditional MSP430 mode; a zero + // indicates 20 bit mode. (XXX: there is a reserved data + // length mode if this bit is zero and the MSP430 instruction + // that follows the extension word also has a zero bit data + // length mode.) + wordx20 = (instruction & 0x40) == 0; instruction = read(pc, MODE_WORD); // System.out.println("*** Extension word!!! " + Utils.hex16(extWord) + // " read the instruction too: " + Utils.hex16(instruction) + " at " + Utils.hex16(pc - 2)); @@ -1016,6 +1048,7 @@ public class MSP430Core extends Chip implements MSP430Constants { boolean zeroCarry = false; /* msp430X can zero carry in repeats */ boolean word = (instruction & 0x40) == 0; + // Destination vars int dstRegister = 0; int dstAddress = -1; @@ -1040,25 +1073,14 @@ public class MSP430Core extends Chip implements MSP430Constants { int srcData = (instruction & 0x0f00) >> 8; int dstData = (instruction & 0x000f); boolean rrword = true; + switch(op) { // 20 bit register write - case MOVA_IMM2REG: - src = read(pc, MODE_WORD); - writeRegister(PC, pc += 2); - dst = src + (srcData << 16); -// System.out.println("*** Writing $" + getAddressAsString(dst) + " to reg: " + dstData); - writeRegister(dstData, dst); - updateStatus = false; - break; - case MOVA_ABS2REG: - src = read(pc, MODE_WORD); - writeRegister(PC, pc += 2); - dst = src + (srcData << 16); - //System.out.println(Utils.hex20(pc) + " MOVA &ABS Reading from $" + getAddressAsString(dst) + " to reg: " + dstData); - dst = read(dst, MODE_WORD20); - //System.out.println(" => $" + getAddressAsString(dst)); - writeRegister(dstData, dst); + case MOVA_IND: + /* Read from address in src register, move to destination register. */ + writeRegister(dstData, readRegister(srcData)); updateStatus = false; + cycles += 3; break; case MOVA_IND_AUTOINC: if (profiler != null && instruction == 0x0110) { @@ -1075,52 +1097,203 @@ public class MSP430Core extends Chip implements MSP430Constants { // System.out.println("*** Writing $" + getAddressAsString(dst) + " to reg: " + dstData); writeRegister(dstData, dst); updateStatus = false; + cycles += 3; break; -// case CMPA_IMM: -// break; -// case CMPA_REG: -// break; -// case ADDA_IMM - TODO - make both ADDA use the same code. - case ADDA_REG: - src = readRegister(srcData); - dst = readRegister(dstData); - - int tmp = (src ^ dst) & 0x80000; - - dst = src + dst; - int nxtCarry = (dst & 0x100000) > 0 ? CARRY : 0; /* bit 20 */ - dst &= 0xfffff; - + case MOVA_ABS2REG: + src = read(pc, MODE_WORD); + writeRegister(PC, pc += 2); + dst = src + (srcData << 16); + //System.out.println(Utils.hex20(pc) + " MOVA &ABS Reading from $" + getAddressAsString(dst) + " to reg: " + dstData); + dst = read(dst, MODE_WORD20); + //System.out.println(" => $" + getAddressAsString(dst)); writeRegister(dstData, dst); - sr = readRegister(SR); - sr = sr & ~(NEGATIVE | OVERFLOW | CARRY | ZERO); - - // If tmp == 0 and currenly not the same sign for src & dst - if (tmp == 0 && ((src ^ dst) & 0x80000) != 0) { - sr |= OVERFLOW; - // System.out.println("OVERFLOW - ADD/SUB " + Utils.hex16(src) - // + " + " + Utils.hex16(tmpDst)); - } - - sr = sr | nxtCarry | (dst == 0 ? ZERO : 0) | ((dst & 0x80000) > 0 ? NEGATIVE : 0); - writeRegister(SR, sr); updateStatus = false; + cycles += 4; break; + case MOVA_INDX2REG: + /* Read data from address in memory, indexed by source + * register, and place into destination register. */ + int index = read(pc, MODE_WORD); + int indexModifier = readRegister(srcData); + if(index > 0x8000) { + index = -(0x10000 - index); + } + if(indexModifier > 0x8000) { + indexModifier = -(0x10000 - indexModifier); + } + writeRegister(dstData, read(indexModifier + index, MODE_WORD20)); + writeRegister(PC, pc += 2); + updateStatus = false; + cycles += 4; + break; + + case MOVA_REG2ABS: + dst = read(pc, MODE_WORD); + writeRegister(PC, pc += 2); + write(dst + (dstData << 16), readRegister(srcData), MODE_WORD20); + updateStatus = false; + cycles += 4; + break; + + case MOVA_REG2INDX: + /* Read data from register, write to address in memory, + * indexed by source register. */ + index = read(pc, MODE_WORD); + indexModifier = readRegister(dstData); + if(index > 0x8000) { + index = -(0x10000 - index); + } + if(indexModifier > 0x8000) { + indexModifier = -(0x10000 - indexModifier); + } + write(indexModifier + index, readRegister(srcData), MODE_WORD20); + writeRegister(PC, pc += 2); + updateStatus = false; + cycles += 4; + break; + + case MOVA_IMM2REG: + src = read(pc, MODE_WORD); + writeRegister(PC, pc += 2); + dst = src + (srcData << 16); +// System.out.println("*** Writing $" + getAddressAsString(dst) + " to reg: " + dstData); + writeRegister(dstData, dst); + updateStatus = false; + cycles += 2; + break; + + + case ADDA_IMM: + // For all immediate instructions, the data low 16 bits of + // the data is stored in the following word (PC + 2) and + // the high 4 bits in the instruction word, which we have + // masked out as srcData. + int immData = read(pc, MODE_WORD) + (srcData << 16); + writeRegister(PC, pc += 2); + dst = readRegister(dstData) + immData; + writeRegister(dstData, dst); + cycles += 3; + break; + case CMPA_IMM: + /* Status Bits N: Set if result is negative (src > dst), reset if positive (src ≤ dst) + Z: Set if result is zero (src = dst), reset otherwise (src ≠ dst) + C: Set if there is a carry from the MSB, reset otherwise + V: Set if the subtraction of a negative source operand from a positive destination + operand delivers a negative result, or if the subtraction of a positive source + operand from a negative destination operand delivers a positive result, reset + otherwise (no overflow) */ + immData = read(pc, MODE_WORD) + (srcData << 16); + writeRegister(PC, pc += 2); + sr = readRegister(SR); + sr &= ~(NEGATIVE | ZERO | CARRY | OVERFLOW); + if (readRegister(dstData) >= immData) { + sr |= CARRY; + } + if (readRegister(dstData) < immData) { + sr |= NEGATIVE; + } + if (readRegister(dstData) == immData) { + sr |= ZERO; + } + + int cmpTmp = readRegister(dstData) - immData; + int b = 0x80000; // CMPA always use 20 bit data length + + if (((readRegister(dstData) ^ cmpTmp) & b) == 0 && + (((readRegister(dstData) ^ immData) & b) != 0)) { + sr |= OVERFLOW; + } + + writeRegister(SR, sr); + updateStatus = false; + cycles += 3; + break; + + case SUBA_IMM: + immData = read(pc, MODE_WORD) + (srcData << 16); + writeRegister(PC, pc += 2); + dst = readRegister(dstData) - immData; + writeRegister(dstData, dst); + cycles += 3; + break; + + case MOVA_REG: + cycles += 1; + writeRegister(dstData, readRegister(srcData)); + break; + + case CMPA_REG: + sr = readRegister(SR); + sr &= ~(NEGATIVE | ZERO | CARRY | OVERFLOW); + if (readRegister(dstData) >= readRegister(srcData)) { + sr |= CARRY; + } + if (readRegister(dstData) < readRegister(srcData)) { + sr |= NEGATIVE; + } + if (readRegister(dstData) == readRegister(srcData)) { + sr |= ZERO; + } + + cmpTmp = readRegister(dstData) - readRegister(srcData); + b = 0x80000; // CMPA always use 20 bit data length + + if (((readRegister(dstData) ^ cmpTmp) & b) == 0 && + (((readRegister(dstData) ^ readRegister(srcData)) & b) != 0)) { + sr |= OVERFLOW; + } + + writeRegister(SR, sr); + updateStatus = false; + cycles += 1; + break; + + case ADDA_REG: + dst = readRegister(dstData) + readRegister(srcData); + writeRegister(dstData, dst); + cycles += 1; + break; + case SUBA_REG: + dst = readRegister(dstData) - readRegister(srcData); + writeRegister(dstData, dst); + cycles += 1; + break; + case RRXX_ADDR: rrword = false; case RRXX_WORD: - int count = 1 + (instruction >> 10)& 0x03; + int count = ((instruction >> 10) & 0x03) + 1; dst = readRegister(dstData); - nxtCarry = 0; + int nxtCarry = 0; + int carry = (readRegister(SR) & CARRY) > 0? 1: 0; if (rrword) { dst = dst & 0xffff; } + cycles += 1 + count; switch(instruction & RRMASK) { /* if word zero anything above */ case RRCM: - System.out.println("*** RRCM!!! not implemented"); - throw new EmulationException("**** RRCM!! not implemented"); -// break; + /* if (rrword): Rotate right through carry the 16-bit CPU register content + if (!rrword): Rotate right through carry the 20-bit CPU register content */ + + /* Pull the (count) lowest bits from dst - those will + * be placed in the (count) high bits of dst after the + * instruction is complete. */ + int dst_low = dst & ((1 << count) - 1); + + /* Grab the bit that wlil be in the carry flag when instruction completes. */ + nxtCarry = (dst & (1 << (count + 1))) > 0? CARRY: 0; + + /* Rotate dst. */ + dst = dst >> (count); + + /* Rotate the high bits, insert into dst. */ + if (rrword) { + dst |= (dst_low << (17 - count)) | (carry << (16 - count)); + } else { + dst |= (dst_low << (21 - count)) | (carry << (20 - count)); + } + break; case RRAM: // System.out.println("RRAM executing"); /* roll in MSB from above */ @@ -1134,12 +1307,14 @@ public class MSP430Core extends Chip implements MSP430Constants { dst = dst >> 1; break; case RLAM: + // System.out.println("RLAM executing at " + pc); /* just roll in "zeroes" from left */ dst = dst << (count - 1); nxtCarry = (dst & (rrword ? 0x8000 : 0x80000)) > 0 ? CARRY : 0; dst = dst << 1; break; case RRUM: + //System.out.println("RRUM executing"); /* just roll in "zeroes" from right */ dst = dst >> (count - 1); nxtCarry = (dst & 1) > 0 ? CARRY : 0; @@ -1152,9 +1327,12 @@ public class MSP430Core extends Chip implements MSP430Constants { writeRegister(dstData, dst); break; default: - System.out.println("MSP430X instructions not yet supported: " + - Utils.hex16(instruction)); - throw new EmulationException("MSP430X instructions not yet supported..."); + System.out.println("MSP430X instruction not yet supported: " + + Utils.hex16(instruction) + + " op " + Utils.hex16(op)); + throw new EmulationException("Found unsupported MSP430X instruction " + + Utils.hex16(instruction) + + " op " + Utils.hex16(op)); } break; @@ -1177,14 +1355,14 @@ public class MSP430Core extends Chip implements MSP430Constants { case CALLA_IMM: dst = (dstRegister << 16) | read(pc, MODE_WORD); pc += 2; - cycles += 4; + cycles += 5; break; case CALLA_ABS: /* read the address of where the address to call is */ dst = (dstRegister << 16) | read(pc, MODE_WORD); dst = read(dst, MODE_WORD20); pc += 2; - cycles += 4; + cycles += 7; break; default: int type = MODE_WORD; @@ -1195,6 +1373,7 @@ public class MSP430Core extends Chip implements MSP430Constants { case PUSHM_A: type = MODE_WORD20; size = 4; + cycles += 2; case PUSHM_W: int n = 1 + ((instruction >> 4) & 0x0f); int regNo = instruction & 0x0f; @@ -1205,6 +1384,7 @@ public class MSP430Core extends Chip implements MSP430Constants { /* decrease stack pointer and write n times */ for(int i = 0; i < n; i++) { sp -= size; + cycles += 2; write(sp, this.reg[regNo--], type); // System.out.println("Saved reg: " + (regNo + 1) + " was " + reg[regNo + 1]); @@ -1216,6 +1396,7 @@ public class MSP430Core extends Chip implements MSP430Constants { case POPM_A: type = MODE_WORD20; size = 4; + cycles += 2; case POPM_W: n = 1 + ((instruction >> 4) & 0x0f); regNo = instruction & 0x0f; @@ -1224,6 +1405,7 @@ public class MSP430Core extends Chip implements MSP430Constants { /* read and increase stack pointer n times */ for(int i = 0; i < n; i++) { + cycles += 2; this.reg[regNo++] = read(sp, type); // System.out.println("Restored reg: " + (regNo - 1) + " to " + reg[regNo - 1]); sp += size; @@ -1305,7 +1487,7 @@ public class MSP430Core extends Chip implements MSP430Constants { break; // Bugfix suggested by Matt Thompson case AM_IND_AUTOINC: - if(dstRegister == PC) { + if (dstRegister == PC) { dstAddress = readRegister(PC); pc += 2; writeRegister(PC, pc); @@ -1322,15 +1504,19 @@ public class MSP430Core extends Chip implements MSP430Constants { if (dstRegMode) { dst = readRegisterCG(dstRegister, ad); - if (!word) { + if (word) { + dst &= 0xffff; + } else if (wordx20) { + dst &= 0xfffff; + } else { dst &= 0xff; } /* set the repeat here! */ - if ((extWord & EXTWORD_REPEAT) > 0) { - repeats = 1 + readRegister(ext3_0) & 0xf; - } else { - repeats = 1 + ext3_0; - } + if (repeatsInDstReg) { + repeats = 1 + readRegister(ext3_0); + } else { + repeats = 1 + ext3_0; + } zeroCarry = (extWord & EXTWORD_ZC) > 0; // if (repeats > 1) { @@ -1357,9 +1543,12 @@ public class MSP430Core extends Chip implements MSP430Constants { dst = dst >> 1; if (word) { dst |= (sr & CARRY) > 0 ? 0x8000 : 0; + } else if (wordx20) { + dst |= (sr & CARRY) > 0 ? 0x80000 : 0; } else { dst |= (sr & CARRY) > 0 ? 0x80 : 0; } + // Indicate write to memory!! write = true; // Set the next carry! @@ -1374,6 +1563,8 @@ public class MSP430Core extends Chip implements MSP430Constants { nxtCarry = (dst & 1) > 0 ? CARRY : 0; if (word) { dst = (dst & 0x8000) | (dst >> 1); + } else if (wordx20) { + dst = (dst & 0x80000) | (dst >> 1); } else { dst = (dst & 0x80) | (dst >> 1); } @@ -1382,7 +1573,7 @@ public class MSP430Core extends Chip implements MSP430Constants { break; case SXT: // Extend Sign (bit 8-15 => same as bit 7) - dst = (dst & 0x80) > 0 ? dst | 0xff00 : dst & 0x7f; + dst = (dst & 0x80) > 0 ? dst | 0xfff00 : dst & 0x7f; write = true; sr = sr & ~(CARRY | OVERFLOW); if (dst != 0) { @@ -1461,10 +1652,12 @@ public class MSP430Core extends Chip implements MSP430Constants { Utils.hex16(instruction)); } if (repeats > 0) { - if (!word) { - dst &= 0xff; + if (word) { + dst &= 0xffff; + } else if (wordx20) { + dst &= 0xfffff; } else { - dst &= 0xffff; + dst &= 0xff; } } } @@ -1534,7 +1727,11 @@ public class MSP430Core extends Chip implements MSP430Constants { // Some CGs should be handled as registry reads only... if ((srcRegister == CG1 && as > AM_INDEX) || srcRegister == CG2) { src = CREG_VALUES[srcRegister - 2][as]; - if (!word) { + if (word) { + src &= 0xffff; + } else if (wordx20) { + src &= 0xfffff; + } else { src &= 0xff; } cycles += dstRegMode ? 1 : 4; @@ -1544,8 +1741,12 @@ public class MSP430Core extends Chip implements MSP430Constants { case AM_REG: // CG handled above! src = readRegister(srcRegister); - if (!word) { - src &= 0xff; + if (word) { + src &= 0xffff; + } else if (wordx20) { + src &= 0xfffff; + } else { + src &= 0xff; } cycles += dstRegMode ? 1 : 4; /* add cycle if destination register = PC */ @@ -1554,11 +1755,12 @@ public class MSP430Core extends Chip implements MSP430Constants { if (dstRegMode) { /* possible to have repeat, etc... */ /* TODO: decode the # also */ - if ((extWord & EXTWORD_REPEAT) > 0) { - repeats = 1 + readRegister(ext3_0) & 0xf; - } else { - repeats = 1 + ext3_0; - } + if (repeatsInDstReg) { + repeats = 1 + readRegister(ext3_0); + } else { + repeats = 1 + ext3_0; + } + zeroCarry = (extWord & EXTWORD_ZC) > 0; } @@ -1602,9 +1804,13 @@ public class MSP430Core extends Chip implements MSP430Constants { if (dstRegMode) { if (op != MOV) { dst = readRegister(dstRegister); - if (!word) { - dst &= 0xff; - } + if (word) { + dst &= 0xffff; + } else if (wordx20) { + dst &= 0xfffff; + } else { + dst &= 0xff; + } } } else { // PC Could have changed above! @@ -1689,17 +1895,17 @@ public class MSP430Core extends Chip implements MSP430Constants { case ADD: // ADD // Tmp gives zero if same sign! if sign is different after -> overf. sr &= ~(OVERFLOW | CARRY); - - tmp = (src ^ dst) & (word ? 0x8000 : 0x80); + int b = word ? 0x8000 : (wordx20 ? 0x80000 : 0x80); + tmp = (src ^ dst) & b; // Includes carry if carry should be added... dst = dst + src + tmpAdd; - - if (dst > (word ? 0xffff : 0xff)) { + int b2 = word ? 0xffff : (wordx20 ? 0xfffff : 0xff); + if (dst > b2) { sr |= CARRY; } // If tmp == 0 and currenly not the same sign for src & dst - if (tmp == 0 && ((src ^ dst) & (word ? 0x8000 : 0x80)) != 0) { + if (tmp == 0 && ((src ^ dst) & b) != 0) { sr |= OVERFLOW; // System.out.println("OVERFLOW - ADD/SUB " + Utils.hex16(src) // + " + " + Utils.hex16(tmpDst)); @@ -1712,7 +1918,7 @@ public class MSP430Core extends Chip implements MSP430Constants { break; case CMP: // CMP // Set CARRY if A >= B, and it's clear if A < B - int b = word ? 0x8000 : 0x80; + b = word ? 0x8000 : (wordx20 ? 0x80000 : 0x80); sr = (sr & ~(CARRY | OVERFLOW)) | (dst >= src ? CARRY : 0); tmp = (dst - src); @@ -1760,7 +1966,8 @@ public class MSP430Core extends Chip implements MSP430Constants { break; case XOR: // XOR sr = sr & ~(CARRY | OVERFLOW); - if ((src & (word ? 0x8000 : 0x80)) != 0 && (dst & (word ? 0x8000 : 0x80)) != 0) { + b = word ? 0x8000 : (wordx20 ? 0x80000 : 0x80); + if ((src & b) != 0 && (dst & b) != 0) { sr |= OVERFLOW; } dst = src ^ dst; @@ -1790,12 +1997,14 @@ public class MSP430Core extends Chip implements MSP430Constants { /* If we have the same register as dst and src then copy here to get input * in next loop */ - if(repeats > 0 && srcRegister == dstRegister) { + if (repeats > 0 && srcRegister == dstRegister) { src = dst; - if (!word) { - src &= 0xff; + if (word) { + src &= 0xffff; + } else if (wordx20) { + src &= 0xfffff; } else { - src &= 0xffff; + src &= 0xff; } } } @@ -1804,6 +2013,8 @@ public class MSP430Core extends Chip implements MSP430Constants { /* Processing after each instruction */ if (word) { dst &= 0xffff; + } else if (wordx20) { + dst &= 0xfffff; } else { dst &= 0xff; } @@ -1822,7 +2033,8 @@ public class MSP430Core extends Chip implements MSP430Constants { sr = (sr & ~(ZERO | NEGATIVE)) | ((dst == 0) ? ZERO : 0) | (word ? ((dst & 0x8000) > 0 ? NEGATIVE : 0) : - ((dst & 0x80) > 0 ? NEGATIVE : 0)); + (wordx20 ? ((dst & 0x80000) > 0 ? NEGATIVE : 0) : + ((dst & 0x80) > 0 ? NEGATIVE : 0))); writeRegister(SR, sr); } diff --git a/se/sics/mspsim/core/UnifiedClockSystem.java b/se/sics/mspsim/core/UnifiedClockSystem.java new file mode 100644 index 0000000..ee61541 --- /dev/null +++ b/se/sics/mspsim/core/UnifiedClockSystem.java @@ -0,0 +1,396 @@ +/** + * Copyright (c) 2007, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of MSPSim. + * + * $Id$ + * + * ----------------------------------------------------------------- + * + * UnifiedClockSystem + * + * Author : Joakim Eriksson + * Author : Adam Dunkels + * Created : Sun Oct 21 22:00:00 2007 + * Updated : $Date$ + * $Revision$ + */ + +package se.sics.mspsim.core; +import se.sics.mspsim.util.Utils; + +public class UnifiedClockSystem extends ClockSystem { + + private static final int UCSCTL0 = 0x0160; + private static final int UCSCTL1 = 0x0162; + private static final int UCSCTL2 = 0x0164; + private static final int UCSCTL3 = 0x0166; + private static final int UCSCTL4 = 0x0168; + private static final int UCSCTL5 = 0x016a; + private static final int UCSCTL6 = 0x016c; + private static final int UCSCTL7 = 0x016e; + private static final int UCSCTL8 = 0x0170; + +/* UCSCTL0 Control Bits */ +// private static final int RESERVED = 0x0001; /* RESERVED */ +// private static final int RESERVED = 0x0002; /* RESERVED */ +// private static final int RESERVED = 0x0004; /* RESERVED */ + private static final int MOD_BITPOS = 3; + private static final int MOD_BITWIDTH = 5; + private static final int MOD0 = 0x0008; /* Modulation Bit Counter Bit : 0 */ + private static final int MOD1 = 0x0010; /* Modulation Bit Counter Bit : 1 */ + private static final int MOD2 = 0x0020; /* Modulation Bit Counter Bit : 2 */ + private static final int MOD3 = 0x0040; /* Modulation Bit Counter Bit : 3 */ + private static final int MOD4 = 0x0080; /* Modulation Bit Counter Bit : 4 */ + + private static final int DCO_BITPOS = 8; + private static final int DCO_BITWIDTH = 5; + private static final int DCO0 = 0x0100; /* DCO TAP Bit : 0 */ + private static final int DCO1 = 0x0200; /* DCO TAP Bit : 1 */ + private static final int DCO2 = 0x0400; /* DCO TAP Bit : 2 */ + private static final int DCO3 = 0x0800; /* DCO TAP Bit : 3 */ + private static final int DCO4 = 0x1000; /* DCO TAP Bit : 4 */ +// private static final int RESERVED = 0x2000; /* RESERVED */ +// private static final int RESERVED = 0x4000; /* RESERVED */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + + +/* UCSCTL1 Control Bits */ + private static final int DISMOD = 0x0001; /* Disable Modulation */ +// private static final int RESERVED = 0x0002; /* RESERVED */ +// private static final int RESERVED = 0x0004; /* RESERVED */ +// private static final int RESERVED = 0x0008; /* RESERVED */ + private static final int DCORSEL_BITPOS = 4; + private static final int DCORSEL_BITWIDTH = 3; + private static final int DCORSEL0 = 0x0010; /* DCO Freq. Range Select Bit : 0 */ + private static final int DCORSEL1 = 0x0020; /* DCO Freq. Range Select Bit : 1 */ + private static final int DCORSEL2 = 0x0040; /* DCO Freq. Range Select Bit : 2 */ +// private static final int RESERVED = 0x0080; /* RESERVED */ +// private static final int RESERVED = 0x0100; /* RESERVED */ +// private static final int RESERVED = 0x0200; /* RESERVED */ +// private static final int RESERVED = 0x0400; /* RESERVED */ +// private static final int RESERVED = 0x0800; /* RESERVED */ +// private static final int RESERVED = 0x1000; /* RESERVED */ +// private static final int RESERVED = 0x2000; /* RESERVED */ +// private static final int RESERVED = 0x4000; /* RESERVED */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + + +/* UCSCTL2 Control Bits */ + private static final int FLLN_BITPOS = 0; + private static final int FLLN_BITWIDTH = 10; + private static final int FLLN0 = 0x0001; /* FLL Multipier Bit : 0 */ + private static final int FLLN1 = 0x0002; /* FLL Multipier Bit : 1 */ + private static final int FLLN2 = 0x0004; /* FLL Multipier Bit : 2 */ + private static final int FLLN3 = 0x0008; /* FLL Multipier Bit : 3 */ + private static final int FLLN4 = 0x0010; /* FLL Multipier Bit : 4 */ + private static final int FLLN5 = 0x0020; /* FLL Multipier Bit : 5 */ + private static final int FLLN6 = 0x0040; /* FLL Multipier Bit : 6 */ + private static final int FLLN7 = 0x0080; /* FLL Multipier Bit : 7 */ + private static final int FLLN8 = 0x0100; /* FLL Multipier Bit : 8 */ + private static final int FLLN9 = 0x0200; /* FLL Multipier Bit : 9 */ +// private static final int RESERVED = 0x0400; /* RESERVED */ +// private static final int RESERVED = 0x0800; /* RESERVED */ + private static final int FLLD_BITPOS = 12; + private static final int FLLD_BITWIDTH = 3; + private static final int FLLD0 = 0x1000; /* Loop Divider Bit : 0 */ + private static final int FLLD1 = 0x2000; /* Loop Divider Bit : 1 */ + private static final int FLLD2 = 0x4000; /* Loop Divider Bit : 1 */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + + +/* UCSCTL3 Control Bits */ + private static final int FLLREFDIV_BITPOS = 0; + private static final int FLLREFDIV_BITWIDTH = 3; + private static final int FLLREFDIV0 = 0x0001; /* Reference Divider Bit : 0 */ + private static final int FLLREFDIV1 = 0x0002; /* Reference Divider Bit : 1 */ + private static final int FLLREFDIV2 = 0x0004; /* Reference Divider Bit : 2 */ +// private static final int RESERVED = 0x0008; /* RESERVED */ + private static final int SELREF_BITPOS = 4; + private static final int SELREF_BITWIDTH = 3; + private static final int SELREF0 = 0x0010; /* FLL Reference Clock Select Bit : 0 */ + private static final int SELREF1 = 0x0020; /* FLL Reference Clock Select Bit : 1 */ + private static final int SELREF2 = 0x0040; /* FLL Reference Clock Select Bit : 2 */ +// private static final int RESERVED = 0x0080; /* RESERVED */ +// private static final int RESERVED = 0x0100; /* RESERVED */ +// private static final int RESERVED = 0x0200; /* RESERVED */ +// private static final int RESERVED = 0x0400; /* RESERVED */ +// private static final int RESERVED = 0x0800; /* RESERVED */ +// private static final int RESERVED = 0x1000; /* RESERVED */ +// private static final int RESERVED = 0x2000; /* RESERVED */ +// private static final int RESERVED = 0x4000; /* RESERVED */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + +/* UCSCTL3 Control Bits */ + + private static final int FLLREFDIV_0 = 0x0000; /* Reference Divider: f(LFCLK);/1 */ + private static final int FLLREFDIV_1 = 0x0001; /* Reference Divider: f(LFCLK);/2 */ + private static final int FLLREFDIV_2 = 0x0002; /* Reference Divider: f(LFCLK);/4 */ + private static final int FLLREFDIV_3 = 0x0003; /* Reference Divider: f(LFCLK);/8 */ + private static final int FLLREFDIV_4 = 0x0004; /* Reference Divider: f(LFCLK);/12 */ + private static final int FLLREFDIV_5 = 0x0005; /* Reference Divider: f(LFCLK);/16 */ + private static final int FLLREFDIV_6 = 0x0006; /* Reference Divider: f(LFCLK);/16 */ + private static final int FLLREFDIV_7 = 0x0007; /* Reference Divider: f(LFCLK);/16 */ + private static final int FLLREFDIV__1 = 0x0000; /* Reference Divider: f(LFCLK);/1 */ + private static final int FLLREFDIV__2 = 0x0001; /* Reference Divider: f(LFCLK);/2 */ + private static final int FLLREFDIV__4 = 0x0002; /* Reference Divider: f(LFCLK);/4 */ + private static final int FLLREFDIV__8 = 0x0003; /* Reference Divider: f(LFCLK);/8 */ + private static final int FLLREFDIV__12 = 0x0004; /* Reference Divider: f(LFCLK);/12 */ + private static final int FLLREFDIV__16 = 0x0005; /* Reference Divider: f(LFCLK);/16 */ + private static final int SELREF_0 = 0x0000; /* FLL Reference Clock Select 0 */ + private static final int SELREF_1 = 0x0010; /* FLL Reference Clock Select 1 */ + private static final int SELREF_2 = 0x0020; /* FLL Reference Clock Select 2 */ + private static final int SELREF_3 = 0x0030; /* FLL Reference Clock Select 3 */ + private static final int SELREF_4 = 0x0040; /* FLL Reference Clock Select 4 */ + private static final int SELREF_5 = 0x0050; /* FLL Reference Clock Select 5 */ + private static final int SELREF_6 = 0x0060; /* FLL Reference Clock Select 6 */ + private static final int SELREF_7 = 0x0070; /* FLL Reference Clock Select 7 */ + private static final int SELREF__XT1CLK = 0x0000; /* Multiply Selected Loop Freq. By XT1CLK */ + private static final int SELREF__REFOCLK = 0x0020; /* Multiply Selected Loop Freq. By REFOCLK */ + private static final int SELREF__XT2CLK = 0x0050; /* Multiply Selected Loop Freq. By XT2CLK */ + +/* UCSCTL4 Control Bits */ + private static final int SELM0 = 0x0001; /* MCLK Source Select Bit: 0 */ + private static final int SELM1 = 0x0002; /* MCLK Source Select Bit: 1 */ + private static final int SELM2 = 0x0004; /* MCLK Source Select Bit: 2 */ +// private static final int RESERVED = 0x0008; /* RESERVED */ + private static final int SELS0 = 0x0010; /* SMCLK Source Select Bit: 0 */ + private static final int SELS1 = 0x0020; /* SMCLK Source Select Bit: 1 */ + private static final int SELS2 = 0x0040; /* SMCLK Source Select Bit: 2 */ +// private static final int RESERVED = 0x0080; /* RESERVED */ + private static final int SELA0 = 0x0100; /* ACLK Source Select Bit: 0 */ + private static final int SELA1 = 0x0200; /* ACLK Source Select Bit: 1 */ + private static final int SELA2 = 0x0400; /* ACLK Source Select Bit: 2 */ +// private static final int RESERVED = 0x0800; /* RESERVED */ +// private static final int RESERVED = 0x1000; /* RESERVED */ +// private static final int RESERVED = 0x2000; /* RESERVED */ +// private static final int RESERVED = 0x4000; /* RESERVED */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + +/* UCSCTL4 Control Bits */ + private static final int SELM__XT1CLK = 0x0000; /* MCLK Source Select XT1CLK */ + private static final int SELM__VLOCLK = 0x0001; /* MCLK Source Select VLOCLK */ + private static final int SELM__REFOCLK = 0x0002; /* MCLK Source Select REFOCLK */ + private static final int SELM__DCOCLK = 0x0003; /* MCLK Source Select DCOCLK */ + private static final int SELM__DCOCLKDIV = 0x0004; /* MCLK Source Select DCOCLKDIV */ + private static final int SELM__XT2CLK = 0x0005; /* MCLK Source Select XT2CLK */ + + private static final int SELS__XT1CLK = 0x0000; /* SMCLK Source Select XT1CLK */ + private static final int SELS__VLOCLK = 0x0010; /* SMCLK Source Select VLOCLK */ + private static final int SELS__REFOCLK = 0x0020; /* SMCLK Source Select REFOCLK */ + private static final int SELS__DCOCLK = 0x0030; /* SMCLK Source Select DCOCLK */ + private static final int SELS__DCOCLKDIV = 0x0040; /* SMCLK Source Select DCOCLKDIV */ + private static final int SELS__XT2CLK = 0x0050; /* SMCLK Source Select XT2CLK */ + + private static final int SELA__XT1CLK = 0x0000; /* ACLK Source Select XT1CLK */ + private static final int SELA__VLOCLK = 0x0100; /* ACLK Source Select VLOCLK */ + private static final int SELA__REFOCLK = 0x0200; /* ACLK Source Select REFOCLK */ + private static final int SELA__DCOCLK = 0x0300; /* ACLK Source Select DCOCLK */ + private static final int SELA__DCOCLKDIV = 0x0400; /* ACLK Source Select DCOCLKDIV */ + private static final int SELA__XT2CLK = 0x0500; /* ACLK Source Select XT2CLK */ + +/* UCSCTL5 Control Bits */ + private static final int DIVM0 = 0x0001; /* MCLK Divider Bit: 0 */ + private static final int DIVM1 = 0x0002; /* MCLK Divider Bit: 1 */ + private static final int DIVM2 = 0x0004; /* MCLK Divider Bit: 2 */ +// private static final int RESERVED = 0x0008; /* RESERVED */ + private static final int DIVS_BITPOS = 4; + private static final int DIVS_BITWIDTH = 3; + private static final int DIVS0 = 0x0010; /* SMCLK Divider Bit: 0 */ + private static final int DIVS1 = 0x0020; /* SMCLK Divider Bit: 1 */ + private static final int DIVS2 = 0x0040; /* SMCLK Divider Bit: 2 */ +// private static final int RESERVED = 0x0080; /* RESERVED */ + private static final int DIVA0 = 0x0100; /* ACLK Divider Bit: 0 */ + private static final int DIVA1 = 0x0200; /* ACLK Divider Bit: 1 */ + private static final int DIVA2 = 0x0400; /* ACLK Divider Bit: 2 */ +// private static final int RESERVED = 0x0800; /* RESERVED */ + private static final int DIVPA0 = 0x1000; /* ACLK from Pin Divider Bit: 0 */ + private static final int DIVPA1 = 0x2000; /* ACLK from Pin Divider Bit: 1 */ + private static final int DIVPA2 = 0x4000; /* ACLK from Pin Divider Bit: 2 */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + +/* UCSCTL6 Control Bits */ + private static final int XT1OFF = 0x0001; /* High Frequency Oscillator 1 (XT1); disable */ + private static final int SMCLKOFF = 0x0002; /* SMCLK Off */ + private static final int XCAP0 = 0x0004; /* XIN/XOUT Cap Bit: 0 */ + private static final int XCAP1 = 0x0008; /* XIN/XOUT Cap Bit: 1 */ + private static final int XT1BYPASS = 0x0010; /* XT1 bypass mode : 0: internal 1:sourced from external pin */ + private static final int XTS = 0x0020; /* 1: Selects high-freq. oscillator */ + private static final int XT1DRIVE0 = 0x0040; /* XT1 Drive Level mode Bit 0 */ + private static final int XT1DRIVE1 = 0x0080; /* XT1 Drive Level mode Bit 1 */ + private static final int XT2OFF = 0x0100; /* High Frequency Oscillator 2 (XT2); disable */ +// private static final int RESERVED = 0x0200; /* RESERVED */ +// private static final int RESERVED = 0x0400; /* RESERVED */ +// private static final int RESERVED = 0x0800; /* RESERVED */ + private static final int XT2BYPASS = 0x1000; /* XT2 bypass mode : 0: internal 1:sourced from external pin */ +// private static final int RESERVED = 0x2000; /* RESERVED */ + private static final int XT2DRIVE0 = 0x4000; /* XT2 Drive Level mode Bit 0 */ + private static final int XT2DRIVE1 = 0x8000; /* XT2 Drive Level mode Bit 1 */ + +/* UCSCTL7 Control Bits */ + private static final int DCOFFG = 0x0001; /* DCO Fault Flag */ + private static final int XT1LFOFFG = 0x0002; /* XT1 Low Frequency Oscillator Fault Flag */ + private static final int XT1HFOFFG = 0x0004; /* XT1 High Frequency Oscillator 1 Fault Flag */ + private static final int XT2OFFG = 0x0008; /* High Frequency Oscillator 2 Fault Flag */ +// private static final int RESERVED = 0x0010; /* RESERVED */ +// private static final int RESERVED = 0x0020; /* RESERVED */ +// private static final int RESERVED = 0x0040; /* RESERVED */ +// private static final int RESERVED = 0x0080; /* RESERVED */ +// private static final int RESERVED = 0x0100; /* RESERVED */ +// private static final int RESERVED = 0x0200; /* RESERVED */ +// private static final int RESERVED = 0x0400; /* RESERVED */ +// private static final int RESERVED = 0x0800; /* RESERVED */ +// private static final int RESERVED = 0x1000; /* RESERVED */ +// private static final int RESERVED = 0x2000; /* RESERVED */ +// private static final int RESERVED = 0x4000; /* RESERVED */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + +/* UCSCTL8 Control Bits */ + private static final int ACLKREQEN = 0x0001; /* ACLK Clock Request Enable */ + private static final int MCLKREQEN = 0x0002; /* MCLK Clock Request Enable */ + private static final int SMCLKREQEN = 0x0004; /* SMCLK Clock Request Enable */ + private static final int MODOSCREQEN = 0x0008; /* MODOSC Clock Request Enable */ +// private static final int RESERVED = 0x0010; /* RESERVED */ +// private static final int RESERVED = 0x0020; /* RESERVED */ +// private static final int RESERVED = 0x0040; /* RESERVED */ +// private static final int RESERVED = 0x0080; /* RESERVED */ +// private static final int RESERVED = 0x0100; /* RESERVED */ +// private static final int RESERVED = 0x0200; /* RESERVED */ +// private static final int RESERVED = 0x0400; /* RESERVED */ +// private static final int RESERVED = 0x0800; /* RESERVED */ +// private static final int RESERVED = 0x1000; /* RESERVED */ +// private static final int RESERVED = 0x2000; /* RESERVED */ +// private static final int RESERVED = 0x4000; /* RESERVED */ +// private static final int RESERVED = 0x8000; /* RESERVED */ + + + private static final int ACLK_FRQ = 32768; + private static final int MAX_DCO_FRQ = 16000000; + + + private MSP430Core core; + private Timer[] timers; + + private int currentDcoFrequency; + + /** + * Creates a new UnifiedClockSystem instance. + * + */ + public UnifiedClockSystem(MSP430Core core, int[] memory, int offset, Timer[] timers) { + super("UnifiedClockSystem", memory, offset); + this.core = core; + this.timers = timers; + } + + public int getMaxDCOFrequency() { + return MAX_DCO_FRQ; + } + + public int getAddressRangeMin() { + return UCSCTL0; + } + + public int getAddressRangeMax() { + return UCSCTL8; + } + + public void reset(int type) { + // Set the reset states, according to the SLAU208h data sheet. + write(UCSCTL0, 0x0000, true, core.cycles); + write(UCSCTL1, 0x0020, true, core.cycles); + write(UCSCTL2, 0x101f, true, core.cycles); + write(UCSCTL3, 0x0000, true, core.cycles); + write(UCSCTL4, 0x0044, true, core.cycles); + write(UCSCTL5, 0x0000, true, core.cycles); + write(UCSCTL6, 0xc1cd, true, core.cycles); + write(UCSCTL7, 0x0703, true, core.cycles); + write(UCSCTL8, 0x0707, true, core.cycles); + } + + // do nothing? + public int read(int address, boolean word, long cycles) { + int val = memory[address]; + if (word) { + val |= memory[(address + 1) & 0xffff] << 8; + } + return val; + } + + public void write(int address, int data, boolean word, long cycles) { + // Currently ignores the word flag... + if (DEBUG) log("Write to UnifiedClockSystem: " + + Utils.hex16(address) + " => " + Utils.hex16(data)); + + memory[address] = data & 0xff; + if (word) memory[address + 1] = (data >> 8) & 0xff; + + setConfiguration(cycles); + } + + public void interruptServiced(int vector) { + } + + + private void setConfiguration(long cycles) { + // Read a configuration from the UCSCTL* registers and compute the timer setup + + // Read Modulation counter and DCO TAP from UCSCTL0 (currently unused) + int modulationBitCounter = ((read(UCSCTL0, true, cycles) >> MOD_BITPOS) & ((1 << MOD_BITWIDTH) - 1)); + int dcoTap = ((read(UCSCTL0, true, cycles) >> DCO_BITPOS) & ((1 << DCO_BITWIDTH) - 1)); + + // Read modulation disable bit (currently unused) + int disableModulation = ((read(UCSCTL1, true, cycles) & DISMOD)); + + // Read DCO range selection from UCSCTL1 register + int dcoRange = ((read(UCSCTL1, true, cycles) >> DCORSEL_BITPOS) & ((1 << DCORSEL_BITWIDTH) - 1)); + + // Read DCO FLL multiplier and loop divider from the UCSCTL2 register + int dcoFLLMultiplier = (read(UCSCTL2, true, cycles) >> FLLN_BITPOS) & ((1 << FLLN_BITWIDTH) - 1); + int dcoLoopDivider = (read(UCSCTL2, true, cycles) >> FLLD_BITPOS) & ((1 << FLLD_BITWIDTH) - 1); + + // FLL reference clock divider and selection from UCSCTL3 (currently unused) + int fllRefDiv = (read(UCSCTL3, true, cycles) >> FLLREFDIV_BITPOS) & ((1 << FLLREFDIV_BITWIDTH) - 1); + int selRef = (read(UCSCTL3, true, cycles) >> SELREF_BITPOS) & ((1 << SELREF_BITWIDTH) - 1); + + // SMCLK divisor + int divSMclk = (read(UCSCTL5, true, cycles) >> DIVS_BITPOS) & ((1 << DIVS_BITWIDTH) - 1); + + int newDcoFrequency = (dcoFLLMultiplier + 1) * ACLK_FRQ; + + if (newDcoFrequency != currentDcoFrequency) { + currentDcoFrequency = newDcoFrequency; + core.setDCOFrq(currentDcoFrequency, currentDcoFrequency / (1 << divSMclk)); + + if (timers != null) { + for(int i = 0; i < timers.length; i++) { + timers[i].resetCounter(cycles); + } + } + } + } +} diff --git a/se/sics/mspsim/util/MapTable.java b/se/sics/mspsim/util/MapTable.java index 93f31d6..b4d09e6 100644 --- a/se/sics/mspsim/util/MapTable.java +++ b/se/sics/mspsim/util/MapTable.java @@ -27,12 +27,16 @@ * * This file is part of MSPSim. * + * $Id$ + * * ----------------------------------------------------------------- * * MapTable * * Author : Joakim Eriksson * Created : Sun Oct 21 22:00:00 2007 + * Updated : $Date$ + * $Revision$ */ package se.sics.mspsim.util; @@ -261,7 +265,7 @@ public class MapTable { int totsize = 0; int totdata = map.dataFill, totbss = map.bssFill; int totmemory = totdata + totbss; - System.out.printf("%7s %7s %7s %4s %s\n", + System.out.printf("%6s %6s %6s %4s %s\n", "text", "data", "bss", "addr", "name"); for (int i = 0; i < map.modules.size(); i++) { MapEntry module = map.modules.get(i); diff --git a/se/sics/mspsim/util/StackMonitor.java b/se/sics/mspsim/util/StackMonitor.java index 6b44eff..4b09926 100644 --- a/se/sics/mspsim/util/StackMonitor.java +++ b/se/sics/mspsim/util/StackMonitor.java @@ -47,7 +47,7 @@ public class StackMonitor implements CPUMonitor { public StackMonitor(MSP430 cpu) { this.cpu = cpu; - this.cpu.addRegisterWriteMonitor(MSP430.SP, this); + this.cpu.setRegisterWriteMonitor(MSP430.SP, this); Object p = cpu.getRegistry().getComponent("profiler"); if (p instanceof SimpleProfiler) { ((SimpleProfiler) p).setStackMonitor(this);