package fabrik.simulator.pic16f84; import java.util.Arrays; public class DataRegister { private static final int INDF = 0x0; private static final int PCL = 0x2; private static final int STATUS = 0x3; private static final int FSR = 0x4; private static final int PORTA = 0x5; private static final int PORTB = 0x6; private static final int PCLATH = 0xA; private static final int INTCON = 0xB; private static final int EEDATA = 0x08; private static final int EEADR = 0x09; private static final int EECON1 = 0x88; private static final int EECON2 = 0x89; private static final int TRISA = 0x85; private static final int TRISB = 0x86; private static final int C = 0x0; private static final int DC = 0x1; private static final int Z = 0x2; private static final int RP0 = 0x5; private static final int [] dataRegister = new int[0xFF]; private static final int [] syncedRegisters = {INDF, PCL, STATUS, FSR, PCLATH, INTCON}; private static final int [] eepromRegisters = {EEDATA, EEADR, EECON1, EECON2}; public static final int [] ioRegisters = {PORTA, PORTB, TRISA, TRISB}; public static void initDataRegister() { dataRegister[PCL] = 0b0; dataRegister[STATUS] = 0b00011000; dataRegister[PCLATH] = 0b0; dataRegister[INTCON] = 0b0; dataRegister[0x81] = 0b11111111; dataRegister[0x80 + PCL] = dataRegister[PCL]; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; dataRegister[TRISA] = 0b11111111; dataRegister[TRISB] = 0b11111111; dataRegister[0x80 + PCLATH] = dataRegister[PCLATH]; dataRegister[0x80 + INTCON] = dataRegister[INTCON]; System.out.println(Arrays.toString(dataRegister)); } private static boolean isSyncedRegister (int address){ for (int register : syncedRegisters){ if (address == register || address == 0x80 + register){ return true; } } return false; } public static int[] getDataRegister() { return dataRegister; } private static int determineIndirectAndChange (int address){ if (address == INDF || address == 0x80 + INDF) { return dataRegister[FSR]; } else return address; } public static int getFSR (){ return dataRegister[FSR]; } private static int bank() { return ((dataRegister[STATUS] >> RP0) & 1) * 0x80; } public static int getRegister(int fileAddress){ int address = determineIndirectAndChange (fileAddress); if (bank () + address == EECON2) return 0; return dataRegister[bank() + address]; } public static void setRegister(int fileAddress, int content){ int address = determineIndirectAndChange (fileAddress); if (Arrays.stream(ioRegisters).anyMatch(i -> i == address)){ IOPorts.setRegister(bank() + address, content); return; } if (Arrays.stream(eepromRegisters).anyMatch(i -> i == address)){ EEPROM.parse(bank() + address, content, 0b11); return; } if (fileAddress == PCL || fileAddress == 0x80 + PCL){ programCounter = content + (dataRegister[PCLATH] << 8); } if (!isSyncedRegister(address)) dataRegister[bank() + address] = content; else { dataRegister[address] = content; dataRegister[0x80 + address] = content; if (address == STATUS){ setFlags(); } } if (address == 1) PreScaler.resetFromRegister(); } public static int getBit(int fileAddress, int bit) { int address = determineIndirectAndChange (fileAddress); if (bank() + address == EECON2) return 0; return (dataRegister[bank() + address] >> bit) & 1; } public static int getDirectBit(int address, int bit){ return (dataRegister[address] >> bit) & 1; } public static void clearBit(int fileAddress, int bit) { int address = determineIndirectAndChange (fileAddress); if (Arrays.stream(ioRegisters).anyMatch(i -> i == address)){ IOPorts.clearBit(bank() + address, bit); return; } if (Arrays.stream(eepromRegisters).anyMatch(i -> i == address)){ EEPROM.parse(bank () + address, bit, 0b00); return; } if (!isSyncedRegister(address)) { if (getBit(address, bit) == 1) { dataRegister[bank() + address] -= (int) Math.pow(2, bit); } } else { if (getBit(address, bit) == 1) { dataRegister[address] -= (int) Math.pow(2, bit); dataRegister[0x80 + address] = dataRegister[address]; if (address == STATUS){ setFlags(); } } } if (address == 1) PreScaler.resetFromRegister(); } public static void setBit(int fileAddress, int bit) { int address = determineIndirectAndChange (fileAddress); if (Arrays.stream(ioRegisters).anyMatch(i -> i == address)){ IOPorts.setBit(bank() + address, bit); return; } if (Arrays.stream(eepromRegisters).anyMatch(i -> i == address)){ EEPROM.parse(bank () + address, bit, 0b10); return; } if (!isSyncedRegister(address)) { if (getBit(address, bit) == 0) { dataRegister[bank() + address] += (int) Math.pow(2, bit); } } else { if (getBit(address, bit) == 0) { dataRegister[address] += (int) Math.pow(2, bit); dataRegister[0x80 + address] = dataRegister[address]; if (address == STATUS){ setFlags(); } } } if (address == 1) PreScaler.resetFromRegister(); } public static void setDirectBit (int fileAddress, int bit, int value){ if (getDirectBit(fileAddress, bit) == 0 && value == 1){ dataRegister[fileAddress] += (int) Math.pow(2, bit); } else if (getDirectBit(fileAddress, bit) == 1 && value == 0){ dataRegister[fileAddress] -= (int) Math.pow(2, bit); } } private static int programCounter = 0; private static void writeToPCL(){ dataRegister[PCL] = programCounter & 0xFF; dataRegister[0x80 + PCL] = dataRegister[PCL]; } public static void increasePC (){ if (programCounter != 0x3FF) { programCounter++; } else { programCounter = 0; } writeToPCL(); } public static void setPC (int value){ programCounter = value + ((getRegister(PCLATH) & 0b11000) << 8); writeToPCL(); } public static void resetPC () { programCounter = 0; } public static int getPC(){ return programCounter; } private static void setFlags() { carryFlag = getDirectBit(STATUS, C); digitCarryFlag = getDirectBit(STATUS, DC); zeroFlag = getDirectBit(STATUS, Z); } private static int zeroFlag = 0; public static void determineZeroFlag(int result){ if (result == 0){ zeroFlag = 1; if (getBit(STATUS, Z) == 0){ dataRegister[STATUS] += 0b100; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } else { zeroFlag = 0; if (getBit(STATUS, Z) == 1){ dataRegister[STATUS] -= 0b100; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } } public static int getZeroFlag(){ return zeroFlag; } private static int carryFlag = 0; public static void setCarryFlag(int value){ carryFlag = value; if (value == 1){ if (getBit(STATUS, C) == 0){ dataRegister[STATUS] += 0b1; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } else { if (getBit(STATUS, C) == 1){ dataRegister[STATUS] -= 0b1; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } } public static void determineCarryFlag (int result){ if (result > 0xFF){ setCarryFlag(1); } else { setCarryFlag(0); } } public static int getCarryFlag (){ return carryFlag; } private static int digitCarryFlag = 0; public static void setDigitCarryFlag(int value){ digitCarryFlag = value; if (value == 1){ if (getBit(STATUS, DC) == 0){ dataRegister[STATUS] += 0b10; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } else { if (getBit(STATUS, DC) == 1){ dataRegister[STATUS] -= 0b10; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } } public static void determineDigitCarryFlag(int result){ if (result > 0xF){ setDigitCarryFlag(1); } else { setDigitCarryFlag(0); } } public static int getDigitCarryFlag(){ return digitCarryFlag; } public static void setDirectRegister(int fileAddress, int content) { dataRegister[fileAddress] = content; } public static int getPCL() { return PCL; } public static int getSTATUS() { return STATUS; } public static int getPCLATH() { return PCLATH; } public static int getINTCON() { return INTCON; } public static int getDirectRegister(int address) { return dataRegister[address]; } }