| 
							
							
							
						 |  |  | @@ -1,9 +1,9 @@ | 
		
	
		
			
				|  |  |  |  | #include "semihosting.h" | 
		
	
		
			
				|  |  |  |  | #include <cstdint> | 
		
	
		
			
				|  |  |  |  | #include <map> | 
		
	
		
			
				|  |  |  |  | #include <iss/vm_types.h> | 
		
	
		
			
				|  |  |  |  | #include <stdexcept> | 
		
	
		
			
				|  |  |  |  | #include <chrono> | 
		
	
		
			
				|  |  |  |  | #include <cstdint> | 
		
	
		
			
				|  |  |  |  | #include <iss/vm_types.h> | 
		
	
		
			
				|  |  |  |  | #include <map> | 
		
	
		
			
				|  |  |  |  | #include <stdexcept> | 
		
	
		
			
				|  |  |  |  | // explanation of syscalls can be found at https://github.com/SpinalHDL/openocd_riscv/blob/riscv_spinal/src/target/semihosting_common.h | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | const char* SYS_OPEN_MODES_STRS[] = {"r", "rb", "r+", "r+b", "w", "wb", "w+", "w+b", "a", "ab", "a+", "a+b"}; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -15,7 +15,9 @@ template <typename T> T sh_read_field(iss::arch_if* arch_if_ptr, T addr, int len | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     if(res != iss::Ok) { | 
		
	
		
			
				|  |  |  |  |         return 0; // TODO THROW ERROR | 
		
	
		
			
				|  |  |  |  |     } else return static_cast<T>(bytes[0]) | (static_cast<T>(bytes[1]) << 8) | (static_cast<T>(bytes[2]) << 16) | (static_cast<T>(bytes[3]) << 24); | 
		
	
		
			
				|  |  |  |  |     } else | 
		
	
		
			
				|  |  |  |  |         return static_cast<T>(bytes[0]) | (static_cast<T>(bytes[1]) << 8) | (static_cast<T>(bytes[2]) << 16) | | 
		
	
		
			
				|  |  |  |  |                (static_cast<T>(bytes[3]) << 24); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T> std::string sh_read_string(iss::arch_if* arch_if_ptr, T addr, T str_len) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -27,7 +29,6 @@ template <typename T> std::string sh_read_string(iss::arch_if* arch_if_ptr, T ad | 
		
	
		
			
				|  |  |  |  |     return str; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arch_if_ptr, T* call_number, T* parameter) { | 
		
	
		
			
				|  |  |  |  |     static std::map<T, FILE*> openFiles; | 
		
	
		
			
				|  |  |  |  |     static T file_count = 3; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -80,7 +81,8 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc | 
		
	
		
			
				|  |  |  |  |         auto file = openFiles[file_handle]; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         size_t currentPos = ftell(file); | 
		
	
		
			
				|  |  |  |  |         if (currentPos < 0) throw std::runtime_error("SYS_FLEN negative value"); | 
		
	
		
			
				|  |  |  |  |         if(currentPos < 0) | 
		
	
		
			
				|  |  |  |  |             throw std::runtime_error("SYS_FLEN negative value"); | 
		
	
		
			
				|  |  |  |  |         fseek(file, 0, SEEK_END); | 
		
	
		
			
				|  |  |  |  |         size_t length = ftell(file); | 
		
	
		
			
				|  |  |  |  |         fseek(file, currentPos, SEEK_SET); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -138,7 +140,6 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc | 
		
	
		
			
				|  |  |  |  |         openFiles[file_handle] = file; | 
		
	
		
			
				|  |  |  |  |         *call_number = file_handle; | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     case semihosting_syscalls::SYS_READ: { | 
		
	
		
			
				|  |  |  |  |         T file_handle = sh_read_field<T>(arch_if_ptr, (*parameter) + 4); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -149,12 +150,10 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         std::vector<uint8_t> buffer(count); | 
		
	
		
			
				|  |  |  |  |         size_t num_read = 0; | 
		
	
		
			
				|  |  |  |  |         if (file == stdin) | 
		
	
		
			
				|  |  |  |  |         { | 
		
	
		
			
				|  |  |  |  |         if(file == stdin) { | 
		
	
		
			
				|  |  |  |  |             // when reading from stdin: mimic behaviour from read syscall | 
		
	
		
			
				|  |  |  |  |             // and return on newline. | 
		
	
		
			
				|  |  |  |  |             while (num_read < count) | 
		
	
		
			
				|  |  |  |  |             { | 
		
	
		
			
				|  |  |  |  |             while(num_read < count) { | 
		
	
		
			
				|  |  |  |  |                 char c = fgetc(file); | 
		
	
		
			
				|  |  |  |  |                 buffer[num_read] = c; | 
		
	
		
			
				|  |  |  |  |                 num_read++; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -172,7 +171,6 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         *call_number = count - num_read; | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     case semihosting_syscalls::SYS_READC: { | 
		
	
		
			
				|  |  |  |  |         uint8_t character = getchar(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -188,7 +186,8 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc | 
		
	
		
			
				|  |  |  |  |         T path_len = sh_read_field<T>(arch_if_ptr, (*parameter) + 4); | 
		
	
		
			
				|  |  |  |  |         std::string path_str = sh_read_string<T>(arch_if_ptr, path_str_addr, path_len); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         if(remove(path_str.c_str())<0) *call_number = -1; | 
		
	
		
			
				|  |  |  |  |         if(remove(path_str.c_str()) < 0) | 
		
	
		
			
				|  |  |  |  |             *call_number = -1; | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     case semihosting_syscalls::SYS_RENAME: { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -208,7 +207,8 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc | 
		
	
		
			
				|  |  |  |  |         auto file = openFiles[file_handle]; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         int retval = fseek(file, pos, SEEK_SET); | 
		
	
		
			
				|  |  |  |  |         if(retval<0) throw std::runtime_error("SYS_SEEK negative return value"); | 
		
	
		
			
				|  |  |  |  |         if(retval < 0) | 
		
	
		
			
				|  |  |  |  |             throw std::runtime_error("SYS_SEEK negative return value"); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -244,7 +244,8 @@ template <typename T> void semihosting_callback<T>::operator()(iss::arch_if* arc | 
		
	
		
			
				|  |  |  |  |         for(int i = 0; i < buffer_len; i++) { | 
		
	
		
			
				|  |  |  |  |             uint8_t character = filename[i]; | 
		
	
		
			
				|  |  |  |  |             auto res = arch_if_ptr->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, (*parameter) + i, 1, &character); | 
		
	
		
			
				|  |  |  |  |             if(res != iss::Ok) return; | 
		
	
		
			
				|  |  |  |  |             if(res != iss::Ok) | 
		
	
		
			
				|  |  |  |  |                 return; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
	
		
			
				
					
					|  |  |  |   |