quick-n-dirty num to str
This commit is contained in:
		
							parent
							
								
									a1c74760a1
								
							
						
					
					
						commit
						af01b5afae
					
				
							
								
								
									
										180
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										180
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
/* #define MEMORY_SIZE 65536 /\* 64KB memory (adjustable) *\/ */
 | 
			
		||||
#define MEMORY_SIZE 200 
 | 
			
		||||
#define MEMORY_SIZE 1024
 | 
			
		||||
typedef union {
 | 
			
		||||
  float f;
 | 
			
		||||
  uint32_t u;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,28 +15,78 @@ typedef union {
 | 
			
		|||
Data memory[MEMORY_SIZE]; /* Memory array */
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  OP_HALT,    /* terminate execution */
 | 
			
		||||
  OP_ADD,     /* dest = src1 + src2  */
 | 
			
		||||
  OP_SUB,     /* dest = src1 - src2  */
 | 
			
		||||
  OP_MUL,     /* dest = src1 * src2  */
 | 
			
		||||
  OP_DIV,     /* dest = src1 / src2  */
 | 
			
		||||
  OP_ADD_F32, /* dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_F32, /* dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_F32, /* dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_F32, /* dest = src1 / src2  */
 | 
			
		||||
  OP_MOV,     /* dest = src1	     */
 | 
			
		||||
  OP_JMP,     /* jump to address src1 unconditionally */
 | 
			
		||||
  OP_JGZ,     /* jump to address dest if src1 > 0 */
 | 
			
		||||
  OP_HALT,          /* terminate execution */
 | 
			
		||||
  OP_ADD,           /* dest = src1 + src2  */
 | 
			
		||||
  OP_SUB,           /* dest = src1 - src2  */
 | 
			
		||||
  OP_MUL,           /* dest = src1 * src2  */
 | 
			
		||||
  OP_DIV,           /* dest = src1 / src2  */
 | 
			
		||||
  OP_ADD_F32,       /* dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_F32,       /* dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_F32,       /* dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_F32,       /* dest = src1 / src2  */
 | 
			
		||||
  OP_MOV,           /* dest = src1	     */
 | 
			
		||||
  OP_JMP,           /* jump to address src1 unconditionally */
 | 
			
		||||
  OP_JGZ,           /* jump to address dest if src1 > 0 */
 | 
			
		||||
  OP_INT_TO_STRING, /* dest = src1 as str */
 | 
			
		||||
  OP_F32_TO_STRING, /* dest = src2 as str */
 | 
			
		||||
  OP_READ_STRING,
 | 
			
		||||
  OP_PRINT_STRING,
 | 
			
		||||
} Opcode;
 | 
			
		||||
 | 
			
		||||
int core_dump() {
 | 
			
		||||
  FILE *file = fopen("memory_dump.bin", "wb");
 | 
			
		||||
  if (!file) {
 | 
			
		||||
    perror("Failed to open file");
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
  size_t written = fwrite(memory, 1, MEMORY_SIZE, file);
 | 
			
		||||
  if (written != MEMORY_SIZE) {
 | 
			
		||||
    fprintf(stderr, "Incomplete write: %zu bytes written out of %u\n", written,
 | 
			
		||||
            MEMORY_SIZE);
 | 
			
		||||
    fclose(file);
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fclose(file);
 | 
			
		||||
  return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t get_char(uint32_t word, int index) {
 | 
			
		||||
  return (word >> (8 * index)) & 0xFF;
 | 
			
		||||
  return (word >> (8 * (3 - index))) & 0xFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t set_char(uint32_t word, int index, uint8_t ch) {
 | 
			
		||||
  return (word & ~(0xFF << (8 * index))) | (ch << (8 * index));
 | 
			
		||||
  return (word & ~(0xFF << (8 * (3 - index)))) | (ch << (8 * (3 - index)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Pack string into union-based memory */
 | 
			
		||||
void pack_string(const char *str, uint32_t length, uint32_t dest_addr) {
 | 
			
		||||
  memory[dest_addr].u = length;
 | 
			
		||||
  uint32_t buffer_addr = dest_addr + 1;
 | 
			
		||||
  int word_index = 0;
 | 
			
		||||
  int char_index = 0;
 | 
			
		||||
 | 
			
		||||
  uint32_t i = 0;
 | 
			
		||||
  while (i < length) {
 | 
			
		||||
    char ch = str[i++];
 | 
			
		||||
    if (ch == '\0' || ch == EOF) {
 | 
			
		||||
      uint32_t word = memory[buffer_addr + word_index].u;
 | 
			
		||||
      word = set_char(word, char_index, '\0');
 | 
			
		||||
      memory[buffer_addr + word_index].u = word;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t word = memory[buffer_addr + word_index].u;
 | 
			
		||||
    word = set_char(word, char_index, ch);
 | 
			
		||||
    memory[buffer_addr + word_index].u = word;
 | 
			
		||||
 | 
			
		||||
    char_index++;
 | 
			
		||||
    if (char_index == 4) {
 | 
			
		||||
      char_index = 0;
 | 
			
		||||
      word_index++;
 | 
			
		||||
    }
 | 
			
		||||
    length++;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void run_vm() {
 | 
			
		||||
| 
						 | 
				
			
			@ -109,22 +159,32 @@ void run_vm() {
 | 
			
		|||
      pc = (jump_target & mask) | (pc & ~mask);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OP_INT_TO_STRING: {
 | 
			
		||||
      int32_t a = (int32_t)memory[src1_addr].u;
 | 
			
		||||
      char buffer[32];
 | 
			
		||||
      sprintf(buffer, "%d", a);
 | 
			
		||||
      pack_string(buffer, strlen(buffer), dest_addr);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OP_F32_TO_STRING: {
 | 
			
		||||
      float a = memory[src1_addr].f;
 | 
			
		||||
      char buffer[32];
 | 
			
		||||
      sprintf(buffer, "%f", a);
 | 
			
		||||
      pack_string(buffer, strlen(buffer), dest_addr);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case OP_PRINT_STRING: {
 | 
			
		||||
      uint32_t string_addr = src1_addr;
 | 
			
		||||
      uint32_t length = memory[src1_addr-1].u;
 | 
			
		||||
 | 
			
		||||
      uint32_t length = memory[src1_addr - 1].u;
 | 
			
		||||
      uint32_t i;
 | 
			
		||||
      while (i < length) {
 | 
			
		||||
        int j = 0;
 | 
			
		||||
        uint32_t word = memory[string_addr + (i++)].u;
 | 
			
		||||
        for (j = 0; j < 4; j++) {
 | 
			
		||||
          char ch = (word >> (8 * j)) & 0xFF;
 | 
			
		||||
          if (ch == '\0')
 | 
			
		||||
            goto done;
 | 
			
		||||
          putchar(ch);
 | 
			
		||||
        }
 | 
			
		||||
      for (i = 0; i < length;) {
 | 
			
		||||
        uint32_t word = memory[string_addr + (i / 4)].u;
 | 
			
		||||
        uint8_t ch = get_char(word, i % 4);
 | 
			
		||||
        if (ch == '\0')
 | 
			
		||||
          break;
 | 
			
		||||
        putchar(ch);
 | 
			
		||||
        i++;
 | 
			
		||||
      }
 | 
			
		||||
    done:
 | 
			
		||||
      putchar('\n');
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -132,31 +192,30 @@ void run_vm() {
 | 
			
		|||
      putchar('>');
 | 
			
		||||
      putchar(' ');
 | 
			
		||||
      uint32_t buffer_addr = dest_addr + 1;
 | 
			
		||||
      uint32_t length = 0;
 | 
			
		||||
      int word_index = 0;
 | 
			
		||||
      int char_index = 0;
 | 
			
		||||
      uint32_t length = 1;
 | 
			
		||||
 | 
			
		||||
      while (1) {
 | 
			
		||||
        int ch = getchar();
 | 
			
		||||
        if (ch == '\n' || ch == EOF) {
 | 
			
		||||
          /* Store null terminator */
 | 
			
		||||
          uint32_t word = memory[buffer_addr + word_index].u;
 | 
			
		||||
          word = set_char(word, char_index, '\0');
 | 
			
		||||
          memory[buffer_addr + word_index].u = word;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint32_t word = memory[buffer_addr + word_index].u;
 | 
			
		||||
        word = set_char(word, char_index, ch);
 | 
			
		||||
        memory[buffer_addr + word_index].u = word;
 | 
			
		||||
        length++;
 | 
			
		||||
 | 
			
		||||
        char_index++;
 | 
			
		||||
        if (char_index == 4) {
 | 
			
		||||
          char_index = 0;
 | 
			
		||||
          word_index++;
 | 
			
		||||
        }
 | 
			
		||||
        length++;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      memory[dest_addr].u = length;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -168,27 +227,28 @@ void run_vm() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
  memory[0].u = OP_READ_STRING;
 | 
			
		||||
  memory[1].u = 0;
 | 
			
		||||
  memory[2].u = 0;
 | 
			
		||||
  memory[3].u = 104;
 | 
			
		||||
  memory[4].u = OP_ADD_F32;
 | 
			
		||||
  memory[5].u = 102;
 | 
			
		||||
  memory[6].u = 103;
 | 
			
		||||
  memory[7].u = 103;
 | 
			
		||||
  memory[8].u = OP_SUB;
 | 
			
		||||
  memory[9].u = 100;
 | 
			
		||||
  memory[10].u = 101;
 | 
			
		||||
  memory[11].u = 100;
 | 
			
		||||
  memory[12].u = OP_JGZ;
 | 
			
		||||
  memory[13].u = 100;
 | 
			
		||||
  memory[14].u = 4;
 | 
			
		||||
  memory[15].u = 4;
 | 
			
		||||
  memory[16].u = OP_PRINT_STRING;
 | 
			
		||||
  memory[17].u = 105;
 | 
			
		||||
  memory[18].u = 0;
 | 
			
		||||
  memory[19].u = 0;
 | 
			
		||||
  memory[20].u = OP_HALT;
 | 
			
		||||
  int i = 0;
 | 
			
		||||
  memory[i++].u = OP_ADD_F32;
 | 
			
		||||
  memory[i++].u = 102;
 | 
			
		||||
  memory[i++].u = 103;
 | 
			
		||||
  memory[i++].u = 103;
 | 
			
		||||
  memory[i++].u = OP_SUB;
 | 
			
		||||
  memory[i++].u = 100;
 | 
			
		||||
  memory[i++].u = 101;
 | 
			
		||||
  memory[i++].u = 100;
 | 
			
		||||
  memory[i++].u = OP_JGZ;
 | 
			
		||||
  memory[i++].u = 100;
 | 
			
		||||
  memory[i++].u = 4;
 | 
			
		||||
  memory[i++].u = 4;
 | 
			
		||||
  memory[i++].u = OP_F32_TO_STRING;
 | 
			
		||||
  memory[i++].u = 103;
 | 
			
		||||
  memory[i++].u = 0;
 | 
			
		||||
  memory[i++].u = 104;
 | 
			
		||||
  memory[i++].u = OP_PRINT_STRING;
 | 
			
		||||
  memory[i++].u = 105;
 | 
			
		||||
  memory[i++].u = 0;
 | 
			
		||||
  memory[i++].u = 0;
 | 
			
		||||
  memory[i++].u = OP_HALT;
 | 
			
		||||
  memory[100].u = 5;
 | 
			
		||||
  memory[101].u = 1;
 | 
			
		||||
  memory[102].f = 5.f;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,19 +256,5 @@ int main() {
 | 
			
		|||
 | 
			
		||||
  run_vm();
 | 
			
		||||
 | 
			
		||||
    FILE *file = fopen("memory_dump.bin", "wb");
 | 
			
		||||
    if (!file) {
 | 
			
		||||
        perror("Failed to open file");
 | 
			
		||||
        return EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
    size_t written = fwrite(memory, 1, MEMORY_SIZE, file);
 | 
			
		||||
    if (written != MEMORY_SIZE) {
 | 
			
		||||
        fprintf(stderr, "Incomplete write: %zu bytes written out of %u\n", written, MEMORY_SIZE);
 | 
			
		||||
        fclose(file);
 | 
			
		||||
        return EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fclose(file);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
  return core_dump();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue