summaryrefslogtreecommitdiff
path: root/libinterp/decgen.c
blob: f81749c7420325690f72a3cfb5d60a25b9e600bd (plain)
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
#include "lib9.h"
#include "isa.h"
#include "interp.h"

void	decgen(int);

/*
 * Force intermediate dereference of $o(o(reg)) modes to ensure intermediate
 * pointer is valid. This is required if you want secure memory.
 */
#define	SOFTMMU		0

void
main(void)
{
	int i;

	print("/* Machine generated by decgen.c */\n\n");

	print("#include \"lib9.h\"\n");
	print("#include \"isa.h\"\n");
	print("#include \"interp.h\"\n\n");

	print("#define DIND(reg, xxx) (uchar*)((*(ulong*)(R.reg+R.PC->xxx.i.f))+R.PC->xxx.i.s)\n");

	for(i = 0; i < 256; i++)
		decgen(i);

	print("\nvoid	(*dec[])(void) =\n{\n");
	for(i = 0; i < 256; i++)
		print("\tD%.2uX%c\n", i, i != 255 ? ',' : ' ');
	print("};\n");
}

void
decgen(int addr)
{
	int nodst;

	print("static void\nD%.2uX(void)\n{\n", addr);

	switch(USRC(addr)) {
	case AMP:
		print("\tR.s = R.MP+R.PC->s.ind;\n");
		break;
	case AFP:
		print("\tR.s = R.FP+R.PC->s.ind;\n");
		break;
	case AIMM:
		print("\tR.s = (uchar*)&R.PC->s.imm;\n");
		break;
	case AMP|AIND:
		if(SOFTMMU) {
			print("R.s = R.MP+R.PC->s.i.f\n");
			print("R.s = *(WORD**)R.s\n");
			print("R.s = (uchar*)R.s + R.PC->s.i.s\n");
		}
		else
			print("\tR.s = DIND(MP, s);\n");
		break;
	case AFP|AIND:
		if(SOFTMMU) {
			print("R.s = R.FP+R.PC->s.i.f\n");
			print("R.s = *(WORD**)R.s\n");
			print("R.s = (uchar*)R.s + R.PC->s.i.s\n");
		}
		else
			print("\tR.s = DIND(FP, s);\n");
		break;
	}
	nodst = 0;
	switch(UDST(addr)) {
	default:
		nodst = 1;
		break;
	case AMP:
		print("\tR.d = R.MP+R.PC->d.ind;\n");
		break;
	case AFP:
		print("\tR.d = R.FP+R.PC->d.ind;\n");
		break;
	case AIMM:
		print("\tR.d = (uchar*)&R.PC->d.imm;\n");
		break;
	case AMP|AIND:
		if(SOFTMMU) {
			print("R.d = R.MP+R.PC->d.i.f\n");
			print("R.d = *(WORD**)R.d\n");
			print("R.d = (uchar*)R.d + R.PC->d.i.s\n");
		}
		else
			print("\tR.d = DIND(MP, d);\n");
		break;
	case AFP|AIND:
		if(SOFTMMU) {
			print("R.d = R.FP+R.PC->d.i.f\n");
			print("R.d = *(WORD**)R.d\n");
			print("R.d = (uchar*)R.d + R.PC->d.i.s\n");
		}
		else
			print("\tR.d = DIND(FP, d);\n");
		break;
	}

	if(nodst == 0)
	switch(addr&ARM) {
	case AXNON:
		print("\tR.m = R.d;\n");
		break;
	case AXIMM:
		print("\tR.t = (short)R.PC->reg;\n");
		print("\tR.m = &R.t;\n");
		break;
	case AXINF:
		print("\tR.m = R.FP+R.PC->reg;\n");
		break;
	case AXINM:
		print("\tR.m = R.MP+R.PC->reg;\n");
		break;
	}
	print("}\n");
}