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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [bochs486/] [main_reader.cpp] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
#include <cstdio>
2
#include <cstdlib>
3
 
4
#include <sys/mman.h>
5
#include <sys/types.h>
6
#include <sys/stat.h>
7
#include <fcntl.h>
8
#include <unistd.h>
9
 
10
#include "bochs.h"
11
#include "cpu.h"
12
#include "iodev/iodev.h"
13
 
14
//------------------------------------------------------------------------------
15
//------------------------------------------------------------------------------
16
//------------------------------------------------------------------------------
17
 
18
typedef unsigned char  uint8;
19
typedef unsigned short uint16;
20
typedef unsigned int   uint32;
21
typedef unsigned long long uint64;
22
 
23
//------------------------------------------------------------------------------
24
//------------------------------------------------------------------------------
25
//------------------------------------------------------------------------------ logfunctions
26
 
27
void logfunctions::panic(const char *fmt, ...) {
28
    printf("#bochs486_reader::logfunctions::panic(): ");
29
 
30
    va_list ap;
31
    va_start(ap, fmt);
32
    vprintf(fmt, ap);
33
    va_end(ap);
34
 
35
    printf("\n");
36
    fflush(stdout);
37
 
38
    if(strstr(fmt, "exception with no resolution") != NULL) {
39
        printf("start_shutdown: 0\n");
40
        printf("\n");
41
        fflush(stdout);
42
        exit(0);
43
    }
44
    else {
45
        exit(-1);
46
    }
47
}
48
void logfunctions::error(const char *fmt, ...) {
49
    printf("#bochs486_reader::logfunctions::error(): ");
50
 
51
    va_list ap;
52
    va_start(ap, fmt);
53
    vprintf(fmt, ap);
54
    va_end(ap);
55
 
56
    printf("\n");
57
    fflush(stdout);
58
}
59
void logfunctions::ldebug(const char *fmt, ...) {
60
    printf("#bochs486_reader::logfunctions::debug(): ");
61
 
62
    va_list ap;
63
    va_start(ap, fmt);
64
    vprintf(fmt, ap);
65
    va_end(ap);
66
 
67
    printf("\n");
68
    fflush(stdout);
69
}
70
void logfunctions::info(const char *fmt, ...) {
71
    printf("#bochs486_reader::logfunctions::info(): ");
72
 
73
    va_list ap;
74
    va_start(ap, fmt);
75
    vprintf(fmt, ap);
76
    va_end(ap);
77
 
78
    printf("\n");
79
    fflush(stdout);
80
}
81
void logfunctions::put(const char *n, const char *p) {
82
}
83
logfunctions::logfunctions() {
84
}
85
logfunctions::~logfunctions() {
86
}
87
 
88
static logfunctions theLog;
89
logfunctions *pluginlog         = &theLog;
90
logfunctions *siminterface_log  = &theLog;
91
 
92
//------------------------------------------------------------------------------
93
//------------------------------------------------------------------------------
94
//------------------------------------------------------------------------------ menu
95
 
96
void bx_param_string_c::text_print(FILE *fp) {
97
printf("#bochs486_reader::bx_param_string_c::text_print()\n");
98
}
99
void bx_param_enum_c::text_print(FILE *fp) {
100
printf("#bochs486_reader::bx_param_enum_c::text_print()\n");
101
}
102
void bx_param_bool_c::text_print(FILE *fp) {
103
printf("#bochs486_reader::bx_param_bool_c::text_print()\n");
104
}
105
void bx_param_num_c::text_print(FILE *fp) {
106
printf("#bochs486_reader::bx_param_num_c::text_print()\n");
107
}
108
void bx_list_c::text_print(FILE *fp) {
109
printf("#bochs486_reader::bx_list_c::text_print()\n");
110
}
111
int bx_param_enum_c::text_ask(FILE *fpin, FILE *fpout) {
112
printf("#bochs486_reader::bx_param_enum_c::text_ask()\n");
113
    return 0;
114
}
115
int bx_param_bool_c::text_ask(FILE *fpin, FILE *fpout) {
116
printf("#bochs486_reader::bx_param_bool_c::text_ask()\n");
117
    return 0;
118
}
119
int bx_param_num_c::text_ask(FILE *fpin, FILE *fpout) {
120
printf("#bochs486_reader::bx_param_num_c::text_ask()\n");
121
    return 0;
122
}
123
int bx_param_string_c::text_ask(FILE *fpin, FILE *fpout) {
124
printf("#bochs486_reader::bx_param_string_c::text_ask()\n");
125
    return 0;
126
}
127
int bx_list_c::text_ask(FILE *fpin, FILE *fpout) {
128
printf("#bochs486_reader::bx_list_c::text_ask()\n");
129
    return 0;
130
}
131
 
132
bx_list_c *root_param = NULL;
133
 
134
bx_gui_c *bx_gui = NULL;
135
 
136
//------------------------------------------------------------------------------
137
//------------------------------------------------------------------------------
138
//------------------------------------------------------------------------------ cpu
139
 
140
void BX_CPU_C::enter_system_management_mode(void) {
141
printf("#bochs486_reader: enter_system_management_mod()\n");
142
}
143
void BX_CPU_C::init_SMRAM(void) {
144
printf("#bochs486_reader: init_SMRAM()\n");
145
}
146
void BX_CPU_C::debug(bx_address offset) {
147
printf("#bochs486_reader: debug(offset=%08x)\n", offset);
148
}
149
void BX_CPU_C::debug_disasm_instruction(bx_address offset) {
150
printf("#bochs486_reader: debug_disasm_instruction(offset=%08x)\n", offset);
151
}
152
 
153
//------------------------------------------------------------------------------
154
//------------------------------------------------------------------------------
155
//------------------------------------------------------------------------------ pc_system
156
 
157
void bx_pc_system_c::countdownEvent(void) {
158
}
159
bx_pc_system_c::bx_pc_system_c() {
160
}
161
int bx_pc_system_c::Reset(unsigned type) {
162
    printf("#bochs486_reader: bx_pc_system_c::Reset(%d) unimplemented.\n", type);
163
    std::exit(-1);
164
}
165
 
166
bx_pc_system_c bx_pc_system;
167
 
168
const char* cpu_mode_string(unsigned cpu_mode) {
169
  static const char *cpu_mode_name[] = {
170
     "real mode",
171
     "v8086 mode",
172
     "protected mode",
173
     "compatibility mode",
174
     "long mode",
175
     "unknown mode"
176
  };
177
 
178
  if(cpu_mode >= 5) cpu_mode = 5;
179
  return cpu_mode_name[cpu_mode];
180
}
181
 
182
const char *choices[] = { "0_choice", NULL };
183
 
184
class bochs486_sim : public bx_simulator_interface_c {
185
 
186
    bx_param_bool_c *get_param_bool(const char *pname, bx_param_c *base) {
187
        if(strcmp(pname, BXPN_CPUID_LIMIT_WINNT) == 0)      return new bx_param_bool_c(  NULL, "b0", "", "", 0);
188
        if(strcmp(pname, BXPN_CPUID_SSE4A) == 0)            return new bx_param_bool_c(  NULL, "b1", "", "", 0);
189
        if(strcmp(pname, BXPN_CPUID_SEP) == 0)              return new bx_param_bool_c(  NULL, "b2", "", "", 0);
190
        if(strcmp(pname, BXPN_CPUID_XSAVE) == 0)            return new bx_param_bool_c(  NULL, "b3", "", "", 0);
191
        if(strcmp(pname, BXPN_CPUID_XSAVEOPT) == 0)         return new bx_param_bool_c(  NULL, "b4", "", "", 0);
192
        if(strcmp(pname, BXPN_CPUID_AES) == 0)              return new bx_param_bool_c(  NULL, "b5", "", "", 0);
193
        if(strcmp(pname, BXPN_CPUID_MOVBE) == 0)            return new bx_param_bool_c(  NULL, "b6", "", "", 0);
194
        if(strcmp(pname, BXPN_CPUID_SMEP) == 0)             return new bx_param_bool_c(  NULL, "b7", "", "", 0);
195
        if(strcmp(pname, BXPN_RESET_ON_TRIPLE_FAULT) == 0)  return new bx_param_bool_c(  NULL, "b8", "", "", 0);
196
        return NULL;
197
    }
198
    bx_param_string_c *get_param_string(const char *pname, bx_param_c *base) {
199
        if(strcmp(pname, BXPN_VENDOR_STRING) == 0) return new bx_param_string_c(NULL, "s0", "", "", "GeniuneAO486");
200
        if(strcmp(pname, BXPN_BRAND_STRING) == 0)  return new bx_param_string_c(NULL, "s1", "", "", "ao486                                           ");
201
        return NULL;
202
    }
203
    bx_param_enum_c *get_param_enum(const char *pname, bx_param_c *base) {
204
        if(strcmp(pname, BXPN_CPU_MODEL) == 0)  return new bx_param_enum_c(  NULL, "e0", "", "", choices, 0);
205
        if(strcmp(pname, BXPN_CPUID_SSE) == 0)  return new bx_param_enum_c(  NULL, "e1", "", "", choices, 0);
206
        return NULL;
207
    }
208
    bx_param_num_c *get_param_num(const char *pname, bx_param_c *base) {
209
        if(strcmp(pname, BXPN_CPUID_STEPPING) == 0)  return new bx_param_num_c(   NULL, "n0", "", "", 0xB,0xB,0xB);
210
        if(strcmp(pname, BXPN_CPUID_MODEL) == 0)     return new bx_param_num_c(   NULL, "n1", "", "", 0x5,0x5,0x5);
211
        if(strcmp(pname, BXPN_CPUID_FAMILY) == 0)    return new bx_param_num_c(   NULL, "n2", "", "", 0x4,0x4,0x4);
212
        if(strcmp(pname, BXPN_CPUID_LEVEL) == 0)     return new bx_param_num_c(   NULL, "n3", "", "", 0x4,0x4,0x4);
213
        return NULL;
214
    }
215
};
216
 
217
//------------------------------------------------------------------------------
218
 
219
FILE *check_fp = NULL;
220
 
221
char check_line[256];
222
char check_next[256];
223
int check_state = 0;
224
/*
225
 
226
1 - EOF is next
227
2 - both full; line will be used
228
*/
229
 
230
uint32 check_next_irq_at = 0;
231
uint32 check_next_irq_vector = 0;
232
 
233
union memory_t {
234
    uint8  bytes [134217728];
235
    uint16 shorts[67108864];
236
    uint32 ints  [33554432];
237
};
238
memory_t check_memory;
239
 
240
uint32 instr_counter = 0;
241
 
242
void load_file(const char *name, int byte_location) {
243
    FILE *fp = fopen(name, "rb");
244
    if(fp == NULL) {
245
        fprintf(stderr, "#bochs486_reader: error opening file: %s\n", name);
246
        exit(-1);
247
    }
248
 
249
    int int_ret = fseek(fp, 0, SEEK_END);
250
    if(int_ret != 0) {
251
        fclose(fp);
252
        fprintf(stderr, "#bochs486_reader: error stat file: %s\n", name);
253
        exit(-1);
254
    }
255
 
256
    long size = ftell(fp);
257
    rewind(fp);
258
 
259
    int_ret = fread((void *)&check_memory.bytes[byte_location], size, 1, fp);
260
    if(int_ret != 1) {
261
        fclose(fp);
262
        fprintf(stderr, "#bochs486_reader: error loading file: %s\n", name);
263
        exit(-1);
264
    }
265
    fclose(fp);
266
}
267
 
268
bool check_read_fp(char *line) {
269
    while(true) {
270
        char *endoffile = fgets(line, 256, check_fp);
271
        if(endoffile == NULL) return false;
272
printf("line: %s\n", line);
273
        uint32 val1 = 0, val2 = 0;
274
        int scan_ret = sscanf(line, "Exception 0x%x at %x", &val1, &val2);
275
        if(scan_ret == 2) {
276
            //ignore
277
            continue;
278
        }
279
 
280
        val1 = val2 = 0;
281
        scan_ret = sscanf(line, "IAC 0x%x at %d", &val1, &val2);
282
        if(scan_ret == 2) {
283
            check_next_irq_vector = val1;
284
            check_next_irq_at     = val2;
285
 
286
            continue;
287
        }
288
        break;
289
    }
290
    return true;
291
}
292
 
293
uint64 total_size = 0;
294
uint64 last_percent = 0;
295
 
296
void check_init() {
297
    if(check_fp == NULL) {
298
        //const char *filename = "./../backup/run-10/track.txt";
299
        const char *filename = "./../ao486/io_win95pipeline_1_bochs.txt";
300
 
301
        check_fp = fopen(filename, "rb");
302
        if(check_fp == NULL) {
303
            fprintf(stderr, "#bochs486_reader: can not open reader file.\n");
304
            exit(-1);
305
        }
306
 
307
        struct stat st;
308
        memset(&st, 0, sizeof(struct stat));
309
        stat(filename, &st);
310
        total_size = st.st_size;
311
        fprintf(stderr, "#bochs486_reader: total file size: %d\n", total_size);
312
    }
313
 
314
    uint64 curr_pos = ftell(check_fp);
315
    uint64 curr_percent = curr_pos * 100 / total_size;
316
    if(curr_percent != last_percent) {
317
        last_percent = curr_percent;
318
        fprintf(stderr, "#bochs486_reader: %d percent\n", (uint32)last_percent);
319
    }
320
 
321
    if(check_state == 0) {
322
        if(check_read_fp(check_line) == false) {
323
            fprintf(stderr, "#bochs486_reader: EOF\n");
324
            exit(0);
325
        }
326
        if(check_read_fp(check_next) == false) {
327
            check_state = 1;
328
            return;
329
        }
330
        check_state = 2;
331
    }
332
    else if(check_state == 1) {
333
        fprintf(stderr, "#bochs486_reader: EOF\n");
334
        exit(0);
335
    }
336
    else if(check_state == 2) {
337
        memcpy(check_line, check_next, 256);
338
 
339
        if(check_read_fp(check_next) == false) {
340
            check_state = 1;
341
            return;
342
        }
343
        check_state = 2;
344
    }
345
}
346
 
347
uint32 check_io_rd(uint32 address, uint32 byteenable) {
348
    check_init();
349
 
350
    uint32 io_addr = 0, io_byteena = 0, io_data = 0;
351
    int scan_ret = sscanf(check_line, "io rd %x %x %x", &io_addr, &io_byteena, &io_data);
352
 
353
    if(scan_ret == 3) {
354
        if(address != io_addr) {
355
            fprintf(stderr, "#check_io_rd MISMATCH:%s != l:%04x %x\n", check_line, address, byteenable);
356
            exit(-1);
357
        }
358
        if(byteenable != io_byteena) {
359
            fprintf(stderr, "#check_io_rd MISMATCH:%s != l:%04x %x\n", check_line, address, byteenable);
360
            exit(-1);
361
        }
362
    }
363
    else {
364
        fprintf(stderr, "#check_io_rd MISMATCH: f:%s != l:%04x %x\n", check_line, address, byteenable);
365
        exit(-1);
366
    }
367
    return io_data;
368
}
369
 
370
void check_io_wr(uint32 address, uint32 byteenable, uint32 data) {
371
    check_init();
372
 
373
    uint32 io_addr = 0, io_byteena = 0, io_data = 0;
374
    int scan_ret = sscanf(check_line, "io wr %x %x %x", &io_addr, &io_byteena, &io_data);
375
 
376
    if(scan_ret == 3) {
377
        if(((byteenable>>0) & 1) == 0) { data &= 0xFFFFFF00; io_data &= 0xFFFFFF00; }
378
        if(((byteenable>>1) & 1) == 0) { data &= 0xFFFF00FF; io_data &= 0xFFFF00FF; }
379
        if(((byteenable>>2) & 1) == 0) { data &= 0xFF00FFFF; io_data &= 0xFF00FFFF; }
380
        if(((byteenable>>3) & 1) == 0) { data &= 0x00FFFFFF; io_data &= 0x00FFFFFF; }
381
 
382
        if(address != io_addr) {
383
            fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
384
            exit(-1);
385
        }
386
        if(byteenable != io_byteena) {
387
            fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
388
            exit(-1);
389
        }
390
        if(data != io_data) {
391
            fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
392
            exit(-1);
393
        }
394
    }
395
    else {
396
        fprintf(stderr, "#check_io_wr MISMATCH:%s | %04x %x %08x\n", check_line, address, byteenable, data);
397
        exit(-1);
398
    }
399
}
400
 
401
void check_mem_wr(uint32 address, uint32 byteenable, uint32 data) {
402
    check_init();
403
 
404
    uint32 mem_addr = 0, mem_byteena = 0, mem_data = 0;
405
    int scan_ret = sscanf(check_line, "mem wr %x %x %x", &mem_addr, &mem_byteena, &mem_data);
406
 
407
    if(scan_ret == 3) {
408
        if(((byteenable>>0) & 1) == 0) { data &= 0xFFFFFF00; mem_data &= 0xFFFFFF00; }
409
        if(((byteenable>>1) & 1) == 0) { data &= 0xFFFF00FF; mem_data &= 0xFFFF00FF; }
410
        if(((byteenable>>2) & 1) == 0) { data &= 0xFF00FFFF; mem_data &= 0xFF00FFFF; }
411
        if(((byteenable>>3) & 1) == 0) { data &= 0x00FFFFFF; mem_data &= 0x00FFFFFF; }
412
 
413
        if(address != mem_addr) {
414
            fprintf(stderr, "#check_mem_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
415
            exit(-1);
416
        }
417
        if(byteenable != mem_byteena) {
418
            fprintf(stderr, "#check_mem_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
419
            exit(-1);
420
        }
421
        if(data != mem_data) {
422
            fprintf(stderr, "#check_mem_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
423
            exit(-1);
424
        }
425
 
426
        for(uint32 i=0; i<4; i++) {
427
            if(byteenable & 1) {
428
                check_memory.bytes[address + i] = data & 0xFF;
429
            }
430
            byteenable >>= 1;
431
            data >>= 8;
432
        }
433
    }
434
    else {
435
        fprintf(stderr, "#check_io_wr MISMATCH:%s != l:%08x %x %08x\n", check_line, address, byteenable, data);
436
        exit(-1);
437
    }
438
}
439
 
440
uint32 check_mem_rd(uint32 address, uint32 byteenable) {
441
    check_init();
442
 
443
    uint32 mem_addr = 0, mem_byteena = 0, mem_data = 0;
444
    int scan_ret = sscanf(check_line, "mem rd %x %x %x", &mem_addr, &mem_byteena, &mem_data);
445
 
446
    if(scan_ret == 3) {
447
        if(address != mem_addr) {
448
            fprintf(stderr, "#check_mem_rd MISMATCH:%s != l:%08x %x\n", check_line, address, byteenable);
449
            exit(-1);
450
        }
451
        if(byteenable != mem_byteena) {
452
            fprintf(stderr, "#check_mem_rd MISMATCH:%s != l:%08x %x\n", check_line, address, byteenable);
453
            exit(-1);
454
        }
455
    }
456
    else {
457
        fprintf(stderr, "#check_mem_rd MISMATCH:%s != l:%04x %x\n", check_line, address, byteenable);
458
        exit(-1);
459
    }
460
    return mem_data;
461
}
462
 
463
//------------------------------------------------------------------------------
464
 
465
bx_simulator_interface_c *SIM;
466
 
467
BOCHSAPI BX_CPU_C bx_cpu;
468
int interrupt_vector;
469
 
470
//------------------------------------------------------------------------------
471
//------------------------------------------------------------------------------
472
//------------------------------------------------------------------------------ devices
473
 
474
class bochs486_pic : public bx_pic_stub_c {
475
    Bit8u IAC(void) { bx_cpu.clear_INTR(); return interrupt_vector & 0xFF; }
476
};
477
 
478
int is_io_ignored(Bit16u address, Bit32u byteena) {
479
 
480
    bool read_ff =
481
            (address >= 0x0010 && address < 0x0020)     ||
482
            (address == 0x0020 && (byteena & 0x3) == 0) ||
483
            (address >= 0x0024 &&  address < 0x0040)    ||
484
            (address >= 0x0044 &&  address < 0x0060)    ||
485
            (address >= 0x0068 &&  address < 0x0070)    ||
486
            (address == 0x0070 && (byteena & 0x3) == 0) ||
487
            (address >= 0x0074 &&  address < 0x0080)    ||
488
            (address == 0x00A0 && (byteena & 0x3) == 0) ||
489
            (address >= 0x00A4 &&  address < 0x00C0)    ||
490
            (address >= 0x00E0 &&  address < 0x01F0)    ||
491
            (address >= 0x01F8 &&  address < 0x0220)    ||
492
            (address >= 0x0230 &&  address < 0x0388)    ||
493
            (address == 0x0388 && (byteena & 0x3) == 0) ||
494
            (address >= 0x038C &&  address < 0x03B0)    ||
495
            (address >= 0x03E0 &&  address < 0x03F0)    ||
496
            (address >= 0x03F8 &&  address < 0x8888)    ||
497
            (address >= 0x8890);
498
 
499
    bool read_ff_part =
500
            (address == 0x0020) ||
501
            (address == 0x0070) ||
502
            (address == 0x00A0) ||
503
            (address == 0x0388);
504
 
505
    if(read_ff)         return 1;
506
    if(read_ff_part)    return 2;
507
    return 0;
508
}
509
 
510
  Bit32u BX_CPP_AttrRegparmN(2)
511
bx_devices_c::inp(Bit16u addr, unsigned io_len) {
512
//printf("#bochs486_pc:inp(%04x, %d)\n", addr, io_len);
513
    // read aligned to 4 bytes, with byteena
514
 
515
    bool two_reads = (addr & 0x3) + io_len > 4;
516
 
517
    Bit16u   addr1    = addr & 0xFFFC;
518
    unsigned byteena1 = (io_len == 1)? 0x1 : (io_len == 2)? 0x3 : (io_len == 3)? 0x7 : 0xF;
519
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
520
 
521
    Bit16u   addr2    = (addr + 4) & 0xFFFC;
522
    unsigned byteena2 = (byteena1 >> 4) & 0xF;
523
 
524
    //-------------------------------------------------------------------------- first read
525
    int int_ret = is_io_ignored(addr1, byteena1 & 0xF);
526
    unsigned int data1 = 0xFFFFFFFF;
527
 
528
    if(int_ret == 0 || int_ret == 2) {
529
        data1 = ((int_ret == 2)? 0xFFFF0000 : 0x00000000) | check_io_rd(addr1, byteena1 & 0xF);
530
    }
531
    //-------------------------------------------------------------------------- second read
532
    unsigned long long data = data1;
533
//printf("#bochs486_pc:inp() read_one %d\n", two_reads);
534
    if(two_reads) {
535
        int_ret = is_io_ignored(addr2, byteena2 & 0xF);
536
        unsigned int data2 = 0xFFFFFFFF;
537
 
538
        if(int_ret == 0 || int_ret == 2) {
539
            data2 = ((int_ret == 2)? 0xFFFF0000 : 0x00000000) | check_io_rd(addr2, byteena2 & 0xF);
540
        }
541
        data = ((unsigned long long)data2 << 32) | data1;
542
    }
543
 
544
    while((byteena1 & 1) == 0) {
545
        byteena1 >>= 1;
546
        data >>= 8;
547
    }
548
    Bit32u ret_val = (io_len == 1)? (data & 0xFFL) : (io_len == 2)? (data & 0xFFFFL) : (io_len == 3)? (data & 0xFFFFFFL) : (data & 0xFFFFFFFFL);
549
printf("#bochs486_pc:inp(%04x, %d, =%08x)\n", addr, io_len, ret_val);
550
    return ret_val;
551
}
552
 
553
  void BX_CPP_AttrRegparmN(3)
554
bx_devices_c::outp(Bit16u addr, Bit32u value, unsigned io_len) {
555
printf("#bochs486_pc:outp(%04x, %d, %08x)\n", addr, io_len, value);
556
    // write aligned to 4 bytes, with byteena
557
 
558
    bool two_writes = (addr & 0x3) + io_len > 4;
559
 
560
    Bit16u   addr1    = addr & 0xFFFC;
561
    unsigned byteena1 = (io_len == 1)? 0x1 : (io_len == 2)? 0x3 : (io_len == 3)? 0x7 : 0xF;
562
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
563
 
564
    Bit16u   addr2    = (addr + 4) & 0xFFFC;
565
    unsigned byteena2 = (byteena1 >> 4) & 0xF;
566
 
567
    if(io_len == 1) value &= 0x000000FF;
568
    if(io_len == 2) value &= 0x0000FFFF;
569
    if(io_len == 3) value &= 0x00FFFFFF;
570
 
571
    Bit64u value_full = ((addr & 0x3) == 0)? (Bit64u)value : ((addr & 0x3) == 1)? ((Bit64u)value << 8) : ((addr & 0x3) == 2)? ((Bit64u)value << 16) : ((Bit64u)value << 24);
572
    Bit32u value1 = value_full;
573
    Bit32u value2   = (value_full >> 32);
574
 
575
    //-------------------------------------------------------------------------- first write
576
    int int_ret = is_io_ignored(addr1, byteena1 & 0xF);
577
 
578
    if(int_ret == 0 || int_ret == 2) {
579
        check_io_wr(addr1, byteena1 & 0xF, value1);
580
    }
581
//printf("#bochs486_pc:outp() write_one %d\n", two_writes);
582
    //-------------------------------------------------------------------------- second write
583
 
584
    if(two_writes) {
585
        int_ret = is_io_ignored(addr2, byteena2 & 0xF);
586
 
587
        if(int_ret == 0 || int_ret == 2) {
588
            check_io_wr(addr2, byteena2 & 0xF, value2);
589
        }
590
    }
591
//printf("#bochs486_pc:outp() write_two\n");
592
}
593
 
594
bx_devices_c::bx_devices_c() {
595
    pluginPicDevice = new bochs486_pic();
596
}
597
 
598
bx_devices_c::~bx_devices_c() {
599
}
600
 
601
bx_devices_c bx_devices;
602
 
603
//------------------------------------------------------------------------------
604
//------------------------------------------------------------------------------
605
//------------------------------------------------------------------------------ memory
606
 
607
void BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {
608
printf("#bochs486_reader: writePhysicalPage: addr=%08x, len=%d ", addr, len);
609
for(unsigned i=0; i<len; i++) printf("%02x ", ((uint8 *)data)[i]); printf("\n");
610
 
611
    addr &= 0x07FFFFFF;
612
 
613
    if(len > 4) {
614
        printf("#bochs486_pc: writePhysicalPage() with len = %d\n", len);
615
        exit(-1);
616
    }
617
 
618
    bool two_writes = (addr & 0x3) + len > 4;
619
 
620
    Bit32u   addr1    = addr & 0xFFFFFFFC;
621
    unsigned byteena1 = (len == 1)? 0x1 : (len == 2)? 0x3 : (len == 3)? 0x7 : 0xF;
622
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
623
 
624
    Bit32u   addr2    = (addr + 4) & 0xFFFFFFFC;
625
    unsigned byteena2 = (byteena1 >> 4) & 0xF;
626
 
627
    Bit32u value = ((unsigned int *)data)[0];
628
    if(len == 1) value &= 0x000000FF;
629
    if(len == 2) value &= 0x0000FFFF;
630
    if(len == 3) value &= 0x00FFFFFF;
631
 
632
    Bit64u value_full = ((addr & 0x3) == 0)? (Bit64u)value : ((addr & 0x3) == 1)? ((Bit64u)value << 8) : ((addr & 0x3) == 2)? ((Bit64u)value << 16) : ((Bit64u)value << 24);
633
    Bit32u value1 = value_full;
634
    Bit32u value2   = (value_full >> 32);
635
 
636
    //-------------------------------------------------------------------------- first write
637
    check_mem_wr(addr1, byteena1 & 0xF, value1);
638
 
639
//printf("#bochs486_pc: writePhysicalPage: write_one, %d\n", two_writes);
640
    if(two_writes) {
641
        //---------------------------------------------------------------------- second write
642
        check_mem_wr(addr2, byteena2 & 0xF, value2);
643
    }
644
//printf("#bochs486_pc: writePhysicalPage: write_two\n");
645
}
646
 
647
void BX_MEM_C::readPhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {
648
printf("#bochs486_pc: readPhysicalPage: addr=%08x, len=%d\n", addr, len);
649
 
650
        if(addr >= 0xFFFFF000) addr &= 0x000FFFFF;
651
        addr &= 0x07FFFFFF;
652
 
653
    if(len == 4096) {
654
        if((addr & 3) != 0) {
655
            printf("#bochs486_pc: readPhysicalPage() with len = 4096 and addr not aligned to 4.\n");
656
            exit(-1);
657
        }
658
 
659
        if(addr >= 0xA0000 && addr <= 0xBFFFF) {
660
            printf("#bochs486_pc: readPhysicalPage() with len = 4096 and addr in vga buffer.\n");
661
            fflush(stdout);
662
            exit(-1);
663
        }
664
 
665
        memcpy((unsigned char *)data, (void *)(check_memory.bytes + addr), len);
666
        return;
667
    }
668
 
669
    //check if read crosses line boundry (16 bytes)
670
    if( ((addr) & 0xFFFFFFF0) != ((addr + len - 1) & 0xFFFFFFF0) ) {
671
        unsigned char *ptr = (unsigned char*)data;
672
        readPhysicalPage(cpu, addr,             (addr | 0xF) - addr + 1,       ptr);
673
        readPhysicalPage(cpu, (addr | 0xF) + 1, len - (addr | 0xF) + addr - 1, ptr + ((addr | 0xF) - addr + 1));
674
        return;
675
    }
676
 
677
    if(addr < 0xA0000 || addr > 0xBFFFF) {
678
        memcpy((unsigned char *)data, (void *)(check_memory.bytes + addr), len);
679
uint32 *val = (uint32 *)data;
680
printf("read: %08x %08x\n", val[0], (len > 4)? val[1] : 0);
681
        return;
682
    }
683
//printf("#bochs486_pc: readPhysicalPage: vga read.\n");    
684
    bool two_reads   = ((addr & 0x3) + len > 4) && ((addr & 0x3) + len <= 8);
685
    bool three_reads = ((addr & 0x3) + len > 8);
686
 
687
    Bit32u   addr1    = addr & 0xFFFFFFFC;
688
    unsigned byteena1 = (len == 1)? 0x1 : (len == 2)? 0x3 : (len == 3)? 0x7 : 0xF;
689
    byteena1 = ((addr & 0x3) == 0)? byteena1 : ((addr & 0x3) == 1)? byteena1 << 1 : ((addr & 0x3) == 2)? byteena1 << 2 : byteena1 << 3;
690
 
691
    Bit32u   addr2    = (addr + 4) & 0xFFFFFFFC;
692
    Bit32u   addr3    = (addr + 8) & 0xFFFFFFFC;
693
 
694
    if(two_reads || three_reads) byteena1 = 0xF;
695
    byteena1 &= 0xF;
696
 
697
    //-------------------------------------------------------------------------- first read
698
    unsigned int data_read[3] = { 0,0,0 };
699
 
700
    data_read[0] = check_mem_rd(addr1, byteena1 & 0xF);
701
 
702
    if(two_reads || three_reads) {
703
        //---------------------------------------------------------------------- second read
704
        data_read[1] = check_mem_rd(addr2, 0xF);
705
 
706
        if(three_reads) {
707
            //------------------------------------------------------------------ third read
708
            data_read[2] = check_mem_rd(addr3, 0xF);
709
        }
710
    }
711
 
712
    unsigned char *ptr = (unsigned char *)data_read;
713
 
714
    for(int i=0; i<(addr & 0x3); i++) ptr++;
715
 
716
    memcpy((unsigned char *)data, ptr, len);
717
}
718
 
719
Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw) {
720
//printf("#bochs486_pc: getHostMemAddr: addr=%08x, rw=%d\n", addr, rw);
721
 
722
    if(addr >= 0xA0000 && addr < 0xC0000) return NULL;
723
    if(rw != BX_EXECUTE) return NULL;
724
 
725
    if(addr >= 0xFFFFF000) addr &= 0x000FFFFF;
726
    addr &= 0x07FFFFFF;
727
 
728
    return (Bit8u *)(check_memory.bytes + addr);
729
}
730
BX_MEM_C::BX_MEM_C() {
731
}
732
BX_MEM_C::~BX_MEM_C() {
733
}
734
 
735
BOCHSAPI BX_MEM_C bx_mem;
736
 
737
//------------------------------------------------------------------------------
738
//------------------------------------------------------------------------------
739
//------------------------------------------------------------------------------ interrupt
740
 
741
void print_segment(bx_segment_reg_t *seg, const char *prefix) {
742
 
743
    printf("%s: %04x ",    prefix, seg->selector.value);
744
    printf("val: %01x ",   seg->cache.valid & 1);
745
    printf("rpl: %01hhx ", seg->selector.rpl);
746
    printf("base: %08x ",  seg->cache.u.segment.base);
747
    printf("limit: %08x ", (seg->cache.u.segment.g)? seg->cache.u.segment.limit_scaled >> 12 : seg->cache.u.segment.limit_scaled);
748
    printf("g: %01x ",     seg->cache.u.segment.g);
749
    printf("d_b: %01x ",   seg->cache.u.segment.d_b);
750
    printf("avl: %01x ",   seg->cache.u.segment.avl);
751
    printf("p: %01x ",     seg->cache.p);
752
    printf("dpl: %01x ",   seg->cache.dpl);
753
    printf("s: %01x ",     seg->cache.segment);
754
    printf("type: %01x\n", seg->cache.type);
755
}
756
 
757
void output_cpu_state() {
758
    printf("eax: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EAX));
759
    printf("ebx: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EBX));
760
    printf("ecx: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_ECX));
761
    printf("edx: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EDX));
762
    printf("esi: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_ESI));
763
    printf("edi: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EDI));
764
    printf("ebp: %08x ", bx_cpu.get_reg32(BX_32BIT_REG_EBP));
765
    printf("esp: %08x\n", bx_cpu.get_reg32(BX_32BIT_REG_ESP));
766
 
767
    printf("eip: %08x\n", bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx);
768
 
769
    printf("cflag:  %01x ", bx_cpu.getB_CF());
770
    printf("pflag:  %01x ", bx_cpu.getB_PF());
771
    printf("aflag:  %01x ", bx_cpu.getB_AF());
772
    printf("zflag:  %01x ", bx_cpu.getB_ZF());
773
    printf("sflag:  %01x ", bx_cpu.getB_SF());
774
    printf("tflag:  %01x ", bx_cpu.getB_TF()&1);
775
    printf("iflag:  %01x ", bx_cpu.getB_IF()&1);
776
    printf("dflag:  %01x ", bx_cpu.getB_DF()&1);
777
    printf("oflag:  %01x ", bx_cpu.getB_OF()&1);
778
    printf("iopl:   %01x ", bx_cpu.get_IOPL()&3);
779
    printf("ntflag: %01x ", bx_cpu.getB_NT()&1);
780
    printf("rflag:  %01x ", bx_cpu.getB_RF()&1);
781
    printf("vmflag: %01x ", bx_cpu.getB_VM()&1);
782
    printf("acflag: %01x ", bx_cpu.getB_AC()&1);
783
    printf("idflag: %01x\n", bx_cpu.getB_ID()&1);
784
 
785
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_CS]), "cs");
786
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_DS]), "ds");
787
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_ES]), "es");
788
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_FS]), "fs");
789
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_GS]), "gs");
790
    print_segment(&(bx_cpu.sregs[BX_SEG_REG_SS]), "ss");
791
    print_segment(&(bx_cpu.ldtr), "ldtr");
792
    print_segment(&(bx_cpu.tr),   "tr");
793
 
794
    printf("gdtr_base:  %08x ", bx_cpu.gdtr.base);
795
    printf("gdtr_limit: %02x\n", bx_cpu.gdtr.limit & 0xFFFF);
796
 
797
    printf("idtr_base:  %08x ", bx_cpu.idtr.base);
798
    printf("idtr_limit: %02x\n", bx_cpu.idtr.limit & 0xFFFF);
799
 
800
    printf("cr0_pe: %01x ", bx_cpu.cr0.get_PE() & 1);
801
    printf("cr0_mp: %01x ", bx_cpu.cr0.get_MP() & 1);
802
    printf("cr0_em: %01x ", bx_cpu.cr0.get_EM() & 1);
803
    printf("cr0_ts: %01x ", bx_cpu.cr0.get_TS() & 1);
804
    printf("cr0_ne: %01x ", bx_cpu.cr0.get_NE() & 1);
805
    printf("cr0_wp: %01x ", bx_cpu.cr0.get_WP() & 1);
806
    printf("cr0_am: %01x ", bx_cpu.cr0.get_AM() & 1);
807
    printf("cr0_nw: %01x ", bx_cpu.cr0.get_NW() & 1);
808
    printf("cr0_cd: %01x ", bx_cpu.cr0.get_CD() & 1);
809
    printf("cr0_pg: %01x\n", bx_cpu.cr0.get_PG() & 1);
810
 
811
    printf("cr2: %08x ", bx_cpu.cr2);
812
    printf("cr3: %08x\n", bx_cpu.cr3);
813
 
814
    printf("dr0: %08x ", bx_cpu.dr[0]);
815
    printf("dr1: %08x ", bx_cpu.dr[1]);
816
    printf("dr2: %08x ", bx_cpu.dr[2]);
817
    printf("dr3: %08x ", bx_cpu.dr[3]);
818
 
819
    printf("dr6: %08x ", bx_cpu.dr6.val32);
820
    printf("dr7: %08x\n", bx_cpu.dr7.val32);
821
 
822
    fflush(stdout);
823
}
824
 
825
uint32 seg_word_1(bx_segment_reg_t *seg) {
826
    return  (seg->cache.u.segment.base & 0xFF000000) |
827
            (seg->cache.u.segment.g?   0x00800000 : 0x00) |
828
            (seg->cache.u.segment.d_b? 0x00400000 : 0x00) |
829
            (seg->cache.u.segment.avl? 0x00100000 : 0x00) |
830
            (((seg->cache.u.segment.limit_scaled >> (seg->cache.u.segment.g? 12 : 0)) << 16) & 0xF) |
831
            (seg->cache.p?   0x00008000 : 0x0) |
832
            ((seg->cache.dpl & 0x3) << 13) |
833
            ((seg->cache.segment & 0x1) << 12) |
834
            ((seg->cache.type & 0xF) << 8) |
835
            ((seg->cache.u.segment.base >> 16) & 0xFF);
836
}
837
 
838
uint32 seg_word_2(bx_segment_reg_t *seg) {
839
    return ((seg->cache.u.segment.base & 0xFFFF) << 16) |
840
           ((seg->cache.u.segment.limit_scaled >> (seg->cache.u.segment.g? 12 : 0)) & 0xFFFF);
841
}
842
 
843
//------------------------------------------------------------------------------
844
//------------------------------------------------------------------------------
845
//------------------------------------------------------------------------------ instrument
846
 
847
bool bochs486_skip_rep_finish = false;
848
 
849
 
850
void bx_instr_init_env(void) { }
851
void bx_instr_exit_env(void) { }
852
 
853
void bx_instr_debug_promt() { }
854
void bx_instr_debug_cmd(const char *cmd) { }
855
 
856
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip) { }
857
void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip) { }
858
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip) { }
859
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip) { }
860
 
861
void bx_instr_opcode(unsigned cpu, bxInstruction_c *i, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64) { }
862
 
863
void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code) { }
864
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) { }
865
 
866
void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3) { }
867
void bx_instr_cache_cntrl(unsigned cpu, unsigned what) { }
868
void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset) { }
869
void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr) { }
870
 
871
void bx_instr_initialize(unsigned cpu) { }
872
void bx_instr_exit(unsigned cpu) { }
873
void bx_instr_reset(unsigned cpu, unsigned type) { }
874
 
875
void bx_instr_inp(Bit16u addr, unsigned len) { }
876
void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val) { }
877
void bx_instr_outp(Bit16u addr, unsigned len, unsigned val) { }
878
 
879
void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw) { }
880
void bx_instr_phy_access(unsigned cpu, bx_address phy, unsigned len, unsigned rw) { }
881
 
882
void bx_instr_wrmsr(unsigned cpu, unsigned addr, Bit64u value) { }
883
 
884
 
885
//uint32 check_next_irq_at = 0;
886
//uint32 check_next_irq_vector = 0;
887
 
888
bool intr_pending = false;
889
bool double_exception = false;
890
 
891
void bx_instr_interrupt(unsigned cpu, unsigned vector, unsigned type, bx_bool push_error, Bit16u error_code) {
892
 
893
    bochs486_skip_rep_finish = false;
894
    if(type == BX_EXTERNAL_INTERRUPT) intr_pending = false;
895
 
896
    if(type == BX_HARDWARE_EXCEPTION || type == BX_EXTERNAL_INTERRUPT) {
897
        printf("bx_instr_interrupt(%d): %02x at %d\n", type, vector, instr_counter);
898
        if(double_exception == false) instr_counter++;
899
        else {
900
            fprintf(stderr, "double exception: type: %d\n", type);
901
        }
902
        double_exception = true;
903
 
904
        if(instr_counter == check_next_irq_at) {
905
            interrupt_vector = check_next_irq_vector;
906
printf("raise_INTR(): %02x at %d\n", interrupt_vector, instr_counter);
907
            bx_cpu.raise_INTR();
908
            intr_pending = true;
909
        }
910
        else if(intr_pending && check_next_irq_at == 0) {
911
printf("clear_INTR() at %d\n", instr_counter);
912
            bx_cpu.clear_INTR();
913
            intr_pending = false;
914
        }
915
    }
916
}
917
 
918
void instr_after_execution() {
919
 
920
    instr_counter++;
921
 
922
bx_cpu.TLB_flush();
923
 
924
    if(instr_counter > 0) {
925
        output_cpu_state();
926
    }
927
//if(instr_counter > 11491275) exit(0);
928
 
929
    if(instr_counter == check_next_irq_at) {
930
        interrupt_vector = check_next_irq_vector;
931
printf("raise_INTR(): %02x at %d\n", interrupt_vector, instr_counter);
932
        bx_cpu.raise_INTR();
933
        intr_pending = true;
934
    }
935
    else if(intr_pending && check_next_irq_at == 0) {
936
printf("clear_INTR() at %d\n", instr_counter);
937
        bx_cpu.clear_INTR();
938
        intr_pending = false;
939
    }
940
 
941
}
942
 
943
void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i) {
944
    double_exception = false;
945
//printf("cs: %04x eip: %08x len: %d op: %02x\n", bx_cpu.sregs[BX_SEG_REG_CS].selector.value, bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx, i->ilen(), i->bochs486_opcode);
946
 
947
}
948
 
949
void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i) {
950
//printf("AFT cs: %04x eip: %08x len: %d op: %02x\n", bx_cpu.sregs[BX_SEG_REG_CS].selector.value, bx_cpu.gen_reg[BX_32BIT_REG_EIP].dword.erx, i->ilen(), i->bochs486_opcode);    
951
 
952
    if(bochs486_skip_rep_finish) {
953
        printf("#bx_instr_after_execution: bochs486_skip_rep_finished at %d\n", instr_counter);
954
        bochs486_skip_rep_finish = false;
955
        return;
956
    }
957
 
958
printf("#instr: %02x %d\n", i->bochs486_opcode, instr_counter);
959
    instr_after_execution();
960
}
961
void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i) {
962
    bochs486_skip_rep_finish = true;
963
 
964
printf("#repeat: %d\n", instr_counter);
965
    instr_after_execution();
966
}
967
void bx_instr_hlt(unsigned cpu) {
968
    instr_after_execution();
969
}
970
 
971
void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags) { }
972
 
973
// memory trace callbacks from CPU, len=1,2,4 or 8
974
void bx_dbg_lin_memory_access(unsigned cpu, bx_address lin, bx_phy_address phy, unsigned len, unsigned pl, unsigned rw, Bit8u *data) {
975
}
976
void bx_dbg_phy_memory_access(unsigned cpu, bx_phy_address phy, unsigned len, unsigned rw, unsigned attr, Bit8u *data) {
977
}
978
 
979
//------------------------------------------------------------------------------
980
//------------------------------------------------------------------------------
981
//------------------------------------------------------------------------------ main
982
 
983
int main(int argc, char **argv) {
984
 
985
    load_file("./../sd/bios/bochs_legacy",    0xF0000);
986
    load_file("./../sd/vgabios/vgabios_lgpl", 0xC0000);
987
 
988
    bx_pc_system.a20_mask = 0xFFFFFFFF;
989
 
990
    SIM = new bochs486_sim();
991
 
992
    bx_cpu.initialize();
993
    bx_cpu.reset(BX_RESET_HARDWARE);
994
 
995
    printf("START\n");
996
    bx_cpu.gen_reg[BX_32BIT_REG_EDX].dword.erx = 0x0000045b; //after reset EDX value
997
    instr_counter++; //ao486 has extra instruction at 0xFFFFFFF0
998
 
999
    bx_cpu.async_event = 0;
1000
    bx_cpu.handleCpuModeChange();
1001
 
1002
    bx_cpu.cpu_loop();
1003
 
1004
    printf("#bochs486_pc: finishing.\n");
1005
 
1006
    return 0;
1007
}

powered by: WebSVN 2.1.0

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