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

Subversion Repositories light52

[/] [light52/] [trunk/] [tools/] [b51/] [src/] [b51_cpu.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 ja_rd
 
2
#include <stdint.h>
3
#include <stdbool.h>
4
#include <stdio.h>
5
 
6
#include "b51_cpu.h"
7
#include "b51_mcu.h"
8
#include "b51_log.h"
9
#include "util/ihex.h"
10
 
11
 
12
/*-- Local data types & macros -----------------------------------------------*/
13
 
14
typedef enum cpu_op_e {
15
    add, addc, subb,
16
    alu_mul, alu_div,
17
    da,
18
    rrc, rlc, rr, rl,
19
    setb_c, clr_c, anl_c, orl_c,
20
    cjne
21
} cpu_op_t;
22
 
23
/** Cycle count information for an opcode. */
24
typedef struct {
25
    int min;    /**< Minimum number of cycles. */
26
    int max;    /**< Maximum number of cycles. */
27
} cycle_count_t;
28
 
29
/** Cycle count table for light52 core. */
30
cycle_count_t cycle_count[256] = {
31
    { 2, 2}, { 5, 5}, { 6, 6}, { 3, 3}, { 3, 3}, { 5, 5}, { 7, 7}, { 7, 7},
32
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
33
    { 7, 8}, { 7, 7}, { 8, 8}, { 3, 3}, { 3, 3}, { 5, 5}, { 7, 7}, { 7, 7},
34
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
35
    { 6, 7}, { 5, 5}, { 7, 7}, { 3, 3}, { 4, 4}, { 5, 5}, { 7, 7}, { 7, 7},
36
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
37
    { 6, 7}, { 7, 7}, { 7, 7}, { 3, 3}, { 4, 4}, { 5, 5}, { 7, 7}, { 7, 7},
38
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
39
    { 3, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 4, 4}, { 5, 5}, { 7, 7}, { 7, 7},
40
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
41
    { 3, 5}, { 7, 7}, { 5, 5}, { 5, 5}, { 4, 4}, { 5, 5}, { 7, 7}, { 7, 7},
42
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
43
    { 3, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 4, 4}, { 5, 5}, { 7, 7}, { 7, 7},
44
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
45
    { 3, 5}, { 7, 7}, { 5, 5}, { 4, 4}, { 4, 4}, { 5, 5}, { 5, 5}, { 5, 5},
46
    { 4, 4}, { 4, 4}, { 4, 4}, { 4, 4}, { 4, 4}, { 4, 4}, { 4, 4}, { 4, 4},
47
    { 5, 5}, { 5, 5}, { 5, 5}, { 4, 4}, {10,10}, { 5, 5}, { 7, 7}, { 7, 7},
48
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
49
    { 5, 5}, { 7, 7}, { 5, 5}, { 4, 4}, { 4, 4}, { 5, 5}, { 7, 7}, { 7, 7},
50
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
51
    { 5, 5}, { 5, 5}, { 5, 5}, { 3, 3}, { 3, 3}, { 2, 2}, { 6, 6}, { 6, 6},
52
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
53
    { 5, 5}, { 7, 7}, { 5, 5}, { 3, 3}, { 5, 6}, { 6, 7}, { 8, 9}, { 8, 9},
54
    { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7},
55
    { 5, 5}, { 5, 5}, { 5, 5}, { 3, 3}, { 3, 3}, { 6, 6}, { 7, 7}, { 7, 7},
56
    { 6, 6}, { 6, 6}, { 6, 6}, { 6, 6}, { 6, 6}, { 6, 6}, { 6, 6}, { 6, 6},
57
    { 5, 5}, { 7, 7}, { 5, 5}, { 3, 3}, { 2, 2}, { 7, 8}, { 2, 2}, { 2, 2},
58
    { 7, 8}, { 7, 8}, { 7, 8}, { 7, 8}, { 7, 8}, { 7, 8}, { 7, 8}, { 7, 8},
59
    { 3, 3}, { 5, 5}, { 6, 6}, { 6, 6}, { 3, 3}, { 5, 5}, { 7, 7}, { 7, 7},
60
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
61
    { 3, 3}, { 7, 7}, { 5, 5}, { 5, 5}, { 3, 3}, { 4, 4}, { 5, 5}, { 5, 5},
62
    { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5}, { 5, 5},
63
    };
64
 
65
 
66
 
67
 
68
/*-- Local function prototypes -----------------------------------------------*/
69
 
70
 
71
static uint8_t cpu_fetch(cpu51_t *cpu);
72
static uint16_t cpu_fetch16(cpu51_t *cpu);
73
static uint16_t cpu_fetch11(cpu51_t *cpu, uint8_t opcode);
74
static uint8_t cpu_xcode_read(cpu51_t *cpu, uint16_t addr);
75
static uint8_t cpu_xdata_read(cpu51_t *cpu, uint16_t addr);
76
static void cpu_xdata_write(cpu51_t *cpu, uint16_t addr, uint8_t value);
77
static void cpu_set_rn(cpu51_t *cpu, uint8_t n, uint8_t value);
78
static void cpu_set_a(cpu51_t *cpu, uint8_t value);
79
static uint8_t cpu_update_flags(cpu51_t *cpu, uint8_t x, uint8_t y, cpu_op_t op);
80
static uint8_t cpu_compute_ac(cpu51_t *cpu, uint8_t x, uint8_t y, cpu_op_t op);
81
static void cpu_set_dir(cpu51_t *cpu, uint8_t dir, uint8_t value);
82
static void cpu_set_idata(cpu51_t *cpu, uint8_t dir, uint8_t value);
83
static uint8_t cpu_get_dir(cpu51_t *cpu, uint8_t dir);
84
static uint8_t cpu_get_idata(cpu51_t *cpu, uint8_t dir);
85
static bool cpu_rel_jump(cpu51_t *cpu, uint8_t rel);
86
static void cpu_set_sfr(cpu51_t *cpu, uint8_t dir, uint8_t value);
87
static uint8_t cpu_get_sfr(cpu51_t *cpu, uint8_t dir);
88
static uint8_t cpu_get_bit_address(cpu51_t *cpu, uint8_t bit);
89
static uint8_t cpu_get_bit(cpu51_t *cpu, uint8_t bit);
90
static void cpu_set_bit(cpu51_t *cpu, uint8_t bit, uint8_t value);
91
 
92
static bool cpu_exec_rn(cpu51_t *cpu, uint8_t opcode);
93
static bool cpu_exec_upper_half(cpu51_t *cpu, uint8_t opcode);
94
 
95
 
96
/*-- Public functions --------------------------------------------------------*/
97
 
98
extern uint16_t cpu_load_code(cpu51_t *cpu, const char *hex_filename){
99
    FILE *fp;
100
    IHexRecord irec;
101
    uint16_t i, target, bytes_read=0;
102
 
103
    fp = fopen(hex_filename, "r");
104
    if (fp == NULL) {
105
        perror("Error opening file");
106
        return 0;
107
    }
108
 
109
    while (Read_IHexRecord(&irec, fp) == IHEX_OK) {
110
        /* Debug: print read record */
111
        #if 0
112
        Print_IHexRecord(&irec);
113
        printf("\n");
114
        #endif
115
        /* Move data from record to XCODE space, no questions asked */
116
        /* FIXME XCODE size hardcoded here */
117
        target = irec.address;
118
        for(i=0; i < irec.dataLen && (target+i)<65536; i++){
119
            cpu->mcu.xcode[target + i] = irec.data[i];
120
        }
121
        bytes_read += irec.dataLen;
122
    }
123
 
124
    fclose(fp);
125
 
126
    if(bytes_read > 0){
127
        printf("Read %d code bytes from '%s'\n", bytes_read, hex_filename);
128
    }
129
 
130
    return bytes_read;
131
}
132
 
133
extern void cpu_init(cpu51_t *cpu){
134
    /* Not much to init in the CPU so far */
135
    cpu->breakpoint = 0xffff; /* FIXME implementation of BP is flimsy */
136
    cpu->log.executed_instructions = 0;
137
    /* Set the core implementation options to their default value */
138
    cpu->options.bcd = false;
139
    /* now init the MCU model -- peripherals */
140
    mcu_init(&cpu->mcu);
141
}
142
 
143
extern void cpu_reset(cpu51_t *cpu){
144
    /* Give CPU registers their reset value, if any */
145
    cpu->sfr.dph = 0x00;
146
    cpu->sfr.dpl = 0x00;
147
    cpu->sfr.sp = 0x07;
148
    cpu->sfr.psw = 0x00;
149
    cpu->pc = 0x0000;
150
    cpu->cycles = 0;
151
    /* FIXME reset interrupt level */
152
    /* Now reset the MCU model -- peripherals */
153
    mcu_reset(&cpu->mcu);
154
}
155
 
156
extern bool cpu_add_breakpoint(cpu51_t *cpu, uint16_t address){
157
    cpu->breakpoint = address;
158
    return true;
159
}
160
 
161
extern uint32_t cpu_exec(cpu51_t *cpu, uint32_t num_inst){
162
    uint8_t opcode;
163
    uint32_t i;
164
    bool ok;
165
    uint32_t cycles;
166
 
167
    for(i=0;i<num_inst;i++){
168
        log_baseline(&(cpu->log), cpu->pc, cpu->sfr.sp, cpu->a, cpu->sfr.psw);
169
 
170
        if(cpu->pc == cpu->breakpoint){
171
            printf("BREAKPOINT hit at %04Xh\n", cpu->breakpoint);
172
            return 2;
173
        }
174
 
175
        opcode = cpu_fetch(cpu);
176
        cpu->max_cycle_count = false;
177
        cpu->implemented_as_nop = false;
178
 
179
        if((opcode & 0x08)!=0){
180
            /* bottom half of decoding table */
181
            ok = cpu_exec_rn(cpu, opcode);
182
        }
183
        else{
184
            /* top half of decoding table */
185
            ok = cpu_exec_upper_half(cpu, opcode);
186
        }
187
 
188
        /* Update cycle counter... */
189
        if(cpu->implemented_as_nop){
190
            /* Instruction is not implemented as per command line parameters;
191
               it was executed as NOP so its cycle count is that of NOP.*/
192
            cycles = cycle_count[0].min;
193
        }
194
        else{
195
            if(cpu->max_cycle_count){
196
                cycles = cycle_count[opcode].max;
197
            }
198
            else{
199
                cycles = cycle_count[opcode].min;
200
            }
201
        }
202
        cpu->cycles += cycles;
203
 
204
        mcu_update(&cpu->mcu, cycles);
205
        log_status(&(cpu->log), cpu->sfr.sp, cpu->a, cpu->sfr.psw);
206
 
207
        cpu->log.executed_instructions++;
208
 
209
        /* Break execution on any kind of trouble */
210
        /* FIXME handle execution faults */
211
        if(!ok) {
212
            return 1;
213
            break;
214
        }
215
    }
216
 
217
    return 0;
218
}
219
 
220
/*-- Local functions ---------------------------------------------------------*/
221
 
222
/**
223
    Get the byte pointed to by PC, increment PC.
224
 
225
    This function and cpu_xcode_read encapsulate code space addressing.
226
 
227
    @arg CPU object.
228
    @return Opcode at PC.
229
    @sideeffect CPU state updated accordingly.
230
*/
231
static uint8_t cpu_fetch(cpu51_t *cpu){
232
    return cpu_xcode_read(cpu, cpu->pc++);
233
}
234
 
235
static uint16_t cpu_fetch16(cpu51_t *cpu){
236
    uint8_t hi, lo;
237
    uint16_t word;
238
 
239
    hi = cpu_fetch(cpu);
240
    lo = cpu_fetch(cpu);
241
    word = ((uint16_t)hi << 8) + (uint16_t)lo;
242
    return word;
243
}
244
 
245
static uint16_t cpu_fetch11(cpu51_t *cpu, uint8_t opcode){
246
    uint8_t hi, lo, tmp;
247
    uint16_t word;
248
 
249
    lo = cpu_fetch(cpu);
250
    hi = (opcode >> 5) & 0x07;
251
    tmp = (cpu->pc >> 8) & 0xf8;
252
    hi |= tmp;
253
    word = ((uint16_t)hi << 8) + (uint16_t)lo;
254
    return word;
255
}
256
 
257
 
258
static uint8_t cpu_xcode_read(cpu51_t *cpu, uint16_t addr){
259
    return cpu->mcu.xcode[addr];
260
}
261
 
262
 
263
static uint8_t cpu_xdata_read(cpu51_t *cpu, uint16_t addr){
264
    return cpu->mcu.xdata[addr];
265
}
266
 
267
static void cpu_xdata_write(cpu51_t *cpu, uint16_t addr, uint8_t value){
268
    /*if(cpu->mcu.xdata[addr]!=value){*/
269
        log_xdata(&(cpu->log), addr, value);
270
    /*}*/
271
    cpu->mcu.xdata[addr] = value;
272
}
273
 
274
 
275
static uint8_t cpu_get_rn(cpu51_t *cpu, uint8_t n){
276
    uint8_t idata_address;
277
 
278
    idata_address = (cpu->sfr.psw & 0x18) + (n & 0x07);
279
    return cpu->idata[idata_address];
280
}
281
 
282
static void cpu_set_rn(cpu51_t *cpu, uint8_t n, uint8_t value){
283
    uint8_t idata_address;
284
 
285
    idata_address = (cpu->sfr.psw & 0x18) + (n & 0x07);
286
    cpu_set_idata(cpu, idata_address, value);
287
}
288
 
289
static void cpu_set_a(cpu51_t *cpu, uint8_t value){
290
    uint8_t p, t, i;
291
 
292
    cpu->a = value;
293
 
294
    /* Update P flag */
295
    t = cpu->a;
296
    p = 0;
297
    for(i=0;i<8;i++){
298
        p = p ^ (t & 0x01);
299
        t = t >> 1;
300
    }
301
    cpu->sfr.psw &= 0x0fe;
302
    cpu->sfr.psw |= (p & 0x01);
303
}
304
 
305
 
306
static uint8_t set_bit(uint8_t target, uint8_t index, uint8_t value){
307
    index &= 0x07;
308
    target &= ~(1 << index);
309
    value &= 0x01;
310
    target |= (value << index);
311
    return target;
312
}
313
 
314
static uint8_t cpu_compute_ac(cpu51_t *cpu, uint8_t x, uint8_t y, cpu_op_t op){
315
 
316
  if(op==subb){
317
    x = x & 0x0f;
318
    y = y & 0x0f;
319
    if((cpu->sfr.psw)&0x80){
320
      y++;
321
    }
322
    return (x<y)?1:0;
323
  }
324
  else{
325
    x = x & 0x0f;
326
    y = y & 0x0f;
327
    if((cpu->sfr.psw)&0x80){
328
      y++;
329
    }
330
    return ((x+y)>0x0f)?1:0;
331
  }
332
}
333
 
334
static uint8_t cpu_update_flags(cpu51_t *cpu, uint8_t s, uint8_t d, cpu_op_t op){
335
    uint16_t res, x, y, res_half, rem;
336
    uint16_t cy=0, ov=0, ac=0;
337
 
338
    x = (uint16_t)s;
339
    y = (uint16_t)d;
340
 
341
    switch(op){
342
    case add:
343
        res = x + y;
344
        res_half = (x & 0x0f) + (y & 0x0f);
345
        cy = (res & 0x0100)? 1 : 0;
346
        ac = (res_half & 0x0010)? 1 : 0;
347
        if((x < 0x80) && (y < 0x80)){
348
            ov = (res & 0x0080)? 1 : 0;
349
        }
350
        else if((x >= 0x80) && (y >= 0x80)){
351
            ov = (~(res & 0x0080))? 1 : 0;
352
        }
353
        else{
354
            ov = 0;
355
        }
356
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
357
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 6, ac);
358
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 2, ov);
359
        break;
360
    case subb:
361
        ac = cpu_compute_ac(cpu, x, y, subb);
362
        y ^= 0xffff;
363
        y += 1;
364
        res = x + y;
365
        if(cpu->sfr.psw & 0x80){
366
            res--;
367
        }
368
        cy = (res & 0x0100)? 1 : 0;
369
 
370
        if((x < 0x80) && (y >= 0x80)){
371
            /* positive - negative = positive, otherwise OV */
372
            ov = (res & 0x0080)? 1 : 0;
373
        }
374
        else if((x >= 0x80) && (y < 0x80)){
375
            /* negative - positive = negative, otherwise OV */
376
            ov = (~(res & 0x0080))? 1 : 0;
377
        }
378
        else{
379
            ov = 0;
380
        }
381
 
382
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
383
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 6, ac);
384
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 2, ov);
385
        break;
386
    case addc:
387
        res = x + y;
388
        res_half = (x & 0x0f) + (y & 0x0f);
389
        if(cpu->sfr.psw & 0x80){
390
            res++;
391
            res_half++;
392
        }
393
        cy = (res & 0x0100)? 1 : 0;
394
        ac = (res_half & 0x0010)? 1 : 0;
395
        if((x < 0x80) && (y < 0x80)){
396
            ov = (res & 0x0080)? 1 : 0;
397
        }
398
        else if((x >= 0x80) && (y >= 0x80)){
399
            ov = (~(res & 0x0080))? 1 : 0;
400
        }
401
        else{
402
            ov = 0;
403
        }
404
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
405
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 6, ac);
406
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 2, ov);
407
        break;
408
    case alu_mul:
409
        res = x * y;
410
        ov = (res & 0xff00)? 1 : 0;
411
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, 0);
412
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 2, ov);
413
        /* special case: update B right here */
414
        cpu->sfr.b = (res>>8)&0xff;
415
        res = res & 0xff;
416
        break;
417
    case alu_div:
418
        if(y != 0){
419
            res = x / y;
420
            rem = x % y;
421
            cy = 0;
422
            ov = 0;
423
            /* special case: update B right here */
424
            cpu->sfr.b = rem;
425
        }
426
        else{
427
            ov = 1;
428
            cy = 0;
429
            /* Quotient and remainder are undefined in Intel specs; we'll use
430
               light52 actual values for consistency of the SW/HW simulations */
431
            res = 0xff;
432
            rem = 0x00;
433
        }
434
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
435
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 2, ov);
436
        break;
437
    case da:
438
        x = s & 0x0f;
439
        y = s;
440
        if((x > 9) || ((cpu->sfr.psw&0x40)!=0)){
441
            y += 0x06;
442
        }
443
        x = (y >> 4) & 0x1f;
444
        if((x > 9) || ((cpu->sfr.psw&0x80)!=0)){
445
            y += 0x60;
446
        }
447
        res = y & 0x0ff;
448
        /* DA can SET C but can't clear it if it's set */
449
        if(y > 0x0ff){
450
            cpu->sfr.psw |= 0x80;
451
        }
452
        break;
453
    case rlc:
454
        res = (s << 1) | (cpu->sfr.psw >> 7);
455
        cy = (s >> 7) & 0x01;
456
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
457
        break;
458
    case rl:
459
        res = (s << 1) | ((s >> 7) & 0x01);
460
        break;
461
    case rrc:
462
        cy = (s & 0x01)? 1 : 0;
463
        res = ((s >> 1) & 0x7f) | (cpu->sfr.psw & 0x80);
464
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
465
        break;
466
    case rr:
467
        res = ((s >> 1) & 0x7f) | ((s << 7) & 0x80);
468
        break;
469
    case setb_c:
470
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, 1);
471
        res = 0; /* unused ret value */
472
        break;
473
    case clr_c:
474
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, 0);
475
        res = 0; /* unused ret value */
476
        break;
477
    case anl_c:
478
        s = (cpu->sfr.psw >> 7);
479
        cy = s & d;
480
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
481
        break;
482
    case orl_c:
483
        s = (cpu->sfr.psw >> 7);
484
        cy = s | d;
485
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, cy);
486
        break;
487
    case cjne:
488
        if(x < y){
489
            cpu->sfr.psw |= 0x80;
490
        }
491
        else{
492
            cpu->sfr.psw &= ~0x80;
493
        }
494
        res = 0;
495
        break;
496
    }
497
 
498
    return res;
499
}
500
 
501
static void cpu_set_sfr(cpu51_t *cpu, uint8_t dir, uint8_t value){
502
    uint16_t undefined_sfr=0;
503
 
504
    if(dir < 0x80) return;
505
 
506
    switch(dir){
507
    case 0xe0:  /* ACC */
508
        cpu_set_a(cpu, value);
509
        break;
510
    case 0xf0:  /* B */
511
        cpu->sfr.b = value;
512
        break;
513
    case 0x83:  /* DPH */
514
        cpu->sfr.dph = value;
515
        break;
516
    case 0x82:  /* DPL */
517
        cpu->sfr.dpl = value;
518
        break;
519
    case 0xa8:  /* IE */
520
        cpu->sfr.ie = value;
521
        break;
522
    case 0xb8:  /* IP */
523
        cpu->sfr.ip = value;
524
        break;
525
    case 0x0d0: /* PSW */
526
        /* The P flag can't be overwritten */
527
        cpu->sfr.psw = (value & 0xfe) | (cpu->sfr.psw & 0x01);
528
        break;
529
    case 0x081: /* SP */
530
        cpu->sfr.sp = value;
531
        break;
532
    default:
533
        undefined_sfr = mcu_set_sfr(&cpu->mcu, dir, value);
534
        if(undefined_sfr){
535
            /* TODO unimplemented SFR addr message should be optional */
536
            printf("(%04X) UNIMPLEMENTED SFR %02X\n", cpu->log.pc, dir);
537
        }
538
    }
539
    log_sfr(&(cpu->log), dir, value);
540
}
541
 
542
static uint8_t cpu_get_sfr(cpu51_t *cpu, uint8_t dir){
543
    uint16_t sfr_value;
544
 
545
    /* TODO this is a bug and some fault flag should be raised */
546
    if(dir < 0x80) return 0;
547
 
548
    switch(dir){
549
    case 0xe0:  /* ACC */
550
        return cpu->a;
551
        break;
552
    case 0xf0:  /* B */
553
        return cpu->sfr.b;
554
        break;
555
    case 0x83:  /* DPH */
556
        return cpu->sfr.dph;
557
        break;
558
    case 0x82:  /* DPL */
559
        return cpu->sfr.dpl;
560
        break;
561
    case 0xa8:  /* IE */
562
        return cpu->sfr.ie;
563
        break;
564
    case 0xb8:  /* IP */
565
        return cpu->sfr.ip;
566
        break;
567
    case 0x0d0: /* PSW */
568
        return cpu->sfr.psw;
569
        break;
570
    case 0x081: /* SP */
571
        return cpu->sfr.sp;
572
        break;
573
    default:
574
        sfr_value = mcu_get_sfr(&cpu->mcu, dir);
575
        if(sfr_value==0xffff){
576
            /* TODO unimplemented SFR addr message should be optional */
577
            printf("(%04X) UNIMPLEMENTED SFR %02X\n", cpu->log.pc, dir);
578
        }
579
        else{
580
            return (uint8_t)sfr_value;
581
        }
582
    }
583
 
584
    /* Control will never actually reach here */
585
    return 0;
586
}
587
 
588
static void cpu_set_idata(cpu51_t *cpu, uint8_t dir, uint8_t value){
589
    /* FIXME check bounds */
590
    cpu->idata[dir] = value;
591
    log_idata(&(cpu->log), dir, value);
592
}
593
 
594
static void cpu_set_dir(cpu51_t *cpu, uint8_t dir, uint8_t value){
595
    /* Direct addressing mode is special; can access both idata and sfr */
596
    if(dir > 0x07f){
597
        /* In direct addressing mode, 0x80 to 0xff is actually an SFR address */
598
        cpu_set_sfr(cpu, dir, value);
599
    }
600
    else{
601
        /* From 0x00 to 0x7f, we're addressing regular idata RAM */
602
        cpu->idata[dir] = value;
603
        log_idata(&(cpu->log), dir, value);
604
    }
605
}
606
 
607
static uint8_t cpu_get_dir(cpu51_t *cpu, uint8_t dir){
608
    /* Direct addressing mode is special; can access both idata and sfr */
609
    if(dir > 0x07f){
610
        /* In direct addressing mode, 0x80 to 0xff is actually an SFR address */
611
        return cpu_get_sfr(cpu, dir);
612
    }
613
    else{
614
        /* From 0x00 to 0x7f, we're addressing regular idata RAM */
615
        return cpu->idata[dir];
616
    }
617
}
618
 
619
static uint8_t cpu_get_idata(cpu51_t *cpu, uint8_t dir){
620
    /* FIXME check bounds */
621
    return cpu->idata[dir];
622
}
623
 
624
 
625
static bool cpu_rel_jump(cpu51_t *cpu, uint8_t rel){
626
    int16_t target, offset;
627
 
628
    target = (int16_t)cpu->pc;
629
    offset = (int16_t)((int8_t)rel);
630
    target += offset;
631
    cpu->pc = (uint16_t)target;
632
    return log_jump(&(cpu->log), cpu->pc);
633
}
634
 
635
 
636
static uint8_t cpu_get_bit_address(cpu51_t *cpu, uint8_t bit){
637
    uint8_t addr;
638
 
639
    if(bit > 0x7f){
640
        addr = bit & 0xf8;
641
    }
642
    else{
643
        addr = 0x20 + (bit >> 3);
644
    }
645
 
646
    return addr;
647
}
648
 
649
 
650
static uint8_t cpu_get_bit(cpu51_t *cpu, uint8_t bit){
651
    uint8_t dir, res, value;
652
 
653
    dir = cpu_get_bit_address(cpu, bit);
654
    res = cpu_get_dir(cpu, dir);
655
    value = (res & (1 << (bit & 0x07)))? 1 : 0;
656
 
657
    return value;
658
}
659
 
660
 
661
static void cpu_set_bit(cpu51_t *cpu, uint8_t bit, uint8_t value){
662
    uint8_t dir, res;
663
 
664
    dir = cpu_get_bit_address(cpu, bit);
665
    res = cpu_get_dir(cpu, dir);
666
    res = set_bit(res, bit, value);
667
    cpu_set_dir(cpu, dir, res);
668
}
669
 
670
 
671
static bool cpu_exec_upper_half(cpu51_t *cpu, uint8_t opcode){
672
    uint8_t imm, dir, dir2, bit, res, rel, val;
673
    uint8_t hi, lo;
674
    uint16_t address;
675
    bool ok = true, endless_loop = false;
676
 
677
 
678
    switch(opcode){
679
    /*-- ROW 0 ---------------------------------------------------------------*/
680
    case 0x00:  /* NOP */
681
        break;
682
    case 0x10: /* Jcc bit, rel */
683
    case 0x20:
684
    case 0x30:
685
        bit = cpu_fetch(cpu);
686
        rel = cpu_fetch(cpu);
687
        dir = cpu_get_bit_address(cpu, bit);
688
        res = cpu_get_dir(cpu, dir);
689
        switch(opcode){
690
        case 0x10:  /* JBC bit, rel */
691
            val = res & (1 << (bit & 0x07));
692
            res &= ~(1 << (bit & 0x07));
693
            cpu_set_dir(cpu, dir, res);
694
            if(val){
695
                cpu_rel_jump(cpu, rel);
696
                cpu->max_cycle_count = true;
697
            }
698
            break;
699
        case 0x20:  /* JB bit, rel */
700
            if(res & (1 << (bit & 0x07))){
701
                cpu_rel_jump(cpu, rel);
702
                cpu->max_cycle_count = true;
703
            }
704
            break;
705
        case 0x30:  /* JC bit, rel */
706
            if((res & (1 << (bit & 0x07))) ==0){
707
                cpu_rel_jump(cpu, rel);
708
                cpu->max_cycle_count = true;
709
            }
710
            break;
711
        }
712
        break;
713
    case 0x40:  /* JC rel */
714
        rel = cpu_fetch(cpu);
715
        if(cpu->sfr.psw & 0x80){
716
            cpu_rel_jump(cpu, rel);
717
            cpu->max_cycle_count = true;
718
        }
719
        break;
720
    case 0x50:  /* JNC rel */
721
        rel = cpu_fetch(cpu);
722
        if(!(cpu->sfr.psw & 0x80)){
723
            cpu_rel_jump(cpu, rel);
724
            cpu->max_cycle_count = true;
725
        }
726
        break;
727
    case 0x60:  /* JZ rel */
728
        rel = cpu_fetch(cpu);
729
        if(cpu->a == 0){
730
            cpu_rel_jump(cpu, rel);
731
            cpu->max_cycle_count = true;
732
        }
733
        break;
734
    case 0x70:  /* JNZ rel */
735
        rel = cpu_fetch(cpu);
736
        if(cpu->a != 0){
737
            cpu_rel_jump(cpu, rel);
738
            cpu->max_cycle_count = true;
739
        }
740
        break;
741
    case 0x80:  /* SJMP rel */
742
        rel = cpu_fetch(cpu);
743
        endless_loop = cpu_rel_jump(cpu, rel);
744
        break;
745
    case 0x90:  /* MOV DPTR, #addr16 */
746
        hi = cpu_fetch(cpu);
747
        lo = cpu_fetch(cpu);
748
        cpu->sfr.dph = hi;
749
        cpu->sfr.dpl = lo;
750
        log_sfr(&(cpu->log), 0x83, hi);
751
        log_sfr(&(cpu->log), 0x82, lo);
752
        break;
753
    case 0xa0:  /* ORL C, /bit */
754
        bit = cpu_fetch(cpu);
755
        res = 1 - cpu_get_bit(cpu, bit);
756
        cpu->sfr.psw  |= (res << 7);
757
        break;
758
    case 0xb0:  /* ANL C, /bit */
759
        bit = cpu_fetch(cpu);
760
        res = 1 - cpu_get_bit(cpu, bit);
761
        cpu->sfr.psw  &= (res << 7);
762
        break;
763
    case 0xc0:  /* PUSH dir */
764
        dir = cpu_fetch(cpu);
765
        res = cpu_get_dir(cpu, dir);
766
        cpu->sfr.sp++;
767
        cpu_set_idata(cpu, cpu->sfr.sp, res);
768
        break;
769
    case 0xd0:  /* POP dir */
770
        dir = cpu_fetch(cpu);
771
        res = cpu_get_idata(cpu, cpu->sfr.sp--);
772
        cpu_set_dir(cpu, dir, res);
773
        break;
774
    case 0xe0:  /* MOVX A, @DPTR */
775
        address = (((uint16_t)cpu->sfr.dph) << 8) + (uint16_t)cpu->sfr.dpl;
776
        res = cpu_xdata_read(cpu, address);
777
        cpu_set_a(cpu, res);
778
        break;
779
    case 0xf0:  /* MOVX @DPTR, A */
780
        address = (((uint16_t)cpu->sfr.dph) << 8) + (uint16_t)cpu->sfr.dpl;
781
        cpu_xdata_write(cpu, address, cpu->a);
782
        break;
783
    /*-- ROW 1 ---------------------------------------------------------------*/
784
    case 0x01: case 0x21: case 0x41: case 0x61: /* AJMP addr11 */
785
    case 0x81: case 0xa1: case 0xc1: case 0xe1:
786
        address = cpu_fetch11(cpu, opcode);
787
        cpu->pc = address;
788
        endless_loop = log_jump(&(cpu->log), address);
789
        break;
790
    case 0x11: case 0x31: case 0x51: case 0x71: /* ACALL addr11 */
791
    case 0x91: case 0xb1: case 0xd1: case 0xf1:
792
        address = cpu_fetch11(cpu, opcode);
793
        hi = (uint8_t)(cpu->pc >> 8);
794
        lo = (uint8_t)(cpu->pc >> 0);
795
        cpu->sfr.sp++;
796
        cpu_set_idata(cpu, cpu->sfr.sp, lo);
797
        cpu->sfr.sp++;
798
        cpu_set_idata(cpu, cpu->sfr.sp, hi);
799
        cpu->pc = address;
800
        endless_loop = log_jump(&(cpu->log), address);
801
        break;
802
    /*-- ROW 2 ---------------------------------------------------------------*/
803
    case 0x02:  /* LJMP addr16 */
804
        address = cpu_fetch16(cpu);
805
        cpu->pc = address;
806
        endless_loop = log_jump(&(cpu->log), address);
807
        break;
808
    case 0x12:  /* LCALL addr16 */
809
        address = cpu_fetch16(cpu);
810
        hi = (uint8_t)(cpu->pc >> 8);
811
        lo = (uint8_t)(cpu->pc >> 0);
812
        cpu->sfr.sp++;
813
        cpu_set_idata(cpu, cpu->sfr.sp, lo);
814
        cpu->sfr.sp++;
815
        cpu_set_idata(cpu, cpu->sfr.sp, hi);
816
        cpu->pc = address;
817
        endless_loop = log_jump(&(cpu->log), address);
818
        break;
819
    case 0x22:  /* RET */
820
        hi = cpu_get_idata(cpu, cpu->sfr.sp--);
821
        lo = cpu_get_idata(cpu, cpu->sfr.sp--);
822
        address = ((uint16_t)hi << 8) + (uint16_t)lo;
823
        cpu->pc = address;
824
        endless_loop = log_jump(&(cpu->log), address);
825
        break;
826
    case 0x32:  /* RET */
827
        /* FIXME interrupts unimplemented / RETI */
828
        hi = cpu_get_idata(cpu, cpu->sfr.sp--);
829
        lo = cpu_get_idata(cpu, cpu->sfr.sp--);
830
        address = ((uint16_t)hi << 8) + (uint16_t)lo;
831
        cpu->pc = address;
832
        endless_loop = log_jump(&(cpu->log), address);
833
        break;
834
    case 0x42:  /* ORL dir, A */
835
        dir = cpu_fetch(cpu);
836
        res = cpu_get_dir(cpu, dir);
837
        res = res | cpu->a;
838
        cpu_set_dir(cpu, dir, res);
839
        break;
840
    case 0x52:  /* ANL dir, A */
841
        dir = cpu_fetch(cpu);
842
        res = cpu_get_dir(cpu, dir);
843
        res = res & cpu->a;
844
        cpu_set_dir(cpu, dir, res);
845
        break;
846
    case 0x62:  /* XRL dir, A */
847
        dir = cpu_fetch(cpu);
848
        res = cpu_get_dir(cpu, dir);
849
        res = res ^ cpu->a;
850
        cpu_set_dir(cpu, dir, res);
851
        break;
852
    case 0x72:  /* ORL C, bit */
853
        bit = cpu_fetch(cpu);
854
        res = cpu_get_bit(cpu, bit);
855
        cpu->sfr.psw  |= (res << 7);
856
        break;
857
    case 0x82:  /* ANL C, bit */
858
        bit = cpu_fetch(cpu);
859
        res = cpu_get_bit(cpu, bit);
860
        cpu->sfr.psw &= (res << 7);
861
        break;
862
    case 0x92:  /* MOV bit, C */
863
        bit = cpu_fetch(cpu);
864
        cpu_set_bit(cpu, bit, (cpu->sfr.psw >> 7));
865
        break;
866
    case 0xa2:  /* MOV C, bit */
867
        bit = cpu_fetch(cpu);
868
        res = cpu_get_bit(cpu, bit);
869
        cpu->sfr.psw = set_bit(cpu->sfr.psw, 7, res);
870
        break;
871
    case 0xb2:  /* CPL bit */
872
        bit = cpu_fetch(cpu);
873
        dir = cpu_get_bit_address(cpu, bit);
874
        res = cpu_get_dir(cpu, dir);
875
        res ^= (1 << (bit & 0x07));
876
        cpu_set_dir(cpu, dir, res);
877
        break;
878
    case 0xc2:  /* CLR bit */
879
        bit = cpu_fetch(cpu);
880
        dir = cpu_get_bit_address(cpu, bit);
881
        res = cpu_get_dir(cpu, dir);
882
        res &= ~(1 << (bit & 0x07));
883
        cpu_set_dir(cpu, dir, res);
884
        break;
885
    case 0xd2:  /* SETB bit */
886
        bit = cpu_fetch(cpu);
887
        dir = cpu_get_bit_address(cpu, bit);
888
        res = cpu_get_dir(cpu, dir);
889
        res |= (1 << (bit & 0x07));
890
        cpu_set_dir(cpu, dir, res);
891
        break;
892
    case 0xe2:  /* MOVX A, @R0 */
893
        /* TODO MOVX @Ri upper address byte hardcoded to zero */
894
        address = ((uint16_t)cpu_get_rn(cpu, 0)) & 0x00ff;
895
        res = cpu_xdata_read(cpu, address);
896
        cpu_set_a(cpu, res);
897
        break;
898
    case 0xf2:  /* MOVX @R0, A */
899
        /* TODO MOVX @Ri upper address byte hardcoded to zero */
900
        address = ((uint16_t)cpu_get_rn(cpu, 0)) & 0x00ff;
901
        cpu_xdata_write(cpu, address, cpu->a);
902
        break;
903
    /*-- ROW 3 ---------------------------------------------------------------*/
904
    case 0x03:  /* RR A */
905
        val = cpu_update_flags(cpu, cpu->a, 0, rr);
906
        cpu_set_a(cpu, val);
907
        break;
908
    case 0x13:  /* RRC A */
909
        val = cpu_update_flags(cpu, cpu->a, 0, rrc);
910
        cpu_set_a(cpu, val);
911
        break;
912
    case 0x23:  /* RL A */
913
        val = cpu_update_flags(cpu, cpu->a, 0, rl);
914
        cpu_set_a(cpu, val);
915
        break;
916
    case 0x33:  /* RLC A */
917
        val = cpu_update_flags(cpu, cpu->a, 0, rlc);
918
        cpu_set_a(cpu, val);
919
        break;
920
    case 0x43:  /* ORL dir, #data */
921
        dir = cpu_fetch(cpu);
922
        imm = cpu_fetch(cpu);
923
        res = cpu_get_dir(cpu, dir);
924
        res = res | imm;
925
        cpu_set_dir(cpu, dir, res);
926
        break;
927
    case 0x53:  /* ANL dir, #data */
928
        dir = cpu_fetch(cpu);
929
        imm = cpu_fetch(cpu);
930
        res = cpu_get_dir(cpu, dir);
931
        res = res & imm;
932
        cpu_set_dir(cpu, dir, res);
933
        break;
934
    case 0x63:  /* XRL dir, #data */
935
        dir = cpu_fetch(cpu);
936
        imm = cpu_fetch(cpu);
937
        res = cpu_get_dir(cpu, dir);
938
        res = res ^ imm;
939
        cpu_set_dir(cpu, dir, res);
940
        break;
941
    case 0x73:  /* JMP @A + DPTR */
942
        address = (((uint16_t)cpu->sfr.dph) << 8) + (uint16_t)cpu->sfr.dpl;
943
        address += (uint16_t)(cpu->a);
944
        cpu->pc = address;
945
        endless_loop = log_jump(&(cpu->log), address);
946
        break;
947
    case 0x83:  /* MOVC A, @A + PC */
948
        /* Base is PC of NEXT instruction == cpu->pc */
949
        address = cpu->pc + (uint16_t)(cpu->a);
950
        res = cpu_xcode_read(cpu, address);
951
        cpu_set_a(cpu, res);
952
        break;
953
    case 0x93:  /* MOVC A, @A + DPTR */
954
        address = (((uint16_t)cpu->sfr.dph) << 8) + (uint16_t)cpu->sfr.dpl;
955
        address += (uint16_t)(cpu->a);
956
        res = cpu_xcode_read(cpu, address);
957
        cpu_set_a(cpu, res);
958
        break;
959
    case 0xa3:  /* INC DPTR */
960
        address = (((uint16_t)cpu->sfr.dph) << 8) + (uint16_t)cpu->sfr.dpl;
961
        address++;
962
        cpu->sfr.dph = (uint8_t)(address >> 8);
963
        cpu->sfr.dpl = (uint8_t)(address >> 0);
964
        log_reg16(&(cpu->log), "DPTR", address);
965
        break;
966
    case 0xb3:  /* CPL C */
967
        cpu->sfr.psw ^= 0x80;
968
        break;
969
    case 0xc3:  /* CLR C */
970
        cpu->sfr.psw &= ~0x80;
971
        break;
972
    case 0xd3:  /* SETB C */
973
        cpu->sfr.psw |= 0x80;
974
        break;
975
    case 0xe3:  /* MOVX A, @R0 */
976
        /* TODO MOVX @Ri upper address byte hardcoded to zero */
977
        address = ((uint16_t)cpu_get_rn(cpu, 1)) & 0x00ff;
978
        res = cpu_xdata_read(cpu, address);
979
        cpu_set_a(cpu, res);
980
        break;
981
    case 0xf3:  /* MOVX @R0, A */
982
        /* TODO MOVX @Ri upper address byte hardcoded to zero */
983
        address = ((uint16_t)cpu_get_rn(cpu, 1)) & 0x00ff;
984
        cpu_xdata_write(cpu, address, cpu->a);
985
        break;
986
    /*-- ROW 4 ---------------------------------------------------------------*/
987
    case 0x04:  /* INC a */
988
        cpu_set_a(cpu, cpu->a + 1);
989
        break;
990
    case 0x14:  /* DEC a */
991
        cpu_set_a(cpu, cpu->a - 1);
992
        break;
993
    case 0x24:  /* ADD A, #imm */
994
        imm = cpu_fetch(cpu);
995
        res = cpu_update_flags(cpu, cpu->a, imm, add);
996
        cpu_set_a(cpu, res);
997
        break;
998
    case 0x34:  /* ADDC A, #imm */
999
        imm = cpu_fetch(cpu);
1000
        res = cpu_update_flags(cpu, cpu->a, imm, addc);
1001
        cpu_set_a(cpu, res);
1002
        break;
1003
    case 0x44:  /* ORL A, #imm */
1004
        imm = cpu_fetch(cpu);
1005
        res = cpu->a | imm;
1006
        cpu_set_a(cpu, res);
1007
        break;
1008
    case 0x54:  /* ANL A, #imm */
1009
        imm = cpu_fetch(cpu);
1010
        res = cpu->a & imm;
1011
        cpu_set_a(cpu, res);
1012
        break;
1013
    case 0x64:  /* XRL A, #imm */
1014
        imm = cpu_fetch(cpu);
1015
        res = cpu->a ^ imm;
1016
        cpu_set_a(cpu, res);
1017
        break;
1018
    case 0x74:  /* MOV A, #data */
1019
        imm = cpu_fetch(cpu);
1020
        cpu_set_a(cpu, imm);
1021
        break;
1022
    case 0x84:  /* DIV AB */
1023
        res = cpu_update_flags(cpu, cpu->a, cpu->sfr.b, alu_div);
1024
        cpu_set_a(cpu, res);
1025
        break;
1026
    case 0x94:  /* SUBB A, #data */
1027
        imm = cpu_fetch(cpu);
1028
        res = cpu_update_flags(cpu, cpu->a, imm, subb);
1029
        cpu_set_a(cpu, res);
1030
        break;
1031
    case 0xa4:  /* MUL AB */
1032
        res = cpu_update_flags(cpu, cpu->a, cpu->sfr.b, alu_mul);
1033
        cpu_set_a(cpu, res);
1034
        break;
1035
    case 0xb4:  /* CJNE A, #data, rel */
1036
        imm = cpu_fetch(cpu);
1037
        rel = cpu_fetch(cpu);
1038
        cpu_update_flags(cpu, cpu->a, imm, cjne);
1039
        if(imm != cpu->a){
1040
            cpu_rel_jump(cpu, rel);
1041
            cpu->max_cycle_count = true;
1042
        }
1043
        break;
1044
    case 0xc4:  /* SWAP A */
1045
        res = (cpu->a >> 4) & 0x0f;
1046
        res = res | ((cpu->a << 4) & 0x0f0);
1047
        cpu_set_a(cpu, res);
1048
        break;
1049
    case 0xd4:  /* DA A */
1050
        if(cpu->options.bcd){
1051
            val = cpu_update_flags(cpu, cpu->a, 0, da);
1052
            cpu_set_a(cpu, val);
1053
        }
1054
        else{
1055
            /* DA unimplemented, execute as NOP */
1056
            cpu->implemented_as_nop = true;
1057
        }
1058
        break;
1059
    case 0xe4:  /* CLR A */
1060
        cpu_set_a(cpu, 0);
1061
        break;
1062
    case 0xf4:  /* CPL A */
1063
        cpu_set_a(cpu, ~(cpu->a));
1064
        break;
1065
    /*-- ROW 5 ---------------------------------------------------------------*/
1066
    case 0x05:  /* INC dir */
1067
        dir = cpu_fetch(cpu);
1068
        res = cpu_get_dir(cpu, dir);
1069
        res = res + 1;
1070
        cpu_set_dir(cpu, dir, res);
1071
        break;
1072
    case 0x15:  /* DEC dir */
1073
        dir = cpu_fetch(cpu);
1074
        res = cpu_get_dir(cpu, dir);
1075
        res = res - 1;
1076
        cpu_set_dir(cpu, dir, res);
1077
        break;
1078
    case 0x25:  /* ADD A, dir */
1079
        dir = cpu_fetch(cpu);
1080
        res = cpu_get_dir(cpu, dir);
1081
        res = cpu_update_flags(cpu, cpu->a, res, add);
1082
        cpu_set_a(cpu, res);
1083
        break;
1084
    case 0x35:  /* ADDC A, dir */
1085
        dir = cpu_fetch(cpu);
1086
        res = cpu_get_dir(cpu, dir);
1087
        res = cpu_update_flags(cpu, cpu->a, res, addc);
1088
        cpu_set_a(cpu, res);
1089
        break;
1090
    case 0x45:  /* ORL A, dir */
1091
        dir = cpu_fetch(cpu);
1092
        res = cpu_get_dir(cpu, dir);
1093
        res = res | cpu->a;
1094
        cpu_set_a(cpu, res);
1095
        break;
1096
    case 0x55:  /* ANL A, dir */
1097
        dir = cpu_fetch(cpu);
1098
        res = cpu_get_dir(cpu, dir);
1099
        res = res & cpu->a;
1100
        cpu_set_a(cpu, res);
1101
        break;
1102
    case 0x65:  /* XRL A, dir */
1103
        dir = cpu_fetch(cpu);
1104
        res = cpu_get_dir(cpu, dir);
1105
        res = res ^ cpu->a;
1106
        cpu_set_a(cpu, res);
1107
        break;
1108
    case 0x75:  /* MOV dir, #imm */
1109
        dir = cpu_fetch(cpu);
1110
        imm = cpu_fetch(cpu);
1111
        cpu_set_dir(cpu, dir, imm);
1112
        break;
1113
    case 0x85:  /* MOV dir1, dir2 */
1114
        dir = cpu_fetch(cpu);
1115
        dir2 = cpu_fetch(cpu);
1116
        res = cpu_get_dir(cpu, dir);
1117
        cpu_set_dir(cpu, dir2, res);
1118
        break;
1119
    case 0x95:  /* SUBB A, dir */
1120
        dir = cpu_fetch(cpu);
1121
        res = cpu_get_dir(cpu, dir);
1122
        res = cpu_update_flags(cpu, cpu->a, res, subb);
1123
        cpu_set_a(cpu, res);
1124
        break;
1125
    case 0xa5:  /* RESERVED A5h opcode : implemented as NOP */
1126
        cpu->implemented_as_nop = true;
1127
        break;
1128
    case 0xb5:  /* CJNE A, dir, rel */
1129
        dir = cpu_fetch(cpu);
1130
        rel = cpu_fetch(cpu);
1131
        res = cpu_get_dir(cpu, dir);
1132
        cpu_update_flags(cpu, cpu->a, res, cjne);
1133
        if(res != cpu->a){
1134
            cpu_rel_jump(cpu, rel);
1135
            cpu->max_cycle_count = true;
1136
        }
1137
        break;
1138
    case 0xc5:  /* XCH A,dir */
1139
        dir = cpu_fetch(cpu);
1140
        res = cpu_get_dir(cpu, dir);
1141
        cpu_set_dir(cpu, dir, cpu->a);
1142
        cpu_set_a(cpu, res);
1143
        break;
1144
    case 0xd5:  /* DJNZ dir, rel */
1145
        dir = cpu_fetch(cpu);
1146
        rel = cpu_fetch(cpu);
1147
        res = cpu_get_dir(cpu, dir);
1148
        res = res - 1;
1149
        cpu_set_dir(cpu, dir, res);
1150
        if(res != 0){
1151
            cpu_rel_jump(cpu, rel);
1152
            cpu->max_cycle_count = true;
1153
        }
1154
        break;
1155
    case 0xe5:  /* MOV a, dir */
1156
        dir = cpu_fetch(cpu);
1157
        res = cpu_get_dir(cpu, dir);
1158
        cpu_set_a(cpu, res);
1159
        break;
1160
    case 0xf5:  /* MOV dir, a */
1161
        dir = cpu_fetch(cpu);
1162
        cpu_set_dir(cpu, dir, cpu->a);
1163
        break;
1164
    /*-- ROW 6 & ROW 7 -------------------------------------------------------*/
1165
    /*  IMPORTANT:
1166
        All the cases in the x6 & x7 groups are PAIRED. The 'case fallthrough'
1167
        is intentional.
1168
        TODO label fallthrough case for lint tool.
1169
    */
1170
    case 0x06:  /* INC @Ri */
1171
    case 0x07:
1172
        dir = cpu_get_rn(cpu, opcode & 0x01);
1173
        res = cpu_get_idata(cpu, dir);
1174
        cpu_set_idata(cpu, dir, res + 1);
1175
        break;
1176
    case 0x16:  /* DEC @Ri */
1177
    case 0x17:
1178
        dir = cpu_get_rn(cpu, opcode & 0x01);
1179
        res = cpu_get_idata(cpu, dir);
1180
        cpu_set_idata(cpu, dir, res - 1);
1181
        break;
1182
    case 0x26:  /* ADD A, @Ri */
1183
    case 0x27:
1184
        dir = cpu_get_rn(cpu, opcode & 0x01);
1185
        res = cpu_get_idata(cpu, dir);
1186
        res = cpu_update_flags(cpu, cpu->a, res, add);
1187
        cpu_set_a(cpu, res);
1188
        break;
1189
    case 0x36:  /* ADDC A, @Ri */
1190
    case 0x37:
1191
        dir = cpu_get_rn(cpu, opcode & 0x01);
1192
        res = cpu_get_idata(cpu, dir);
1193
        res = cpu_update_flags(cpu, cpu->a, res, addc);
1194
        cpu_set_a(cpu, res);
1195
        break;
1196
    case 0x46:  /* ORL A, @Ri */
1197
    case 0x47:
1198
        dir = cpu_get_rn(cpu, opcode & 0x01);
1199
        res = cpu_get_idata(cpu, dir);
1200
        res = res | cpu->a;
1201
        cpu_set_a(cpu, res);
1202
        break;
1203
    case 0x56:  /* ANL A, @Ri */
1204
    case 0x57:
1205
        dir = cpu_get_rn(cpu, opcode & 0x01);
1206
        res = cpu_get_idata(cpu, dir);
1207
        res = res & cpu->a;
1208
        cpu_set_a(cpu, res);
1209
        break;
1210
    case 0x66:  /* XRL A, @Ri */
1211
    case 0x67:
1212
        dir = cpu_get_rn(cpu, opcode & 0x01);
1213
        res = cpu_get_idata(cpu, dir);
1214
        res = res ^ cpu->a;
1215
        cpu_set_a(cpu, res);
1216
        break;
1217
    case 0x76:  /* MOV @Ri, imm */
1218
    case 0x77:
1219
        imm = cpu_fetch(cpu);
1220
        dir = cpu_get_rn(cpu, opcode & 0x01);
1221
        cpu_set_idata(cpu, dir, imm);
1222
        break;
1223
    case 0x86:  /* MOV dir, @Ri */
1224
    case 0x87:
1225
        dir = cpu_fetch(cpu);
1226
        imm = cpu_get_rn(cpu, opcode & 0x01);
1227
        res = cpu_get_idata(cpu, imm);
1228
        cpu_set_dir(cpu, dir, res);
1229
        break;
1230
    case 0x96:  /* SUBB A, @Ri */
1231
    case 0x97:
1232
        dir = cpu_get_rn(cpu, opcode & 0x01);
1233
        res = cpu_get_idata(cpu, dir);
1234
        res = cpu_update_flags(cpu, cpu->a, res, subb);
1235
        cpu_set_a(cpu, res);
1236
        break;
1237
    case 0xa6:  /* MOV @Ri, dir */
1238
    case 0xa7:
1239
        dir = cpu_fetch(cpu);
1240
        res = cpu_get_dir(cpu, dir);
1241
        dir = cpu_get_rn(cpu, opcode & 0x01);
1242
        cpu_set_idata(cpu, dir, res);
1243
        break;
1244
    case 0xb6:  /* CJNE @Ri, #imm, rel */
1245
    case 0xb7:
1246
        imm = cpu_fetch(cpu);
1247
        rel = cpu_fetch(cpu);
1248
        dir = cpu_get_rn(cpu, opcode & 0x01);
1249
        res = cpu_get_idata(cpu, dir);
1250
        cpu_update_flags(cpu, res, imm, cjne);
1251
        if(imm != res){
1252
            cpu_rel_jump(cpu, rel);
1253
            cpu->max_cycle_count = true;
1254
        }
1255
        break;
1256
    case 0xc6:  /* XCH A,@Ri */
1257
    case 0xc7:
1258
        dir = cpu_get_rn(cpu, opcode & 0x01);
1259
        res = cpu_get_idata(cpu, dir);
1260
        cpu_set_idata(cpu, dir, cpu->a);
1261
        cpu_set_a(cpu, res);
1262
        break;
1263
    case 0xd6:  /* XCHD A,@Ri */
1264
    case 0xd7:
1265
        if(cpu->options.bcd){
1266
            dir = cpu_get_rn(cpu, opcode & 0x01);
1267
            res = cpu_get_idata(cpu, dir);
1268
            imm = (res & 0x0f0) | (cpu->a & 0x00f);
1269
            cpu_set_a(cpu, ((cpu->a & 0x0f0) | (res & 0x00f)));
1270
            cpu_set_idata(cpu, dir, imm);
1271
        }
1272
        else{
1273
            /* Implemented as NOP */
1274
            cpu->implemented_as_nop = true;
1275
        }
1276
        break;
1277
    case 0xe6:  /* MOV A, @Ri */
1278
    case 0xe7:
1279
        dir = cpu_get_rn(cpu, opcode & 0x01);
1280
        res = cpu_get_idata(cpu, dir);
1281
        cpu_set_a(cpu, res);
1282
        break;
1283
    case 0xf6:  /* MOV @Ri, A */
1284
    case 0xf7:
1285
        dir = cpu_get_rn(cpu, opcode & 0x01);
1286
        cpu_set_idata(cpu, dir, cpu->a);
1287
        break;
1288
    default:    /* unimplemented opcode */
1289
        log_unimplemented(&(cpu->log), opcode);
1290
        ok = false;
1291
    }
1292
 
1293
    if(endless_loop){
1294
        return false;
1295
    }
1296
    else{
1297
        return ok;
1298
    }
1299
}
1300
 
1301
static bool cpu_exec_rn(cpu51_t *cpu, uint8_t opcode){
1302
    uint8_t operation, rn, n, res, dir, imm, rel;
1303
    bool ok = true;
1304
    bool endless_loop = false;
1305
 
1306
    operation = (opcode >> 4) & 0x0f;
1307
    n = opcode & 0x07;
1308
    rn = cpu_get_rn(cpu, n);
1309
 
1310
    switch(operation){
1311
    case 0x00:  /* INC Rn */
1312
        cpu_set_rn(cpu, n, rn+1);
1313
        break;
1314
    case 0x01:  /* DEC Rn */
1315
        cpu_set_rn(cpu, n, rn-1);
1316
        break;
1317
    case 0x02:  /* ADD A,Rn */
1318
        res = cpu_update_flags(cpu, cpu->a, rn, add);
1319
        cpu_set_a(cpu, res);
1320
        break;
1321
    case 0x03:  /* ADDC A,Rn */
1322
        res = cpu_update_flags(cpu, cpu->a, rn, addc);
1323
        cpu_set_a(cpu, res);
1324
        break;
1325
    case 0x04:  /* ORL A, Rn */
1326
        cpu_set_a(cpu, cpu->a | rn);
1327
        break;
1328
    case 0x05:  /* ANL A, Rn */
1329
        cpu_set_a(cpu, cpu->a & rn);
1330
        break;
1331
    case 0x06:  /* XRL A, Rn */
1332
        cpu_set_a(cpu, cpu->a ^ rn);
1333
        break;
1334
    case 0x07:  /* MOV Rn, #data */
1335
        imm = cpu_fetch(cpu);
1336
        cpu_set_rn(cpu, n, imm);
1337
        break;
1338
    case 0x08:  /* MOV dir, Rn */
1339
        dir = cpu_fetch(cpu);
1340
        cpu_set_dir(cpu, dir, rn);
1341
        break;
1342
    case 0x09:  /* SUBB A, Rn */
1343
        res = cpu_update_flags(cpu, cpu->a, rn, subb);
1344
        cpu_set_a(cpu, res);
1345
        break;
1346
    case 0x0a:  /* MOV Rn, dir */
1347
        dir = cpu_fetch(cpu);
1348
        res = cpu_get_dir(cpu, dir);
1349
        cpu_set_rn(cpu, n, res);
1350
        break;
1351
    case 0x0b:  /* CJNE Rn, #data, rel */
1352
        imm = cpu_fetch(cpu);
1353
        rel = cpu_fetch(cpu);
1354
        cpu_update_flags(cpu, rn, imm, cjne);
1355
        if(imm != rn){
1356
            cpu_rel_jump(cpu, rel);
1357
            cpu->max_cycle_count = true;
1358
        }
1359
        break;
1360
    case 0x0c:  /* XCH A, Rn */
1361
        res = cpu->a;
1362
        cpu_set_a(cpu, rn);
1363
        cpu_set_rn(cpu, n, res);
1364
        break;
1365
    case 0x0d:  /* DJNZ Rn, rel */
1366
        rel = cpu_fetch(cpu);
1367
        res = rn - 1;
1368
        cpu_set_rn(cpu, n, res);
1369
        if(res != 0){
1370
            cpu_rel_jump(cpu, rel);
1371
            cpu->max_cycle_count = true;
1372
        }
1373
        break;
1374
    case 0x0e:  /* MOV A, Rn */
1375
        cpu_set_a(cpu, rn);
1376
        break;
1377
    case 0x0f:  /* MOV Rn, A */
1378
        cpu_set_rn(cpu, n, cpu->a);
1379
        break;
1380
    }
1381
 
1382
    if(endless_loop){
1383
        return false;
1384
    }
1385
    else{
1386
        return ok;
1387
    }
1388
}

powered by: WebSVN 2.1.0

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