20 #include <sys/signal.h> 22 #include <sys/types.h> 30 #include <unordered_map> 37 #include <mach-o/dyld.h> 122 unsigned int misc = 0xFFFFFFFF;
128 enum class BoardInstruction : unsigned char {
161 inline unsigned char operator|(BoardInstruction l,
unsigned char r) {
162 return static_cast<unsigned char>(l) | r;
238 const uint32_t s_address,
239 int*
const increment,
240 const int currentAddressI,
241 unsigned char (*memdata)[52]);
246 inline void sendChar(
unsigned char);
252 inline const int getChar(
unsigned char*);
268 const unsigned char*
const);
272 unsigned char*
const,
284 const char*
const pathToS,
285 const char*
const pathToKMD) {
286 char *file_name, *fnoext, *tmp;
295 file_name = strdup(pathToS);
296 tmp = strrchr(file_name,
'/');
297 fnoext = strchr(file_name,
'.');
304 int dfd = open(
"/dev/null", O_RDWR);
308 execlp(pathToBin.append(
"/aasm.sh").c_str(),
"aasm.sh", file_name, tmp+1, (
char*)0);
310 const char *p = pathToBin.append(
"/aasm").c_str();
311 char *cmd = (
char*)malloc(0x500);
312 sprintf(cmd,
"%s -lk %s %s", p, pathToKMD, pathToS);
338 sendChar(static_cast<unsigned char>(BoardInstruction::START));
349 sendChar(static_cast<unsigned char>(BoardInstruction::CONTINUE));
357 sendChar(static_cast<unsigned char>(BoardInstruction::STOP));
364 sendChar(static_cast<unsigned char>(BoardInstruction::RESET));
373 unsigned int wordA = 0, wordB = 0;
388 if (((wordA >> i) & 1) != 0) {
403 int temp = (~wordA) & wordB;
426 switch (board_state) {
427 case ClientState::RUNNING_SWI:
429 case ClientState::RUNNING:
431 case ClientState::STEPPING:
433 case ClientState::MEMFAULT:
435 case ClientState::BUSY:
437 case ClientState::FINISHED:
439 case ClientState::BREAKPOINT:
442 return ClientState::NORMAL;
456 std::array<std::string, 16> ret;
459 for (
long unsigned int i = 0; i < ret.size(); i++) {
471 unsigned char string[256];
472 unsigned char length = 1;
474 std::string output(
"");
477 sendChar(static_cast<unsigned char>(BoardInstruction::FR_READ));
485 string[length] =
'\0';
486 output.append((
char*)
string);
500 unsigned int key_pressed = val;
501 unsigned char res = 0;
504 if (((key_pressed >=
' ') && (key_pressed <= 0x7F)) ||
505 (key_pressed ==
'\n') || (key_pressed ==
'\b') || (key_pressed ==
'\t') ||
506 (key_pressed ==
'\a')) {
507 sendChar(static_cast<unsigned char>(
508 BoardInstruction::FR_WRITE));
526 const uint32_t s_address) {
527 constexpr
int count = 13;
532 unsigned char* p = (
unsigned char*)&s_address;
534 currentAddressS[0] &= -4;
537 unsigned char memdata[bytecount];
538 sendChar(static_cast<unsigned char>(BoardInstruction::GET_MEM));
544 bool firstFlag =
false;
547 if (source.
pStart != NULL) {
549 while ((src != NULL) && ((src->
address < s_address) || not src->
hasData)) {
559 while ((src != NULL) && not src->
hasData) {
567 std::array<Jimulator::MemoryValues, 13> readValues;
571 for (
long unsigned int i = 0; i < readValues.size(); i++) {
573 unsigned int currentAddressI =
575 readValues[i].address = currentAddressI;
576 readValues[i].hex = std::string(
"00000000");
577 readValues[i].disassembly = std::string(
"...");
580 if (src != NULL && currentAddressI == src->
address) {
581 readValues[i].disassembly =
582 std::regex_replace(std::string(src->
text), std::regex(
";.*$"),
"");
584 currentAddressI, &memdata);
586 firstFlag =
moveSrc(firstFlag, &src);
592 auto iter = bps.find(readValues[i].address);
593 if (iter != bps.end()) {
594 readValues[i].breakpoint =
true;
617 for (; (((v >> i) & 1) == 0); i++)
687 unsigned int* wordB) {
688 sendChar(static_cast<unsigned char>(BoardInstruction::BP_GET));
689 return not((
getNBytes((
int*)wordA, 4) != 4) ||
701 if ((*src)->next != NULL) {
702 (*src) = (*src)->next;
711 }
while (((*src) != NULL) && not(*src)->hasData);
730 const uint32_t s_address,
731 int*
const increment,
732 const int currentAddressI,
733 unsigned char (*memdata)[52]) {
734 std::string hex =
"";
737 if ((*src)->dataSize[i] > 0) {
738 char spaces[5] = {0};
743 &((*memdata)[currentAddressI - s_address + *increment]));
746 for (; j < (*src)->dataSize[i]; j++) {
757 *increment = *increment + (*src)->dataSize[i];
775 sendChar(static_cast<unsigned char>(BoardInstruction::BP_READ));
800 const unsigned char*
const s2) {
816 unsigned char* source,
817 unsigned char* dest) {
830 sendChar(static_cast<unsigned char>(BoardInstruction::BP_SET));
844 sendChar(static_cast<unsigned char>(BoardInstruction::BP_WRITE));
859 struct pollfd pollfd;
861 pollfd.events = POLLOUT;
865 std::cout <<
"Client system not responding!\n";
870 std::cout <<
"Pipe write error!\n";
878 inline void sendChar(
unsigned char data) {
892 unsigned char buffer[n];
895 for (
auto& c : buffer) {
910 inline const int getCharArray(
int length,
unsigned char* data) {
913 struct pollfd pollfd;
916 pollfd.events = POLLIN;
931 if (reply_count == 0) {
936 if (reply_count < 0) {
940 reply_total += reply_count;
941 length -= reply_count;
953 inline const int getChar(
unsigned char* data) {
966 inline const int getNBytes(
int* data,
int n) {
975 for (
int i = 0; i < numberOfReceivedBytes; i++) {
979 return numberOfReceivedBytes;
987 unsigned char clientStatus = 0;
992 sendChar(static_cast<unsigned char>(BoardInstruction::WOT_U_DO));
994 if (
getChar(&clientStatus) != 1 ||
997 std::cout <<
"board not responding\n";
998 return ClientState::BROKEN;
1004 return static_cast<ClientState
>(clientStatus);
1014 unsigned char data[64];
1016 sendChar(static_cast<unsigned char>(BoardInstruction::GET_REG));
1021 std::array<unsigned char, 64> ret;
1022 std::copy(std::begin(data), std::end(data), std::begin(ret));
1037 unsigned char*
const v,
1038 const bool prepend0x) {
1039 std::stringstream ss;
1046 ss << std::setfill(
'0') << std::setw(2) << std::uppercase << std::hex
1090 if (temp >= 0x100) {
1105 unsigned int addr) {
1106 if (src == NULL || src ==
nullptr) {
1110 unsigned int diff = src->
address - addr;
1125 return 4 - (addr % 4);
1139 std::unordered_map<u_int32_t, bool> breakpointAddresses;
1140 unsigned int wordA, wordB;
1147 if (((wordA >> i) & 1) != 0) {
1152 breakpointAddresses.insert({addr,
true});
1160 return breakpointAddresses;
1172 source.pStart = NULL;
1175 while (old != NULL) {
1176 if (old->
text != NULL) {
1192 if ((character >=
'0') && (character <=
'9')) {
1193 return character -
'0';
1194 }
else if ((character >=
'A') && (character <=
'F')) {
1195 return character -
'A' + 10;
1196 }
else if ((character >=
'a') && (character <=
'f')) {
1197 return character -
'a' + 10;
1212 unsigned int*
const n) {
1213 while ((*c ==
' ') || (*c ==
'\t')) {
1217 int j = 0, value = 0;
1220 value = (value << 4) | digit;
1235 for (k = 1; k < j; k = k << 1) {
1274 unsigned char*
const value,
1291 int byteTotal, textLength;
1304 FILE* komodoSource = fopen(pathToKMD,
"r");
1305 if (komodoSource == NULL) {
1306 std::cout <<
"Source could not be opened!\n";
1310 bool hasOldAddress =
false;
1313 while (not feof(komodoSource)) {
1314 unsigned int address = 0;
1316 char c = getc(komodoSource);
1320 hasOldAddress =
false;
1336 c = getc(komodoSource);
1344 if (dSize[j] == 0) {
1348 byteTotal = byteTotal + dSize[j];
1351 oldAddress = address + byteTotal;
1352 hasOldAddress =
true;
1355 else if (hasOldAddress) {
1356 address = oldAddress;
1362 while ((c !=
';') && (c !=
'\n') && not feof(komodoSource)) {
1363 c = getc(komodoSource);
1368 c = getc(komodoSource);
1370 c = getc(komodoSource);
1376 while ((c !=
'\n') && not feof(komodoSource) &&
1378 buffer[textLength++] = c;
1379 c = getc(komodoSource);
1382 buffer[textLength++] =
'\0';
1384 currentLine->
address = address;
1388 currentLine->
dataSize[j] = dSize[j];
1391 if ((currentLine->
dataSize[j] > 0) &&
1393 unsigned char addr[4], data[4];
1395 for (
int i = 0; i < 4; i++) {
1399 for (
int i = 0; i < currentLine->
dataSize[j]; i++) {
1408 byteTotal = byteTotal + currentLine->
dataSize[j];
1409 currentLine->
hasData = (byteTotal != 0);
1420 byteTotal = byteTotal - currentLine->
dataSize[j];
1422 dSize[j] = currentLine->
dataSize[j];
1428 std::cout <<
"OVERFLOW " << dSize[0] <<
" " << dSize[1] <<
" " 1429 << dSize[2] <<
" " << dSize[3] <<
" " << byteTotal
1434 currentLine->
text = (
char *)malloc(textLength);
1435 for (
int j = 0; j < textLength; j++) {
1436 currentLine->
text[j] = buffer[j];
1442 while ((temp1 != NULL) && (address >= temp1->
address)) {
1444 temp1 = temp1->
next;
1447 currentLine->
next = temp1;
1448 currentLine->
prev = temp2;
1450 if (temp1 != NULL) {
1451 temp1->
prev = currentLine;
1453 source.pEnd = currentLine;
1456 if (temp2 != NULL) {
1457 temp2->
next = currentLine;
1459 source.pStart = currentLine;
1466 while ((c !=
'\n') && not feof(komodoSource)) {
1467 c = getc(komodoSource);
1471 fclose(komodoSource);
1475 char * stokmd(
char *file_name) {
1476 char *s = strdup(file_name);
1478 *strrchr(s,
'.') = 0;
1480 len = strlen(file_name);
1481 s = (
char *)realloc(s, len + 5);
1487 char * getKcmdPath() {
1489 uint32_t size = 0x100;
1490 dbuf =
new char[size];
1492 if(_NSGetExecutablePath(dbuf, &size) != 0) {
1493 std::cerr <<
"Failed to get path for kcmd.\n";
1497 if(readlink(
"/proc/self/exe", dbuf, size-1) < 0) {
1510 std::cout <<
"A pipe error ocurred." << std::endl;
1530 auto jimulatorPath = argv0.append(
"/jimulator").c_str();
1531 execlp(jimulatorPath,
"jimulator", (
char*)0);
1537 static void initTerm() {
1539 tcgetattr(0, &oldt);
1540 termios newt = oldt;
1541 newt.c_lflag &= ~(ECHO|ICANON);
1542 tcsetattr(0, TCSANOW, &newt);
1543 std::cout.setf(std::ios::unitbuf);
1544 std::cin.setf(std::ios::unitbuf);
1547 static void handle_io() {
1550 t1 =
new std::thread([&]() ->
void {
1559 t2 =
new std::thread([&]() ->
void {
1569 int main(
int argc,
char** argv) {
1571 std::cout <<
"usage: " << argv[0] <<
" <asm file>\n";
1575 char *kcmd_path = getKcmdPath();
1576 char *kmd_path = stokmd(argv[1]);
1578 *strrchr(kcmd_path,
'/') = 0;
const std::string integerArrayToHexString(int, unsigned char *const, const bool=false)
Converts an array of integers into a formatted hexadecimal string.
unsigned int address
The address of the source line.
Describes an entire file of a .kmd sourceFile.
void sendCharArray(int, unsigned char *)
Sends an array of characters to Jimulator.
unsigned char operator|(BoardInstruction l, unsigned char r)
Performing an or between a BoardInstruction and an unsigned char.
constexpr void copyStringLiterals(int, unsigned char *, unsigned char *)
Copy one string literal into another string literal.
constexpr int IN_POLL_TIMEOUT
The maximum amount of time to wait after sending input to the pipes.
bool hasData
A flag that indicates that the line stores internal data or not.
char * text
Text, as read from the source file.
SourceFileLine * pEnd
The last line in a source file.
void resetJimulator()
Reset the emulators running.
const int getCharArray(int, unsigned char *)
reads an array of characters from Jimulator.
unsigned char addressB[ADDRESS_BUS_WIDTH]
A secondary address for a breakpoint.
const std::string generateMemoryHex(SourceFileLine **src, const uint32_t s_address, int *const increment, const int currentAddressI, unsigned char(*memdata)[52])
Get the hex values from the memory data.
const bool getBreakpointStatus(unsigned int *, unsigned int *)
Gets the status of breakpoints from within Jimulator.
unsigned char dataA[8]
Data associated with the breakpoint.
constexpr const unsigned int boardTranslateMemsize(const int size)
Converts a provided memory size into a Jimulator legal memory size.
void compileJimulator(std::string pathToBin, const char *const pathToS, const char *const pathToKMD)
Runs pathToS through the associated compiler binary, and outputs a .kmd file at pathToKMD.
constexpr int SOURCE_FIELD_COUNT
The number of fields that can be used in a source file.
unsigned int misc
Miscellaneous information associated with the breakpoint.
unsigned char addressA[ADDRESS_BUS_WIDTH]
The address of the breakpoint.
const bool setBreakpoint(const uint32_t address)
Sets a breakpoint.
int writeToJimulator
Stores the file descriptor used for writing to Jimulator.
constexpr int SOURCE_BYTE_COUNT
The maximum number of bytes that can be read from a source file.
constexpr int OUT_POLL_TIMEOUT
The maximum amount of time to wait waiting for output from the pipes.
Describes a single line of a .kmd file.
void setBreakpointStatus(unsigned int, unsigned int)
Overwrites some breakpoint information into Jimulator.
constexpr const int rotateRight1Byte(const int val)
Rotates an integers bits to the right by 1 byte.
void initJimulator(const std::string argv0)
Initialises Jimulator in a separate child process.
unsigned char dataB[8]
Data associated with the secondary breakpoint.
constexpr const char getLeastSignificantByte(const int)
Get the least significant byte out of an integer - if little endian, get the most signficant byte...
constexpr int SOURCE_TEXT_LENGTH
The maximum length of a line in a source file.
constexpr int ADDRESS_BUS_WIDTH
The width of Jimulators internal address bus.
void sendChar(unsigned char)
Sends a singular character to Jimulator.
constexpr const int disassembleSourceFile(SourceFileLine *, unsigned int)
Calculates the difference between the current address to display and the next address that needs to b...
void pauseJimulator()
Pauses the emulator running.
SourceFileLine * pStart
The first line in a source file.
const int getNBytes(int *, int)
Reads n bytes of data from Jimulator.
const std::unordered_map< u_int32_t, bool > getAllBreakpoints()
Reads all of the breakpoints from Jimulator into a map that can be indexed by address. The address is the key, with a boolean as the value to form a pair. However the boolean is redundant - since the address is the key, if you lookup an address in the map and it is present, you know that a breakpoint was found there.
constexpr const int checkHexCharacter(const char character)
Check if the passed character represents a legal hex digit.
int dataValue[4]
Stores the data values.
int emulator_PID
This variable will store the PID of the Jimulator process.
constexpr const int numericStringSubtraction(const unsigned char *const, const unsigned char *const)
Takes two string literals of equal length which represent string forms of integers - for example...
constexpr const bool moveSrc(bool firstFlag, SourceFileLine **src)
Steps any given source line to the next valid source line.
sourceFile source
The source file that is currently loaded into Jimulator.
void startJimulator(const int steps)
Commences running the emulator.
constexpr const int rotateLeft1Byte(const int val)
Rotates an integers bits to the left by 1 byte.
const bool sendTerminalInputToJimulator(const unsigned int val)
Sends terminal information to Jimulator.
void setBreakpointDefinition(unsigned int, BreakpointInfo *)
Writes a new breakpoint into the breakpoint list.
constexpr int MAX_NUMBER_OF_BREAKPOINTS
The maximum number of breakpoints within the application.
const std::array< unsigned char, 64 > readRegistersIntoArray()
Gets serialized bit data from the board that represents 16 register values - 15 general purpose regis...
const bool loadJimulator(const char *const pathToKMD)
Clears the existing source object and loads the file at pathToKMD into Jimulator. ...
const int getChar(unsigned char *)
Reads a singular character from Jimulator.
int readFromJimulator
Stores the file descriptor used for reading from Jimulator.
void flushSourceFile()
removes all of the old references to the previous file.
constexpr const int getNextFreeBreakpoint(const int)
Gets the index of the next free breakpoint from Jimulators internal breakpoint list.
int communicationToJimulator[2]
The pipe which will be used by KoMo2 to write to Jimulator (i.e. Jimulator will read from it...
int communicationFromJimulator[2]
The pipe which will be used by KoMo2 to read from Jimulator (i.e. Jimulator will write to it...
SourceFileLine * next
The next line of the overall source file.
SourceFileLine * prev
The previous line of the overall source file.
const ClientState getBoardStatus()
Gets a code that indicates the internal state of Jimulator.
void continueJimulator()
Continues running Jimulator.
constexpr void numericStringAndIntAddition(unsigned char *const, int)
Takes a string representation of an integer - for example, the string {'5' '7' '2'} representing the ...
const bool readSourceFile(const char *const)
Reads the source of the file pointer to by pathToKMD.
std::array< Jimulator::MemoryValues, 13 > getJimulatorMemoryValues(const uint32_t s_address_int)
Get the memory values from Jimulator, starting to s_address.
constexpr const int readNumberFromFile(FILE *const f, char *const c, unsigned int *const n)
Reads a n from a string of text in the .kmd file.
int compilerCommunication[2]
The pipe that handles communication between the compiler process and KoMo2.
const bool getBreakpointDefinition(unsigned int, BreakpointInfo *)
Reads a breakpoint definition for use by the breakpoints callbacks.
void boardSetMemory(unsigned char *const address, unsigned char *const value, const int size)
Sets a memory value of a given address to a new value. This code is LEGACY. It used to run with a che...
int main(int argc, char *argv[])
The program entry point.
Contains the information read from Jimulator about a given breakpoint.
const ClientState checkBoardState()
Check the state of the board - logs what it is doing.
constexpr const int numericStringToInt(int, const unsigned char *const)
Takes a string literals which represent a string form of an integer - for example, the number 5 represented as the string {'5'}, or the number 327 represented as the string {'3', '2', '7'} - and returns the value represented as an int. For example: Input string {'8', '1', '8'} will result in the output 818.
const std::string getJimulatorTerminalMessages()
Reads for messages from Jimulator, to display in the terminal output.
void sendNBytes(int, int)
Writes n bytes of data to Jimulator.
const std::array< std::string, 16 > getJimulatorRegisterValues()
Queries a register in Jimulator to get it's current value.
int dataSize[4]
Stores the size of the data fields.