Changeset 1639

Show
Ignore:
Timestamp:
06/29/08 14:36:13 (2 months ago)
Author:
common
Message:

libemu

  • basic big endian support
    • main problem is unaligned memory access leading to SIGBUS
      • imm16 is unaligned by default. all operations using imm16 have/had to be sanatized
      • emu_memory access, reading/writing dwords and words requires inverting the byte order on big endian
      • emu_memory has use bcopy to create aligned copies of vars
      • emu_memory has to use bcopy instead of memcpy to access the memory, as memcpy sigbusses on unaligned memory
      • the INSTR_CALC macro's have to use aligned copies of the values, I ported the required macros for sctest and instrtest, a some are left 'todo'
      • instrtest uses nasm to create binary code from asm, nasm does not work correctly on sparc64, therefore the binary data for the test which failed on sparc64 due to nasm failure got added
  • adc instr_group_1_83_adc used imm16 for 'ADC r/m16,imm8' instead of imm8, fixed
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • libemu/trunk/include/emu/emu_cpu_data.h

    r1437 r1639  
    126126 
    127127#if !defined(INSTR_CALC) 
     128#if BYTE_ORDER == BIG_ENDIAN  
     129#define INSTR_CALC(bits, a, b, c, operation)                    \ 
     130UINT(bits) operand_a; \ 
     131UINT(bits) operand_b; \ 
     132bcopy(&(a), &operand_a, bits/8); \ 
     133bcopy(&(b), &operand_b, bits/8); \ 
     134UINT(bits) operation_result = operand_a operation operand_b;    \ 
     135bcopy(&operation_result, &(c), bits/8);  
     136#else // ENDIAN 
    128137#define INSTR_CALC(bits, a, b, c, operation)                    \ 
    129138UINT(bits) operand_a = a;                                                               \ 
     
    131140UINT(bits) operation_result = operand_a operation operand_b;    \ 
    132141c = operation_result; 
     142#endif // ENDIAN 
    133143#endif // INSTR_CALC 
    134144 
  • libemu/trunk/include/emu/emu_cpu_stack.h

    r1317 r1639  
    3131#define PUSH_DWORD(cpu, arg)                                                    \ 
    3232{                                                                                                               \ 
    33         uint32_t pushme = arg;                                                          \ 
     33        uint32_t pushme;                                                                        \ 
     34        bcopy(&(arg),  &pushme, 4);                                                     \ 
    3435        if (cpu->reg[esp] < 4)                                                          \ 
    3536        {                                                                                                       \ 
     
    5051#define PUSH_WORD(cpu, arg)                                                             \ 
    5152{                                                                                                               \ 
    52         uint16_t pushme  = arg;                                                         \ 
     53        uint16_t pushme;                                                                        \ 
     54        bcopy(&(arg),  &pushme, 2);                                                     \ 
    5355        if (cpu->reg[esp] < 2)                                                          \ 
    5456        {                                                                                                       \ 
  • libemu/trunk/include/emu/emu_memory.h

    r1317 r1639  
    8888 
    8989#define MEM_WORD_WRITE(cpu_p, addr, data) \ 
    90  { int32_t ret = emu_memory_write_word((cpu_p)->mem, addr, data); \ 
     90 { uint16_t val; \ 
     91 bcopy(&(data), &val, 2); \ 
     92 int32_t ret = emu_memory_write_word((cpu_p)->mem, addr, val); \ 
    9193 if( ret != 0 ) \ 
    9294  return ret; } 
     
    98100 
    99101#define MEM_DWORD_WRITE(cpu_p, addr, data) \ 
    100  { int32_t ret = emu_memory_write_dword((cpu_p)->mem, addr, data); \ 
     102 { uint32_t val; \ 
     103 bcopy(&(data), &val, 4); \ 
     104 int32_t ret = emu_memory_write_dword((cpu_p)->mem, addr, val); \ 
    101105 if( ret != 0 ) \ 
    102106  return ret; } 
  • libemu/trunk/src/emu_cpu.c

    r1437 r1639  
    846846                        { 
    847847                                /* fnstenv volume 1, page 230 */ 
    848                                 MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x00, 0); 
    849                                 MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x04, 0); 
    850                                 MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x08, 0); 
     848                                static int null = 0; 
     849                                MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x00, null); 
     850                                MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x04, null); 
     851                                MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x08, null); 
    851852                                MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x0c, c->last_fpu_instr[1]); 
    852                                 MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x10, 0); 
    853                                 MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x14, 0); 
    854                                 MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x18, 0); 
     853                                MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x10, null); 
     854                                MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x14, null); 
     855                                MEM_DWORD_WRITE(c, c->instr.fpu.ea + 0x18, null); 
    855856 
    856857                                TRACK_NEED_FPU(c->instr, TRACK_FPU_LAST_INSTRUCTION); 
  • libemu/trunk/src/emu_memory.c

    r1317 r1639  
    276276int32_t emu_memory_read_word(struct emu_memory *m, uint32_t addr, uint16_t *word) 
    277277{ 
     278#if BYTE_ORDER == BIG_ENDIAN 
     279        uint16_t val; 
     280        int32_t retval = emu_memory_read_block(m, addr, &val, 2); 
     281        val =  ((val & 0xff00) >> 8) |  
     282                   ((val & 0x00ff) << 8); 
     283        bcopy(&val,word,2); 
     284        return retval; 
     285#else 
    278286        return emu_memory_read_block(m, addr, word, 2); 
     287#endif 
    279288} 
    280289 
    281290int32_t emu_memory_read_dword(struct emu_memory *m, uint32_t addr, uint32_t *dword) 
    282291{ 
     292#if BYTE_ORDER == BIG_ENDIAN 
     293        uint32_t val; 
     294        int32_t retval =  emu_memory_read_block(m, addr, &val, 4); 
     295        val =  ((val & (0xff000000)) >> 24) |  
     296                   ((val & (0x00ff0000)) >> 8)  |  
     297                   ((val & (0x0000ff00)) << 8) |  
     298                   ((val & (0x000000ff)) << 24); 
     299        memcpy(dword, &val, 4); 
     300        return retval; 
     301#else 
    283302        return emu_memory_read_block(m, addr, dword, 4); 
     303#endif 
    284304} 
    285305 
     
    300320        if (OFFSET(addr) + len <= PAGE_SIZE) 
    301321        { 
    302                 memcpy(dest, address, len); 
     322                bcopy(address, dest, len); 
    303323                return 0; 
    304324        } 
     
    306326        { 
    307327                uint32_t cb = PAGE_SIZE - OFFSET(addr); 
    308                 memcpy(dest, address, cb); 
     328                bcopy(address, dest, cb); 
    309329                return emu_memory_read_block(m, oaddr + cb, dest + cb, len - cb); 
    310330        } 
     
    369389                return 0; 
    370390 
     391#if BYTE_ORDER == BIG_ENDIAN 
     392        uint16_t val; 
     393        bcopy(&word, &val, 2); 
     394        val = ((val & 0xff00) >> 8) |  
     395                  ((val & 0x00ff) << 8); 
     396        return emu_memory_write_block(m, addr, &val, 2); 
     397#else 
    371398        return emu_memory_write_block(m, addr, &word, 2); 
     399#endif 
    372400} 
    373401 
     
    377405                return 0; 
    378406 
     407#if BYTE_ORDER == BIG_ENDIAN 
     408        uint32_t val; 
     409        bcopy(&dword, &val, 4); 
     410        val = ((val & (0xff000000)) >> 24) | 
     411                  ((val & (0x00ff0000)) >> 8)  | 
     412                  ((val & (0x0000ff00)) << 8)  | 
     413                  ((val & (0x000000ff)) << 24); 
     414        return emu_memory_write_block(m, addr, &val, 4); 
     415#else 
    379416        return emu_memory_write_block(m, addr, &dword, 4); 
     417#endif 
    380418} 
    381419 
     
    400438        if (OFFSET(addr) + len <= PAGE_SIZE) 
    401439        { 
    402                 memcpy(address, src, len); 
     440                bcopy(src, address, len); 
    403441                return 0; 
    404442        } 
     
    406444        { 
    407445                uint32_t cb = PAGE_SIZE - OFFSET(addr); 
    408                 memcpy(address, src, cb); 
     446                bcopy(src, address, cb); 
    409447                return emu_memory_write_block(m, oaddr + cb, src + cb, len - cb); 
    410448        } 
  • libemu/trunk/src/functions/adc.c

    r1317 r1639  
    2929#include <stdio.h> 
    3030 
     31 
     32#if BYTE_ORDER == BIG_ENDIAN  
     33#define INSTR_CALC(bits, a, b, c, operation, cpu)                       \ 
     34UINT(bits) operand_a; \ 
     35UINT(bits) operand_b; \ 
     36bcopy(&(a), &operand_a, bits/8); \ 
     37bcopy(&(b), &operand_b, bits/8); \ 
     38UINT(bits) operation_result = operand_a operation operand_b operation ((cpu->eflags & (1 << f_cf))?1:0);        \ 
     39bcopy(&operation_result, &(c), bits/8);  
     40#else // ENDIAN 
    3141#define INSTR_CALC(bits, a, b, c, operation, cpu)                       \ 
    3242UINT(bits) operand_a = a;                                                               \ 
     
    3444UINT(bits) operation_result = operand_a operation operand_b operation ((cpu->eflags & (1 << f_cf))?1:0);        \ 
    3545c = operation_result; 
     46#endif // ENDIAN 
     47 
    3648 
    3749#define INSTR_SET_FLAG_OF(cpu, operand,bits)                                                                                    \ 
     
    546558                         * ADC r/m16,imm8   
    547559                         */ 
    548                         int16_t sexd = (int8_t)*i->imm16
     560                        int16_t sexd = (int8_t)*i->imm8
    549561                        INSTR_CALC_AND_SET_FLAGS(16,  
    550562                                                                         c,  
  • libemu/trunk/src/functions/cmp.c

    r1317 r1639  
    2828#include <stdint.h> 
    2929 
     30#if BYTE_ORDER == BIG_ENDIAN  
     31#define INSTR_CALC(bits, a, b, operation)                       \ 
     32UINT(bits) operand_a; \ 
     33UINT(bits) operand_b; \ 
     34bcopy(&(a), &operand_a, bits/8); \ 
     35bcopy(&(b), &operand_b, bits/8); \ 
     36UINT(bits) operation_result = operand_a operation operand_b;     
     37#else // ENDIAN 
    3038#define INSTR_CALC(bits, a, b, operation)                       \ 
    3139UINT(bits) operand_a = a;                                                               \ 
    3240UINT(bits) operand_b = b;                                                               \ 
    33 UINT(bits) operation_result = operand_a operation operand_b;    \ 
     41UINT(bits) operation_result = operand_a operation operand_b;     
     42#endif // ENDIAN 
    3443 
    3544 
  • libemu/trunk/src/functions/imul.c

    r1317 r1639  
    6868                         * IMUL r16,r/m16,imm16          
    6969                         */ 
    70  
     70#if BYTE_ORDER == BIG_ENDIAN 
     71                        int16_t sexd; 
     72                        bcopy(i->imm16, &sexd, 2); 
     73#else 
    7174                        int16_t sexd = (int16_t)*i->imm16; 
    72  
     75#endif 
    7376                        uint16_t m16; 
    7477                        MEM_WORD_READ(c, i->modrm.ea, &m16); 
     
    125128                         * IMUL r16,r/m16,imm16          
    126129                         */ 
     130#if BYTE_ORDER == BIG_ENDIAN 
     131                        int16_t sexd; 
     132                        bcopy(i->imm16, &sexd, 2); 
     133#else 
    127134                        int16_t sexd = (int16_t)*i->imm16; 
     135#endif 
     136 
    128137 
    129138                        INSTR_CALC(16, 
  • libemu/trunk/src/functions/mov.c

    r1317 r1639  
    270270                 * MOV r16,imm16     
    271271                 */ 
    272  
     272#if BYTE_ORDER == BIG_ENDIAN 
     273                bcopy(i->imm16, c->reg16[i->opc & 7], 2); 
     274#else 
    273275                *c->reg16[i->opc & 7] = *i->imm16; 
     276#endif 
     277 
     278 
    274279        } 
    275280        else 
     
    328333                else 
    329334                { 
     335#if BYTE_ORDER == BIG_ENDIAN 
     336                        bcopy(i->imm16, c->reg16[i->modrm.rm], 2); 
     337#else 
    330338                        *c->reg16[i->modrm.rm] = *i->imm16; 
    331                 }                                                                                                                                         
     339#endif 
     340                }                                                                     
    332341        } 
    333342        else 
  • libemu/trunk/src/functions/push.c

    r1328 r1639  
    150150         * PUSH imm8   
    151151         */ 
    152         if (i->prefixes & PREFIX_OPSIZE) 
    153         { 
    154                 PUSH_WORD(c, (uint16_t)((int8_t)*i->imm8)); 
    155         } 
    156         else 
    157         { 
    158                 PUSH_DWORD(c, (uint32_t)((int8_t)*i->imm8)); 
     152        if ( i->prefixes & PREFIX_OPSIZE ) 
     153        { 
     154                uint16_t word = (uint16_t)((int8_t)*i->imm8); 
     155                PUSH_WORD(c, word); 
     156        } 
     157        else 
     158        { 
     159                uint32_t dword = (uint32_t)((int8_t)*i->imm8); 
     160                PUSH_DWORD(c, dword); 
    159161        } 
    160162 
  • libemu/trunk/src/functions/ret.c

    r1317 r1639  
    4141         */ 
    4242        POP_DWORD(c, &c->eip); 
    43          
     43 
     44#if BYTE_ORDER == BIG_ENDIAN 
     45        uint16_t val; 
     46        bcopy(i->imm16, &val, 2); 
     47        c->reg[esp] += val; 
     48#else 
    4449        c->reg[esp] += *i->imm16; 
    45        
     50#endif         
    4651        return 0; 
    4752} 
  • libemu/trunk/testsuite/instrtest.c

    r1552 r1639  
    436436        { 
    437437                .instr = "or ecx,[ebx+eax*4+0xdeadbeef]", 
    438 //             .code = "\x03\x8c\x83\xef\xbe\xad\xde", 
    439 //            .codesize = 7, 
     438               .code = "\x0b\x8c\x83\xef\xbe\xad\xde", 
     439              .codesize = 7, 
    440440                .in_state.reg  = {0x2,0x1,0,0x1,0,0,0,0}, 
    441441                .in_state.mem_state = {0xdeadbef8, 0x44443333}, 
     
    458458        { 
    459459                .instr = "or ax,0x1111", 
    460 //             .code = "\x66\x05\x11\x11", 
    461 //            .codesize = 4, 
     460               .code = "\x66\x0d\x11\x11", 
     461              .codesize = 4, 
    462462                .in_state.reg  = {0x22222222,0,0,0,0,0,0,0}, 
    463463                .in_state.mem_state = {0, 0}, 
     
    468468        { 
    469469                .instr = "or eax,0x11111111", 
    470 //             .code = "\x05\x11\x11\x11\x11", 
    471 //            .codesize = 5, 
     470               .code = "\x0d\x11\x11\x11\x11", 
     471              .codesize = 5, 
    472472                .in_state.reg  = {0x22222222,0,0,0,0,0,0,0}, 
    473473                .in_state.mem_state = {0, 0}, 
     
    634634        { 
    635635                .instr = "adc ecx,[ebx+eax*4+0xdeadbeef]", 
    636 //             .code = "\x03\x8c\x83\xef\xbe\xad\xde", 
    637 //            .codesize = 7, 
     636               .code = "\x13\x8c\x83\xef\xbe\xad\xde", 
     637              .codesize = 7, 
    638638                .in_state.reg  = {0x2,0x1,0,0x1,0,0,0,0}, 
    639639                .in_state.mem_state = {0xdeadbef8, 0x44443333}, 
     
    655655        { 
    656656                .instr = "adc ax,0x1111", 
    657 //             .code = "\x66\x05\x11\x11", 
    658 //            .codesize = 4, 
     657               .code = "\x66\x15\x11\x11", 
     658              .codesize = 4, 
    659659                .in_state.reg  = {0x22222222,0,0,0,0,0,0,0}, 
    660660                .in_state.mem_state = {0, 0}, 
     
    665665        { 
    666666                .instr = "adc eax,0x11111111", 
    667 //             .code = "\x05\x11\x11\x11\x11", 
    668 //            .codesize = 5, 
     667               .code = "\x15\x11\x11\x11\x11", 
     668              .codesize = 5, 
    669669                .in_state.reg  = {0x22222222,0,0,0,0,0,0,0}, 
    670670                .in_state.mem_state = {0, 0}, 
     
    694694        }, 
    695695        { 
     696                .instr = "jmp +16", 
    696697                .code = "\xeb\x10", /* jmp +16*/ 
    697698                .codesize = 2, 
     
    699700        }, 
    700701        { 
     702                .instr = "jmp -1", 
    701703                .code = "\xeb\xff", /* jmp -1 */ 
    702704                .codesize = 2, 
     
    704706        }, 
    705707        { 
     708                .instr = "jmp +0x01000000", 
    706709                .code = "\xe9\x00\x00\x00\x01", /* jmp +0x01000000 */ 
    707710                .codesize = 5, 
     
    719722        { 
    720723                .instr = "mov ax, 0xffff", 
     724                .code = "\x66\xb8\xff\xff", 
     725                .codesize = 4, 
    721726                .out_state.reg = {0xffff,0,0,0,0,0,0,0}, 
    722727        }, 
    723728        { 
    724729                .instr = "mov eax, 0xffffffff", 
     730                .code = "\xb8\xff\xff\xff\xff", 
     731                .codesize = 5, 
    725732                .out_state.reg = {0xffffffff,0,0,0,0,0,0,0}, 
    726733        }, 
     
    734741        { 
    735742                .instr = "xor dword [eax+0x1000], 0x11111111", 
     743                .code = "\x81\xb0\x00\x10\x00\x00\x11\x11\x11\x11", 
     744                .codesize = 10, 
    736745                .in_state.mem_state = {0x2000, 0x22222222}, 
    737746                .in_state.reg = {0x1000,0,0,0,0,0,0,0}, 
     
    742751        { 
    743752                .instr = "mov eax, [ebp+ecx*4-0x100]", 
     753                .code = "\x8b\x84\x8d\x00\xff\xff\xff", 
     754                .codesize = 7, 
    744755                .in_state.mem_state = {0x140, 0x22222222}, 
    745756                .in_state.reg = {0x1000,0x10,0,0,0,0x200,0,0}, 
     
    749760        { 
    750761                .instr = "mov eax, [ebp+ecx*4-0x10000000]", 
     762                .code = "\x8b\x84\x8d\x00\x00\x00\xf0", 
     763                .codesize = 7, 
    751764                .in_state.mem_state = {0x14000000, 0x22222222}, 
    752765                .in_state.reg = {0x1000,0x1000000,0,0,0,0x20000000,0,0},