OpenCores
URL https://opencores.org/ocsvn/igor/igor/trunk

Subversion Repositories igor

[/] [igor/] [trunk/] [simulator/] [instructions.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 atypic
 
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <err.h>
5
 
6
#include "regs.h"
7
#include "types.h"
8
#include "object.h"
9
#include "memory.h"
10
#include "microcode.h"
11
#include "machine.h"
12
#include "instructions.h"
13
#include "debug.h"
14
#include "bits.h"
15
#include "profiler.h"
16
 
17
typedef void (instr_f)(instr_t);
18
 
19
typedef struct {
20
        int format;
21
        instr_f *func;
22
        char *name;
23
} instr_spec_t;
24
 
25
instr_spec_t instructions[64];
26
 
27
int print_instructions = 0;
28
 
29
const char *
30
register_string(instr_reg_t r)
31
{
32
        struct di_const *c;
33
        static int regnum;
34
        int curreg;
35
        static char regs[12][128];
36
 
37
        c = debug_get1_filter(r.addr, "reg");
38
 
39
        if (c == NULL) {
40
                snprintf(regs[regnum], 128, "r%03X[%d]", r.addr, r.pointer);
41
        } else {
42
                snprintf(regs[regnum], 128, "%%%s(r%03X)[%d]", c->name, r.addr,
43
                    r.pointer);
44
        }
45
        curreg = regnum;
46
 
47
        regnum = (regnum+1)%12;
48
 
49
        return regs[curreg];
50
}
51
 
52
int
53
instr_reg(instr_reg_t r)
54
{
55
        if (r.pointer)
56
                return object_get_datum(reg_get(r.addr));
57
        return r.addr;
58
}
59
 
60
reg_t
61
instr_get_reg(instr_reg_t r)
62
{
63
        return reg_get(instr_reg(r));
64
}
65
 
66
void
67
instr_set_reg(instr_reg_t r, reg_t val)
68
{
69
        reg_set(instr_reg(r), val);
70
}
71
 
72
instr_reg_t
73
decode_instruction_reg(uint32_t r)
74
{
75
        instr_reg_t reg;
76
        reg.pointer = (r>>10) & 1;
77
        reg.addr = r & 0x3FF;
78
        return reg;
79
}
80
 
81
void
82
decode_instruction_imm(instr_t *instr)
83
{
84
        switch (instr->op) {
85
        case INS_LOAD:
86
        case INS_STORE:
87
                instr->disp = sign_extend(bitfield(instr->imm, 0, 17), 18);
88
                break;
89
        case INS_SET_FLAG:
90
        case INS_GET_FLAG:
91
                instr->fmask = bitfield(instr->imm, 0, 8);
92
                instr->fnr = bitfield(instr->imm, 9, 11);
93
                instr->fimm = bitfield(instr->imm, 12, 12);
94
                break;
95
        case INS_SET_TYPE_IMM:
96
        case INS_CMP_TYPE_IMM:
97
                instr->immval = bitfield(instr->imm, 0, 4);
98
                break;
99
        case INS_SET_DATUM_IMM:
100
        case INS_CMP_DATUM_IMM:
101
                instr->immval = sign_extend(instr->imm, 18);
102
                break;
103
        case INS_SET_GC_IMM:
104
        case INS_CMP_GC_IMM:
105
                instr->immval = bitfield(instr->imm, 0, 1);
106
                break;
107
        }
108
}
109
 
110
instr_t
111
decode_instruction(uint64_t raw_instr)
112
{
113
        instr_t instr = { };
114
 
115
        instr.op = bitfield(raw_instr, 42, 47);
116
        instr_spec_t instr_spec = instructions[instr.op];
117
 
118
        if (instr_spec.format < 0 || instr_spec.format > 3)
119
                errx(1, "Unknown instruction format: %d", instr_spec.format);
120
 
121
        if (instr_spec.format == OP_BR) {
122
                instr.r1 = decode_instruction_reg(bitfield(raw_instr, 29, 39));
123
                instr.flag_mask = bitfield(raw_instr, 21, 28);
124
                instr.flag_values = bitfield(raw_instr, 13, 20);
125
                instr.addr = sign_extend(bitfield(raw_instr, 0, 12), 13);
126
                return instr;
127
        }
128
 
129
        switch (instr_spec.format) {
130
        case OP_2R: instr.r2 = decode_instruction_reg(bitfield(raw_instr, 18, 28));
131
        case OP_1R: instr.r1 = decode_instruction_reg(bitfield(raw_instr, 29, 39));
132
        }
133
 
134
        instr.imm = bitfield(raw_instr, 0, 17);
135
        decode_instruction_imm(&instr);
136
 
137
        return instr;
138
}
139
 
140
char* instruction_type(int index)
141
{
142
        return instructions[index].name;
143
}
144
 
145
void
146
print_instruction(reg_t addr)
147
{
148
        print_instruction_to_file(stdout, addr);
149
}
150
 
151
void
152
print_instruction_to_file(FILE *f, reg_t addr)
153
{
154
        instr_t instr = decode_instruction(microcode_fetch_instr(addr));
155
        instr_spec_t instr_spec = instructions[instr.op];
156
        struct di_const *c;
157
        int i;
158
 
159
        c = debug_get1_filter(addr, "label");
160
        if (c != NULL)
161
                fprintf(f, "%s:", c->name);
162
 
163
        fprintf(f, "0x%04X ", addr);
164
 
165
        switch (instr_spec.format) {
166
        case OP_BR:
167
                //fprintf(f, "address: 0x%X\n", instr.addr);
168
                fprintf(f, FORMAT_IBR, instr_spec.name,
169
                        register_string(instr.r1),
170
                        instr.flag_mask, instr.flag_values,
171
                        instr.addr);
172
                break;
173
        case OP_2R:
174
                fprintf(f, FORMAT_I2R, instr_spec.name,
175
                        register_string(instr.r1),
176
                        register_string(instr.r2),
177
                        instr.imm);
178
                break;
179
        case OP_1R:
180
                fprintf(f, FORMAT_I1R, instr_spec.name,
181
                        register_string(instr.r1),
182
                        instr.imm);
183
                break;
184
        case OP_0R:
185
                fprintf(f, FORMAT_I0R, instr_spec.name,
186
                        instr.imm);
187
                break;
188
        default:
189
                errx(1, "Unknown instruction format: %d", instr_spec.format);
190
        }
191
 
192
        switch (instr.op) {
193
        case INS_BRANCH:
194
        case INS_BRANCH_REG:
195
                fprintf(f, " [");
196
                for (i = 0; i < 8; i++) {
197
                        if ((instr.flag_mask >> i) & 1)
198
                                fprintf(f, " %s%c", ((instr.flag_values>>i)&1) ? "" : "!",
199
                                        status_flags[i]);
200
                }
201
                fprintf(f, "]");
202
                c = debug_get1_filter(instr.addr, "label");
203
                if (c != NULL)
204
                        fprintf(f, " label: %s", c->name);
205
                fputs("\n", f);
206
                break;
207
        case INS_SET_TYPE_IMM:
208
                c = debug_get1_filter(instr.immval, "type");
209
                fprintf(f, " %s\n", c ? c->name : "unresolved");
210
                break;
211
        default:
212
                fputs("\n", f);
213
#if 0 // XXX: Pass file here as well
214
                if (instr.imm > 1)
215
                        debug_show(instr.imm);
216
#endif
217
                break;
218
        }
219
}
220
 
221
 
222
 
223
void
224
i_nop(instr_t ins)
225
{
226
        // is this implementation correct?
227
}
228
 
229
void
230
i_halt(instr_t ins)
231
{
232
        machine_shutdown();
233
}
234
 
235
void
236
i_alu(instr_t ins)
237
{
238
        reg_t v1, v2;
239
        int a, b, res;
240
 
241
        v1 = instr_get_reg(ins.r1);
242
        v2 = instr_get_reg(ins.r2);
243
 
244
        //instr_spec_t instr_spec = instructions[ins.op];
245
 
246
        if (OBJECT_TYPE(v1) != OBJECT_TYPE(v2)) {
247
                // TODO set type error flag
248
                //warnx("ALU operation on two objects of different types");
249
                /*
250
                errx(1, "(%s) Can't operate on two objects of different types",
251
                     instr_spec.name);
252
                */
253
        }
254
        if (OBJECT_TYPE(v1) != TYPE_INT) {
255
                //warnx("ALU operation on non-integer values");
256
                /*
257
                errx(1, "(%s) Can't operate on non-integer values",
258
                     instr_spec.name);
259
                */
260
        }
261
 
262
        a = object_get_datum_signed(v1);
263
        b = object_get_datum_signed(v2);
264
 
265
        //printf("alu, a=%d, b=%d\n", a, b);
266
 
267
        switch (ins.op) {
268
        case INS_ADD:
269
                res = a+b;
270
                break;
271
        case INS_SUB:
272
                res = a-b;
273
                break;
274
        case INS_MUL:
275
                res = a*b;
276
                break;
277
        case INS_DIV:
278
                res = a/b;
279
                break;
280
        case INS_MOD:
281
                res = a%b;
282
                break;
283
        case INS_AND:
284
                res = a&b;
285
                break;
286
        case INS_OR:
287
                res = a|b;
288
                break;
289
        case INS_XOR:
290
                res = a^b;
291
                break;
292
        case INS_NOT:
293
                res = ~b;
294
                break;
295
        case INS_SHIFT_L:
296
                res = a << b;
297
                break;
298
        case INS_SHIFT_R:
299
                res = a >> b;
300
                break;
301
        default:
302
                errx(1, "this is not an ALU opcode: %d", ins.op);
303
        }
304
 
305
        //printf("alu, res=%d 0x%X\n", res, res);
306
        instr_set_reg(ins.r1, object_set_datum(v1, res));
307
        set_status_flag(ST_N, res<0);
308
        set_status_flag(ST_Z, res==0);
309
        set_status_flag(ST_O, res<-(1<<25) || res>=(1<<25));
310
}
311
 
312
 
313
void
314
i_load(instr_t ins)
315
{
316
        uint32_t addr = OBJECT_DATUM(instr_get_reg(ins.r2))+ins.disp;
317
        instr_set_reg(ins.r1, memory_get(addr));
318
}
319
 
320
void
321
i_store(instr_t ins)
322
{
323
        uint32_t addr = OBJECT_DATUM(instr_get_reg(ins.r2))+ins.disp;
324
        reg_t val = instr_get_reg(ins.r1);
325
 
326
        if (print_instructions) {
327
                printf("\tStoring (at 0x%07X): ", addr);
328
                object_dump(val);
329
        }
330
        memory_set(addr, val);
331
}
332
 
333
 
334
 
335
void
336
i_branch(instr_t ins)
337
{
338
        if ((ins.flag_mask & get_all_status_flags()) == ins.flag_values)
339
                reg_set(REG_PC, ins.addr);
340
}
341
 
342
 
343
void
344
i_branch_reg(instr_t ins)
345
{
346
        uint32_t addr = object_get_datum(instr_get_reg(ins.r1)) + ins.addr;
347
        if ((ins.flag_mask & get_all_status_flags()) == ins.flag_values)
348
                reg_set(REG_PC, addr);
349
}
350
 
351
 
352
void
353
i_set_flag(instr_t ins)
354
{
355
        printf("i_set_flag: fnr=%X, fmask=%X, fimm=%X, reg=%X\n",
356
               ins.fnr, ins.fmask, ins.fimm, instr_get_reg(ins.r1));
357
        set_status_flag(ins.fnr,
358
                        get_flags(ins.fmask)
359
                        || ins.fimm
360
                        || object_get_datum(instr_get_reg(ins.r1)));
361
}
362
 
363
void
364
i_clear_flag(instr_t ins)
365
{
366
        set_status_flag(ins.fnr, 0);
367
}
368
 
369
void
370
i_get_flag(instr_t ins)
371
{
372
        instr_set_reg(ins.r1, get_flags(ins.fmask));
373
}
374
 
375
 
376
void
377
i_get_type(instr_t ins)
378
{
379
        int type = OBJECT_TYPE(instr_get_reg(ins.r2));
380
        reg_t val = instr_get_reg(ins.r1);
381
        val = object_set_datum(val, type);
382
        val = object_set_type(val, TYPE_INT);
383
        instr_set_reg(ins.r1, val);
384
}
385
 
386
void
387
i_set_type(instr_t ins)
388
{
389
        //printf("SET-TYPE r%x <- %x\n", ins.r1, ins.imm);
390
        reg_t val = instr_get_reg(ins.r1);
391
        if (ins.op == INS_SET_TYPE_IMM) {
392
                val = object_set_type(val, ins.immval);
393
        } else {
394
                val = object_set_type(val, object_get_datum(instr_get_reg(ins.r2)));
395
        }
396
        instr_set_reg(ins.r1, val);
397
}
398
 
399
void
400
i_get_datum(instr_t ins)
401
{
402
        reg_t val1, val2;
403
 
404
        val1 = instr_get_reg(ins.r1);
405
        val2 = instr_get_reg(ins.r2);
406
        val1 = object_set_datum(val1, object_get_datum(val2));
407
        instr_set_reg(ins.r1, val1);
408
}
409
 
410
void
411
i_set_datum(instr_t ins)
412
{
413
        //printf("SET-DATUM r%x <- %x\n", ins.r1, ins.imm);
414
 
415
        reg_t val = instr_get_reg(ins.r1);
416
        instr_set_reg(ins.r1, object_set_datum(val, ins.immval));
417
}
418
 
419
void
420
i_get_gc(instr_t ins)
421
{
422
        reg_t val1, val2;
423
        val1 = instr_get_reg(ins.r1);
424
        val2 = instr_get_reg(ins.r2);
425
        val1 = object_set_datum(val1, object_get_gc(val2));
426
        instr_set_reg(ins.r1, val1);
427
}
428
 
429
void
430
i_set_gc(instr_t ins)
431
{
432
        reg_t val = instr_get_reg(ins.r1);
433
        if (ins.op == INS_SET_GC_IMM) {
434
                val = object_set_gc(val, ins.immval);
435
        } else {
436
                val = object_set_gc(val, object_get_datum(instr_get_reg(ins.r2)));
437
        }
438
        instr_set_reg(ins.r1, val);
439
}
440
 
441
void
442
i_cpy(instr_t ins)
443
{
444
        instr_set_reg(ins.r1, instr_get_reg(ins.r2));
445
}
446
 
447
 
448
void
449
i_cmp(instr_t ins)
450
{
451
        int diff = 0;
452
        switch (ins.op) {
453
        case INS_CMP_TYPE:
454
                diff = object_get_type(instr_get_reg(ins.r1))
455
                        - object_get_type(instr_get_reg(ins.r2));
456
                break;
457
        case INS_CMP_TYPE_IMM:
458
                diff = object_get_type(instr_get_reg(ins.r1))
459
                        - ins.immval;
460
                break;
461
        case INS_CMP_DATUM:
462
                diff = object_get_datum_signed(instr_get_reg(ins.r1))
463
                        - object_get_datum_signed(instr_get_reg(ins.r2));
464
                break;
465
        case INS_CMP_DATUM_IMM:
466
                diff = object_get_datum_signed(instr_get_reg(ins.r1))
467
                        - ins.immval;
468
                break;
469
        case INS_CMP_GC:
470
                diff = object_get_gc(instr_get_reg(ins.r1))
471
                        - object_get_gc(instr_get_reg(ins.r2));
472
                break;
473
        case INS_CMP_GC_IMM:
474
                diff = object_get_gc(instr_get_reg(ins.r1))
475
                        - ins.immval;
476
                break;
477
        case INS_CMP:
478
                // TODO fix
479
                if (object_get_type(instr_get_reg(ins.r1)) !=
480
                    object_get_type(instr_get_reg(ins.r2))) {
481
                        //errx(1, "(CMP) Cannot compare two objects of different types");
482
                        set_status_flag(ST_T, 1);
483
                        return;
484
                }
485
                //if (object_get_type(instr_get_reg(ins.r1)) == TYPE_INT) {
486
                diff = object_get_datum_signed(instr_get_reg(ins.r1))
487
                        - object_get_datum_signed(instr_get_reg(ins.r2));
488
                break;
489
        default:
490
                errx(1, "(i_cmp) Unknown comparison instruction %d",
491
                     ins.op);
492
        }
493
 
494
        //printf("compare, diff=%d\n", diff);
495
 
496
        set_status_flag(ST_T, 0);
497
        set_status_flag(ST_Z, diff==0);
498
        set_status_flag(ST_N, diff<0);
499
}
500
 
501
 
502
/*
503
void
504
i_check_type(instr_t ins)
505
{
506
        int reg = ins.r2;
507
        int type = ins.imm;
508
 
509
        set_status_flag(ST_B, OBJECT_TYPE(reg_get(reg)) == type);
510
}
511
*/
512
 
513
/*
514
void
515
i_push(instr_t ins)
516
{
517
        reg_set(REG_SP, reg_get(REG_SP)-1);
518
        memory_set(reg_get(REG_SP), reg_get(ins.r1));
519
}
520
 
521
void
522
i_pull(instr_t ins)
523
{
524
        reg_set(ins.r1, memory_get(reg_get(REG_SP)));
525
        reg_set(REG_SP, reg_get(REG_SP)+1);
526
}
527
*/
528
 
529
void
530
instructions_init(void)
531
{
532
        REG_INSTR(NOP, OP_2R, i_nop);
533
        REG_INSTR(HALT, OP_2R, i_halt);
534
 
535
        REG_INSTR(ADD, OP_2R, i_alu);
536
        REG_INSTR(SUB, OP_2R, i_alu);
537
        REG_INSTR(MUL, OP_2R, i_alu);
538
        REG_INSTR(DIV, OP_2R, i_alu);
539
        REG_INSTR(AND, OP_2R, i_alu);
540
        REG_INSTR(OR,  OP_2R, i_alu);
541
        REG_INSTR(XOR, OP_2R, i_alu);
542
        REG_INSTR(NOT, OP_2R, i_alu);
543
        REG_INSTR(SHIFT_L, OP_2R, i_alu);
544
        REG_INSTR(MOD, OP_2R, i_alu);
545
        REG_INSTR(SHIFT_R, OP_2R, i_alu);
546
 
547
        REG_INSTR(LOAD, OP_2R, i_load);
548
        REG_INSTR(STORE, OP_2R, i_store);
549
 
550
        REG_INSTR(BRANCH, OP_BR, i_branch);
551
        REG_INSTR(BRANCH_REG, OP_BR, i_branch_reg);
552
 
553
        REG_INSTR(GET_FLAG, OP_1R, i_get_flag);
554
        REG_INSTR(CLEAR_FLAG, OP_0R, i_clear_flag);
555
        REG_INSTR(SET_FLAG, OP_1R, i_set_flag);
556
 
557
        REG_INSTR(GET_TYPE, OP_2R, i_get_type);
558
        REG_INSTR(SET_TYPE, OP_2R, i_set_type);
559
        REG_INSTR(SET_TYPE_IMM, OP_1R, i_set_type);
560
        REG_INSTR(GET_DATUM, OP_2R, i_get_datum);
561
        REG_INSTR(SET_DATUM_IMM, OP_1R, i_set_datum);
562
        REG_INSTR(GET_GC, OP_2R, i_get_gc);
563
        REG_INSTR(SET_GC, OP_2R, i_set_gc);
564
        REG_INSTR(SET_GC_IMM, OP_1R, i_set_gc);
565
        REG_INSTR(CPY, OP_2R, i_cpy);
566
 
567
        REG_INSTR(CMP_TYPE, OP_2R, i_cmp);
568
        REG_INSTR(CMP_TYPE_IMM, OP_1R, i_cmp);
569
        REG_INSTR(CMP_DATUM, OP_2R, i_cmp);
570
        REG_INSTR(CMP_DATUM_IMM, OP_1R, i_cmp);
571
        REG_INSTR(CMP_GC, OP_2R, i_cmp);
572
        REG_INSTR(CMP_GC_IMM, OP_1R, i_cmp);
573
        REG_INSTR(CMP, OP_2R, i_cmp);
574
}
575
 
576
 
577
void
578
execute_instruction(instr_t ins)
579
{
580
        //printf("Looking for opcode: %d\n", ins.op);
581
        instructions[ins.op].func(ins);
582
}
583
 
584
void
585
set_instruction_printing(int s)
586
{
587
        print_instructions = s;
588
}
589
 
590
void
591
do_instruction(reg_t addr)
592
{
593
        instr_t instr;
594
        if (print_instructions)
595
                print_instruction(addr);
596
        instr = decode_instruction(microcode_fetch_instr(addr));
597
        execute_instruction(instr);
598
        profiler_add_execution(addr, instr, get_all_status_flags());
599
}
600
 
601
void
602
do_next_instruction(void)
603
{
604
        reg_t pc;
605
 
606
        if (!machine_up())
607
                errx(1, "(do_next_instruction) cannot do that: machine down\n");
608
 
609
        pc = reg_get(REG_PC);
610
        reg_set(REG_PC, pc+1);
611
        do_instruction(pc);
612
}
613
 
614
reg_t
615
next_instr_addr(void)
616
{
617
        return reg_get(REG_PC);
618
}
619
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.