include: deprecate syscalls leftovers
[cavatools.git] / caveat / insn.c
1 /*
2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
3 */
4
5 #include <unistd.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <string.h>
10 #include <sys/mman.h>
11 #include <time.h>
12 #include <stdint.h>
13
14 #include "caveat.h"
15 #include "opcodes.h"
16 #include "insn.h"
17
18
19 struct insnAttr_t insnAttr[] = {
20 #include "opcodes_attr.h"
21 };
22
23 struct insnSpace_t insnSpace;
24
25 const char* regName[] = {
26 "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
27 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
28 "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
29 "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
30 "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
31 "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
32 "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
33 "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
34 "NOT"
35 };
36
37
38 void insnSpace_init()
39 {
40 dieif(insnSpace.base==0, "insnSpace_init() base, bound not initialized");
41 assert(insnSpace.base < insnSpace.bound);
42
43 long nelts = (insnSpace.bound - insnSpace.base) / 2;
44 insnSpace.insn_array = (struct insn_t*)mmap(0, nelts*sizeof(struct insn_t), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
45 assert(insnSpace.insn_array);
46 memset(insnSpace.insn_array, 0, nelts*sizeof(struct insn_t));
47 for (Addr_t pc=insnSpace.base; pc<insnSpace.bound; pc+=2)
48 decode_instruction(&insnSpace.insn_array[(pc-insnSpace.base)/2], pc);
49 }
50
51
52 static inline struct insn_t fmtC(enum Opcode_t op, signed char rd, signed char rs1, int constant)
53 {
54 struct insn_t i;
55 i.op_code = op;
56 i.op_rd = rd;
57 i.op_rs1 = rs1;
58 i.op_constant = constant;
59 return i;
60 }
61
62 static inline struct insn_t fmtR(enum Opcode_t op, signed char rd, signed char rs1, signed char rs2, signed char rs3, short immed)
63 {
64 struct insn_t i;
65 i.op_code = op;
66 i.op_rd = rd;
67 i.op_rs1 = rs1;
68 i.op.rs2 = rs2;
69 i.op.rs3 = rs3;
70 i.op.immed = immed;
71 return i;
72 }
73
74 void decode_instruction( const struct insn_t* cp, Addr_t PC )
75 {
76 struct insn_t* p = (struct insn_t*)cp;
77 int ir = *((int*)(PC));
78 #include "decode_insn.h"
79 p->op_code = Op_illegal; // no match
80 return;
81 }
82
83
84 int format_pc(char* buf, int width, Addr_t pc)
85 {
86 if (valid_pc(pc)) {
87 const char* func;
88 long offset;
89 if (find_pc(pc, &func, &offset)) {
90 snprintf(buf, width, "%21s", func);
91 snprintf(buf+21, width, "+%-5ld ", offset);
92 }
93 else
94 snprintf(buf, width, "%21s %5s ", "UNKNOWN", "");
95 }
96 else
97 snprintf(buf, width, "%21s %-5s ", "INVALID", "");
98 return strlen(buf);
99 }
100
101 void print_pc( long pc, FILE* f)
102 {
103 char buf[1024];
104 format_pc(buf, 29, pc);
105 fprintf(f, "%-28s", buf);
106 }
107
108
109
110 int format_insn(char* buf, const struct insn_t* p, Addr_t pc, unsigned int image)
111 {
112 int n;
113 if (shortOp(p->op_code))
114 n = sprintf(buf, "%8lx %04x %-16s", pc, image&0xffff, insnAttr[p->op_code].name);
115 else
116 n = sprintf(buf, "%8lx %08x %-16s", pc, image, insnAttr[p->op_code].name);
117 buf += n;
118 switch (p->op_code) {
119 #include "disasm_insn.h"
120 }
121 return n;
122 }
123
124 void print_insn(Addr_t pc, FILE* f)
125 {
126 char buf[1024];
127 format_insn(buf, insn(pc), pc, *((unsigned int*)pc));
128 fprintf(f, "%s\n", buf);
129 }
130
131
132
133 void print_registers(struct reg_t reg[], FILE* f)
134 {
135 char buf[1024];
136 for (int i=0; i<64; i++) {
137 fprintf(f, "%-4s: 0x%016lx ", regName[i], reg[i].ul);
138 if ((i+1) % 4 == 0)
139 fprintf(f, "\n");
140 }
141 }
142
143
144 static struct options_t* opt_ptr;
145 static const char* usage_ptr;
146
147 void help_exit()
148 {
149 fprintf(stderr, "Usage : %s\n", usage);
150 for (int i=0; opt[i].name; ++i) {
151 int len = strlen(opt[i].name);
152 fprintf(stderr, " %-14s %s ", opt[i].name, opt[i].h);
153 if (opt[i].name[len-2] == '=')
154 switch (opt[i].name[len-1]) {
155 case 's':
156 if (opt[i].ds)
157 fprintf(stderr, "[%s]\n", opt[i].ds);
158 else
159 fprintf(stderr, "[none]\n");
160 break;
161 case 'i':
162 fprintf(stderr, "[%ld]\n", opt[i].di);
163 break;
164 default:
165 fprintf(stderr, "Bad option %s\n", opt[i].name);
166 exit(0);
167 }
168 else
169 fprintf(stderr, "\n");
170 }
171 exit(0);
172 }
173
174
175 int parse_options(const char** argv)
176 {
177 /* initialize default values */
178 for (int i=0; opt[i].name; ++i) {
179 int len = strlen(opt[i].name) - 1;
180 if (opt[i].name[len-1] == '=')
181 switch (opt[i].name[len]) {
182 case 's': *opt[i].s = opt[i].ds; break;
183 case 'i': *opt[i].i = opt[i].di; break;
184 default: fprintf(stderr, "Bad option %s\n", opt[i].name); exit(0);
185 }
186 else
187 *opt[i].b = 0; /* flag not given */
188 }
189 /* parse options */
190 int numargs = 0;
191 while (argv[numargs] && argv[numargs][0]=='-') {
192 const char* arg = argv[numargs++];
193 if (strcmp(arg, "--help") == 0)
194 help_exit();
195 for (int i=0; opt[i].name; ++i) {
196 int len = strlen(opt[i].name) - 1;
197 if (opt[i].name[len-1] == '=') {
198 if (strncmp(opt[i].name, arg, len-1) == 0) {
199 switch (opt[i].name[len]) {
200 case 's': *opt[i].s = (arg+len); break;
201 case 'i': *opt[i].i = atoi(arg+len); break;
202 }
203 goto next_option;
204 }
205 }
206 else if (strcmp(arg, opt[i].name) == 0) {
207 *opt[i].b = opt[i].bv;
208 goto next_option;
209 }
210 }
211 fprintf(stderr, "Illegal option %s\n", arg);
212 exit(1);
213 next_option:
214 ;
215 }
216 return numargs;
217 }