delete test, add combined type
This commit is contained in:
parent
cdf21dd5cf
commit
2817e940e1
|
@ -1,176 +0,0 @@
|
|||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MEMORY_SIZE 65536 // 64KB memory (adjustable)
|
||||
uint32_t memory[MEMORY_SIZE]; // Memory array
|
||||
#define DEBUG_PRINT \
|
||||
printf("dest[%d]=%d, src1[%d]=%d, src2[%d]=%d\n", dest_addr, \
|
||||
memory[dest_addr], src1_addr, memory[src1_addr], src2_addr, \
|
||||
memory[src2_addr]);
|
||||
|
||||
typedef enum {
|
||||
OP_HALT, // terminate execution
|
||||
OP_ADD, // dest = src1 + src2
|
||||
OP_SUB, // dest = src1 - src2
|
||||
OP_MOV, // dest = src1
|
||||
OP_JMP, // jump to address src1 unconditionally
|
||||
OP_JGZ, // jump to address dest if src1 > 0
|
||||
OP_READ_STRING,
|
||||
OP_PRINT_STRING,
|
||||
} Opcode;
|
||||
|
||||
uint8_t get_char(uint32_t word, int index) {
|
||||
return (word >> (8 * index)) & 0xFF;
|
||||
}
|
||||
|
||||
uint32_t set_char(uint32_t word, int index, uint8_t ch) {
|
||||
return (word & ~(0xFF << (8 * index))) | (ch << (8 * index));
|
||||
}
|
||||
|
||||
void run_vm() {
|
||||
uint32_t pc = 0; // Program counter
|
||||
while (pc < MEMORY_SIZE - 4) {
|
||||
// Fetch instruction
|
||||
Opcode opcode = memory[pc];
|
||||
uint32_t src1_addr = memory[pc + 1];
|
||||
uint32_t src2_addr = memory[pc + 2];
|
||||
uint32_t dest_addr = memory[pc + 3];
|
||||
pc += 4; // Advance to next instruction
|
||||
|
||||
// Validate addresses (safety check)
|
||||
if (src1_addr >= MEMORY_SIZE || src2_addr >= MEMORY_SIZE ||
|
||||
dest_addr >= MEMORY_SIZE) {
|
||||
printf("Invalid memory address!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("opcode: ");
|
||||
// Execute instruction
|
||||
switch (opcode) {
|
||||
case OP_ADD:
|
||||
printf("ADD, ");
|
||||
DEBUG_PRINT
|
||||
memory[dest_addr] = memory[src1_addr] + memory[src2_addr];
|
||||
break;
|
||||
case OP_SUB:
|
||||
printf("SUB, ");
|
||||
DEBUG_PRINT
|
||||
memory[dest_addr] = memory[src1_addr] - memory[src2_addr];
|
||||
break;
|
||||
case OP_HALT:
|
||||
printf("HALT, ");
|
||||
return;
|
||||
case OP_MOV:
|
||||
printf("MOV, ");
|
||||
DEBUG_PRINT
|
||||
memory[dest_addr] = memory[src1_addr];
|
||||
break;
|
||||
case OP_JMP:
|
||||
printf("JMP, ");
|
||||
DEBUG_PRINT
|
||||
pc = src1_addr; // Jump to address
|
||||
break;
|
||||
case OP_JGZ: {
|
||||
printf("JGZ, ");
|
||||
DEBUG_PRINT
|
||||
uint32_t value = memory[src1_addr];
|
||||
uint32_t jump_target = src2_addr;
|
||||
|
||||
// Branchless greater-than-zero check
|
||||
int32_t mask = -((uint32_t)(value > 0));
|
||||
pc = (jump_target & mask) | (pc & ~mask);
|
||||
break;
|
||||
}
|
||||
case OP_PRINT_STRING: {
|
||||
printf("PRINT_STR, ");
|
||||
uint32_t string_addr = src1_addr;
|
||||
int i = 0;
|
||||
while (1) {
|
||||
uint32_t word = memory[string_addr + (i++)];
|
||||
for (int j = 0; j < 4; j++) {
|
||||
char ch = (word >> (8 * j)) & 0xFF;
|
||||
if (ch == '\0')
|
||||
goto done;
|
||||
putchar(ch);
|
||||
}
|
||||
}
|
||||
done:
|
||||
putchar('\n');
|
||||
break;
|
||||
}
|
||||
case OP_READ_STRING: {
|
||||
printf("READ_STR, ");
|
||||
uint32_t buffer_addr = dest_addr;
|
||||
char buffer[4];
|
||||
int word_index = 0;
|
||||
int char_index = 0;
|
||||
|
||||
while (1) {
|
||||
int ch = getchar();
|
||||
if (ch == '\n' || ch == EOF) {
|
||||
// Store null terminator
|
||||
uint32_t word = memory[buffer_addr + word_index];
|
||||
word = set_char(word, char_index, '\0');
|
||||
memory[buffer_addr + word_index] = word;
|
||||
break;
|
||||
}
|
||||
uint32_t word = memory[buffer_addr + word_index];
|
||||
word = set_char(word, char_index, ch);
|
||||
memory[buffer_addr + word_index] = word;
|
||||
|
||||
char_index++;
|
||||
if (char_index == 4) {
|
||||
char_index = 0;
|
||||
word_index++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DEBUG_PRINT
|
||||
printf("Unknown opcode: %d\n", opcode);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Initialize memory
|
||||
memory[0] = OP_READ_STRING;
|
||||
memory[1] = 0; // unused
|
||||
memory[2] = 0; // unused
|
||||
memory[3] = 104; // dest
|
||||
memory[4] = OP_ADD;
|
||||
memory[5] = 102; // A (src1)
|
||||
memory[6] = 103; // B (src2)
|
||||
memory[7] = 103; // C (dest)
|
||||
memory[8] = OP_SUB;
|
||||
memory[9] = 100; // counter (src1)
|
||||
memory[10] = 101; // value (src2)
|
||||
memory[11] = 100; // counter (dest)
|
||||
memory[12] = OP_JGZ;
|
||||
memory[13] = 100; // (src1)
|
||||
memory[14] = 4; // (src2)
|
||||
memory[15] = 4; // (dest)
|
||||
memory[16] = OP_PRINT_STRING;
|
||||
memory[17] = 104; // String address
|
||||
memory[18] = 0; // Unused
|
||||
memory[19] = 0; // Unused
|
||||
memory[20] = OP_HALT; // Terminate after ADD
|
||||
memory[100] = 5; // Value of A
|
||||
memory[101] = 1; // Value of B
|
||||
memory[102] = 5;
|
||||
memory[103] = 5;
|
||||
/* memcpy(&memory[104], "hell", 4); */
|
||||
/* memcpy(&memory[105], "o\n\0\0", 4); */
|
||||
|
||||
run_vm();
|
||||
|
||||
printf("Result at address 103: %u\n", memory[103]); // Output: 12
|
||||
return 0;
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Q16.16 fixed-point macros
|
||||
#define Q16_16_SCALE 16
|
||||
#define Q16_16_FRACTION_MASK 0x0000FFFF
|
||||
#define TO_Q16_16(x) \
|
||||
((int32_t)((x) << Q16_16_SCALE)) // Convert integer to Q16.16
|
||||
#define FROM_Q16_16(x) \
|
||||
((int32_t)((x) >> Q16_16_SCALE)) // Convert Q16.16 to integer
|
||||
|
||||
#define MEMORY_SIZE 65536
|
||||
int32_t memory[MEMORY_SIZE]; // Changed to signed for fixed-point support
|
||||
|
||||
typedef enum { OP_ADD, OP_MOV, OP_JMP, OP_HALT } Opcode;
|
||||
|
||||
|
||||
// Convert string to Q16.16 fixed-point
|
||||
int32_t string_to_q16_16(const char *str) {
|
||||
int32_t result = 0;
|
||||
int sign = 1;
|
||||
|
||||
// Handle sign
|
||||
if (*str == '-') {
|
||||
sign = -1;
|
||||
str++;
|
||||
}
|
||||
|
||||
// Parse integer part
|
||||
int32_t integer_part = 0;
|
||||
while (*str != '.' && *str != '\0') {
|
||||
if (*str < '0' || *str > '9') {
|
||||
return 0; // Invalid character
|
||||
}
|
||||
integer_part = integer_part * 10 + (*str - '0');
|
||||
str++;
|
||||
}
|
||||
|
||||
// Clamp integer part to 16-bit range
|
||||
if (integer_part > 32767) {
|
||||
integer_part = 32767; // Overflow clamp
|
||||
}
|
||||
|
||||
// Parse fractional part
|
||||
uint32_t frac_digits = 0;
|
||||
int frac_count = 0;
|
||||
|
||||
if (*str == '.') {
|
||||
str++; // Skip decimal point
|
||||
while (*str != '\0' && frac_count < 6) {
|
||||
if (*str < '0' || *str > '9') {
|
||||
break;
|
||||
}
|
||||
frac_digits = frac_digits * 10 + (*str - '0');
|
||||
frac_count++;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
// Scale fractional part to Q16.16
|
||||
// frac_q16 = (frac_digits * 65536 + 500000) / 1000000
|
||||
// This avoids floating-point by using integer arithmetic
|
||||
uint32_t scaled_frac = 0;
|
||||
if (frac_count > 0) {
|
||||
// Pad with zeros if less than 6 digits
|
||||
while (frac_count < 6) {
|
||||
frac_digits *= 10;
|
||||
frac_count++;
|
||||
}
|
||||
// Compute scaled fractional part with rounding
|
||||
scaled_frac = (frac_digits * 65536 + 500000) / 1000000;
|
||||
if (scaled_frac > 0xFFFF) {
|
||||
scaled_frac = 0xFFFF; // Clamp to 16-bit range
|
||||
}
|
||||
}
|
||||
|
||||
// Combine integer and fractional parts
|
||||
result = (integer_part << Q16_16_SCALE) | (scaled_frac & Q16_16_FRACTION_MASK);
|
||||
return result * sign;
|
||||
}
|
||||
|
||||
// Convert Q16.16 to string using integer-only arithmetic
|
||||
int q16_16_to_string(int32_t value, char *buffer, size_t size) {
|
||||
if (size < 13) { // Minimum buffer size for "-32768.000000\0"
|
||||
if (size > 0)
|
||||
buffer[0] = '\0';
|
||||
return -1; // Buffer too small
|
||||
}
|
||||
|
||||
char *buf = buffer;
|
||||
size_t remaining = size;
|
||||
|
||||
// Handle sign
|
||||
if (value < 0) {
|
||||
*buf++ = '-';
|
||||
value = -value;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
// Extract integer and fractional parts
|
||||
int32_t integer_part = value >> Q16_16_SCALE;
|
||||
uint32_t frac = value & Q16_16_FRACTION_MASK;
|
||||
|
||||
// Convert integer part to string
|
||||
char int_buf[11]; // Max 10 digits for 32-bit int
|
||||
char *int_end = int_buf + sizeof(int_buf);
|
||||
char *int_ptr = int_end;
|
||||
|
||||
// Special case for zero
|
||||
if (integer_part == 0) {
|
||||
*--int_ptr = '0';
|
||||
} else {
|
||||
while (integer_part > 0 && int_ptr > int_buf) {
|
||||
*--int_ptr = '0' + (integer_part % 10);
|
||||
integer_part /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy integer part to output buffer
|
||||
while (int_ptr < int_end && remaining > 1) {
|
||||
*buf++ = *int_ptr++;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
// Add decimal point
|
||||
if (remaining > 7) { // Need space for .000000
|
||||
*buf++ = '.';
|
||||
remaining--;
|
||||
} else {
|
||||
if (remaining > 0)
|
||||
*buf = '\0';
|
||||
return size - remaining; // Truncate if insufficient space
|
||||
}
|
||||
|
||||
// Convert fractional part to 6 digits
|
||||
for (int i = 0; i < 6 && remaining > 1; i++) {
|
||||
frac *= 10;
|
||||
uint32_t digit = frac >> 16;
|
||||
frac &= 0xFFFF;
|
||||
*buf++ = '0' + digit;
|
||||
remaining--;
|
||||
}
|
||||
|
||||
// Null-terminate
|
||||
*buf = '\0';
|
||||
return buf - buffer; // Return length written
|
||||
}
|
||||
|
||||
void run_vm() {
|
||||
uint32_t pc = 0;
|
||||
while (1) {
|
||||
Opcode opcode = memory[pc];
|
||||
uint32_t src1_addr = memory[pc + 1];
|
||||
uint32_t src2_addr = memory[pc + 2];
|
||||
uint32_t dest_addr = memory[pc + 3];
|
||||
pc += 4;
|
||||
|
||||
if (src1_addr >= MEMORY_SIZE || src2_addr >= MEMORY_SIZE ||
|
||||
dest_addr >= MEMORY_SIZE) {
|
||||
printf("Invalid memory address!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case OP_ADD:
|
||||
// Q16.16 addition requires no scaling adjustment
|
||||
memory[dest_addr] = memory[src1_addr] + memory[src2_addr];
|
||||
break;
|
||||
case OP_MOV:
|
||||
// Direct copy preserves fixed-point representation
|
||||
memory[dest_addr] = memory[src1_addr];
|
||||
break;
|
||||
case OP_JMP:
|
||||
pc = src1_addr;
|
||||
break;
|
||||
case OP_HALT:
|
||||
return;
|
||||
default:
|
||||
printf("Unknown opcode: %d\n", opcode);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Initialize memory with Q16.16 values
|
||||
memory[0] = OP_ADD;
|
||||
memory[1] = 100;
|
||||
memory[2] = 101;
|
||||
memory[3] = 102;
|
||||
const char *input = "-5.0";
|
||||
memory[100] = string_to_q16_16(input); // Convert "-5.0" to Q16.16
|
||||
const char *input2 = "10.0";
|
||||
memory[101] = string_to_q16_16(input2); // Convert "10.0" to Q16.16
|
||||
memory[4] = OP_HALT;
|
||||
|
||||
run_vm();
|
||||
|
||||
char buffer[13]; // Sufficient for Q16.16 format
|
||||
|
||||
// Convert result back to integer
|
||||
q16_16_to_string(memory[102], buffer, sizeof(buffer));
|
||||
printf("Result at address 102: %s\n", buffer); // Output: 5.0
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
# Compiler and flags
|
||||
CC = gcc
|
||||
CFLAGS += -std=c11 -g -Wall -Wextra -Werror -Wno-unused-parameter
|
||||
CFLAGS += -std=c89 -g -Wall -Wextra -Werror -Wno-unused-parameter
|
||||
LDFLAGS +=
|
||||
LDLIBS +=
|
||||
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MEMORY_SIZE 65536 /* 64KB memory (adjustable) */
|
||||
typedef union {
|
||||
float f;
|
||||
uint32_t u;
|
||||
} FloatUint32Union;
|
||||
FloatUint32Union 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_READ_STRING,
|
||||
OP_PRINT_STRING,
|
||||
} Opcode;
|
||||
|
||||
uint8_t get_char(uint32_t word, int index) {
|
||||
return (word >> (8 * index)) & 0xFF;
|
||||
}
|
||||
|
||||
uint32_t set_char(uint32_t word, int index, uint8_t ch) {
|
||||
return (word & ~(0xFF << (8 * index))) | (ch << (8 * index));
|
||||
}
|
||||
void run_vm() {
|
||||
uint32_t pc = 0; /* Program counter */
|
||||
|
||||
while (pc < MEMORY_SIZE - 4) {
|
||||
|
||||
Opcode opcode = memory[pc].u;
|
||||
uint32_t src1_addr = memory[pc + 1].u;
|
||||
uint32_t src2_addr = memory[pc + 2].u;
|
||||
uint32_t dest_addr = memory[pc + 3].u;
|
||||
pc += 4; /* Advance to next instruction */
|
||||
|
||||
if (src1_addr >= MEMORY_SIZE || src2_addr >= MEMORY_SIZE ||
|
||||
dest_addr >= MEMORY_SIZE) {
|
||||
printf("Invalid memory address!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case OP_ADD:
|
||||
memory[dest_addr].u = memory[src1_addr].u + memory[src2_addr].u;
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
break;
|
||||
|
||||
case OP_SUB:
|
||||
memory[dest_addr].u = memory[src1_addr].u - memory[src2_addr].u;
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
break;
|
||||
|
||||
case OP_MUL:
|
||||
memory[dest_addr].u = memory[src1_addr].u * memory[src2_addr].u;
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
break;
|
||||
|
||||
case OP_DIV:
|
||||
memory[dest_addr].u = memory[src1_addr].u / memory[src2_addr].u;
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
break;
|
||||
|
||||
case OP_ADD_F32:
|
||||
memory[dest_addr].f = memory[src1_addr].f + memory[src2_addr].f;
|
||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
||||
memory[dest_addr].f);
|
||||
break;
|
||||
|
||||
case OP_SUB_F32:
|
||||
memory[dest_addr].f = memory[src1_addr].f - memory[src2_addr].f;
|
||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
||||
memory[dest_addr].f);
|
||||
break;
|
||||
|
||||
case OP_MUL_F32:
|
||||
memory[dest_addr].f = memory[src1_addr].f * memory[src2_addr].f;
|
||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
||||
memory[dest_addr].f);
|
||||
break;
|
||||
|
||||
case OP_DIV_F32:
|
||||
if (memory[src2_addr].f == 0.0f) {
|
||||
printf("Division by zero error at address %d\n", pc - 4);
|
||||
exit(1);
|
||||
}
|
||||
memory[dest_addr].f = memory[src1_addr].f / memory[src2_addr].f;
|
||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
||||
memory[dest_addr].f);
|
||||
break;
|
||||
case OP_HALT:
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
return;
|
||||
case OP_MOV:
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
memory[dest_addr] = memory[src1_addr];
|
||||
break;
|
||||
case OP_JMP:
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
pc = src1_addr; /* Jump to address */
|
||||
break;
|
||||
case OP_JGZ: {
|
||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
||||
memory[dest_addr].u);
|
||||
uint32_t value = memory[src1_addr].u;
|
||||
uint32_t jump_target = src2_addr;
|
||||
|
||||
/* Branchless greater-than-zero check */
|
||||
int32_t mask = -((uint32_t)(value > 0));
|
||||
pc = (jump_target & mask) | (pc & ~mask);
|
||||
break;
|
||||
}
|
||||
case OP_PRINT_STRING: {
|
||||
printf("PRINT_STRING;");
|
||||
uint32_t string_addr = src1_addr;
|
||||
int i = 0;
|
||||
while (1) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
done:
|
||||
putchar('\n');
|
||||
break;
|
||||
}
|
||||
case OP_READ_STRING: {
|
||||
printf("> ");
|
||||
uint32_t buffer_addr = dest_addr;
|
||||
int word_index = 0;
|
||||
int char_index = 0;
|
||||
|
||||
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;
|
||||
|
||||
char_index++;
|
||||
if (char_index == 4) {
|
||||
char_index = 0;
|
||||
word_index++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("Unknown opcode: %d\n", opcode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = 104;
|
||||
memory[18].u = 0;
|
||||
memory[19].u = 0;
|
||||
memory[20].u = OP_HALT;
|
||||
memory[100].u = 5;
|
||||
memory[101].u = 1;
|
||||
memory[102].f = 5.f;
|
||||
memory[103].f = 5.f;
|
||||
|
||||
run_vm();
|
||||
|
||||
printf("Dest at address 103: %f\n", memory[103].f);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue