mirror of https://github.com/contiki-ng/mspsim
Merge branch 'master' of git://mspsim.git.sourceforge.net/gitroot/mspsim/mspsim
This commit is contained in:
commit
c195e4082e
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <code>UnifiedClockSystem</code> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue