undar-lang/src/vm.h

87 lines
3.8 KiB
C

/*
* ZRE - A lightweight, portable programming language for permacomputing.
* Copyright (C) 2025 zongor
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef ZRE_VM_H
#define ZRE_VM_H
#include "common.h"
/* Constants for Q16.16 */
#define Q16_16_SCALE (1 << 16)
#define Q16_16_SCALE_FLOAT 65536.0f
#define Q16_16_FRACTION_MASK 0x0000FFFF
#define Q16_16_INT_MASK 0xFFFF0000
/* Convert float to Q16.16 (with rounding) */
#define FLOAT_TO_Q16_16(f) ((int32_t)((f) * Q16_16_SCALE_FLOAT + 0.5f))
/* Convert Q16.16 to float */
#define Q16_16_TO_FLOAT(q) ((float)(q) / Q16_16_SCALE_FLOAT)
typedef union {
int32_t i; /* Integers */
int32_t q; /* Q16.16 (32-bit fixed-point) */
uint32_t u; /* Unsigned integers */
char c[4]; /* 4 Byte char array for string packing */
} Word;
typedef enum {
OP_HALT, /* terminate execution */
OP_ADD_INT, /* dest = src1 + src2 */
OP_SUB_INT, /* dest = src1 - src2 */
OP_MUL_INT, /* dest = src1 * src2 */
OP_DIV_INT, /* dest = src1 / src2 */
OP_JEQ_INT, /* jump to address dest if src1 as int == src2 as int */
OP_JGT_INT, /* jump to address dest if src1 as int > src2 as int*/
OP_JLT_INT, /* jump to address dest if src1 as int < src2 as int */
OP_JLE_INT, /* jump to address dest if src1 as int <= src2 as int */
OP_JGE_INT, /* jump to address dest if src1 as int >= src2 as int*/
OP_INT_TO_REAL, /* dest = src1 as f32 */
OP_ADD_UINT, /* dest = src1 + src2 */
OP_SUB_UINT, /* dest = src1 - src2 */
OP_MUL_UINT, /* dest = src1 * src2 */
OP_DIV_UINT, /* dest = src1 / src2 */
OP_JEQ_UINT, /* jump to address dest if src1 as int == src2 as uint */
OP_JGT_UINT, /* jump to address dest if src1 as int > src2 as uint*/
OP_JLT_UINT, /* jump to address dest if src1 as int < src2 as uint */
OP_JLE_UINT, /* jump to address dest if src1 as int <= src2 as uint */
OP_JGE_UINT, /* jump to address dest if src1 as int >= src2 as uint*/
OP_UINT_TO_REAL, /* dest = src1 as f32 */
OP_ADD_REAL, /* dest = src1 + src2 */
OP_SUB_REAL, /* dest = src1 - src2 */
OP_MUL_REAL, /* dest = src1 * src2 */
OP_DIV_REAL, /* dest = src1 / src2 */
OP_JEQ_REAL, /* jump to address dest if src1 as real == src2 as real */
OP_JGE_REAL, /* jump to address dest if src1 as real >= src2 as real */
OP_JGT_REAL, /* jump to address dest if src1 as real > src2 as real */
OP_JLT_REAL, /* jump to address dest if src1 as real < src2 as real */
OP_JLE_REAL, /* jump to address dest if src1 as real <= src2 as real */
OP_REAL_TO_INT, /* dest = src1 as int */
OP_REAL_TO_UINT, /* dest = src1 as int */
OP_MOV, /* dest = src1 */
OP_JMP, /* jump to address src1 unconditionally */
OP_INT_TO_STRING, /* dest = src1 as str */
OP_UINT_TO_STRING, /* dest = src1 as str */
OP_REAL_TO_STRING, /* dest = src1 as str */
OP_READ_STRING, /* dest = read as str */
OP_PRINT_STRING, /* write src1 to stdout */
OP_CMP_STRING, /* dest = src1 as str == src2 as str */
} Opcode;
uint32_t step_vm(Word *memory, uint32_t memory_size, uint32_t pc);
#endif