aboutsummaryrefslogtreecommitdiff
path: root/src/c8asm/parser.h
blob: a8cc03cd9933f165e03501bc7a9ce2373365ee21 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#ifndef AHOY_C8ASM_PARSER_H
#define AHOY_C8ASM_PARSER_H

#include <stddef.h>
#include <stdint.h>

#include <mbstring.h>

struct tokens;

typedef enum {
	I_ADD_I_VX,
	I_ADD_VX_B,
	I_ADD_VX_VY,
	I_AND,
	I_BCD,
	I_CALL,
	I_CLS,
	I_DB,
	I_DRW,
	I_HEX,
	I_JP_A,
	I_JP_V0_A,
	I_LD_DT,
	I_LD_I,
	I_LD_ST,
	I_LD_VX_B,
	I_LD_VX_DT,
	I_LD_VX_K,
	I_LD_VX_VY,
	I_OR,
	I_RET,
	I_RND,
	I_RSTR,
	I_SE_VX_B,
	I_SE_VX_VY,
	I_SHL,
	I_SHR,
	I_SKNP,
	I_SKP,
	I_SNE_VX_B,
	I_SNE_VX_VY,
	I_STOR,
	I_SUB,
	I_SUBN,
	I_SYS,
	I_XOR,
} instrkind;

typedef enum {
	R_V0,
	R_V1,
	R_V2,
	R_V3,
	R_V4,
	R_V5,
	R_V6,
	R_V7,
	R_V8,
	R_V9,
	R_VA,
	R_VB,
	R_VC,
	R_VD,
	R_VE,
	R_VF,
	R_I,
	R_K,
	R_DT,
	R_ST,
} reg;

typedef enum {
	D_INSTR,
	D_LABEL,
} dirkind;

/* Arguments can always be represented by a uint16_t, however the parser is not
   responsible for assigning addresses to labels.  As a result an arg at this
   stage can be either a uint16_t or the name of a label. */
struct raw_addr {
	bool label;
	union {
		uint16_t val;
		struct u8view sv;
	};
};

struct instr {
	instrkind kind;

	/* The most arguments any instruction can take is 3, so it’s more efficient
	   to just store the arguments in a fixed-size array.  The only exception is
	   the ‘db’ instruction which takes a variable-number of arguments, so in
	   that case we use a dynamic array. */
	union {
		struct raw_addr args[3];
		struct {
			uint8_t *buf;
			size_t cap;
		};
	};

	size_t len;
};

struct dir {
	dirkind kind;
	union {
		struct u8view name;
		struct instr instr;
	};
};

struct ast {
	struct dir *buf;
	size_t len, cap;
};

struct ast parsefile(struct tokens);

#endif /* !AHOY_C8ASM_PARSER_H */