filename | src/test/testsh4x86.c |
changeset | 1189:1540105786c8 |
prev | 1112:4cac5e474d4c |
next | 1263:b3de98d19faf |
author | nkeynes |
date | Mon Feb 13 20:00:27 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Fix MMU on non-translated platforms - reintroduce old VMA translation functions (slightly modified) - modify shadow processing to work on post-translated memory ops |
file | annotate | diff | log | raw |
nkeynes@363 | 1 | /** |
nkeynes@586 | 2 | * $Id$ |
nkeynes@363 | 3 | * |
nkeynes@363 | 4 | * Test cases for the SH4 => x86 translator core. Takes as |
nkeynes@363 | 5 | * input a binary SH4 object (and VMA), generates the |
nkeynes@363 | 6 | * corresponding x86 code, and outputs the disassembly. |
nkeynes@363 | 7 | * |
nkeynes@363 | 8 | * Copyright (c) 2005 Nathan Keynes. |
nkeynes@363 | 9 | * |
nkeynes@363 | 10 | * This program is free software; you can redistribute it and/or modify |
nkeynes@363 | 11 | * it under the terms of the GNU General Public License as published by |
nkeynes@363 | 12 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@363 | 13 | * (at your option) any later version. |
nkeynes@363 | 14 | * |
nkeynes@363 | 15 | * This program is distributed in the hope that it will be useful, |
nkeynes@363 | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@363 | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@363 | 18 | * GNU General Public License for more details. |
nkeynes@363 | 19 | */ |
nkeynes@363 | 20 | |
nkeynes@363 | 21 | #include <stdio.h> |
nkeynes@363 | 22 | #include <stdarg.h> |
nkeynes@363 | 23 | #include <getopt.h> |
nkeynes@365 | 24 | #include <sys/stat.h> |
nkeynes@990 | 25 | #include <string.h> |
nkeynes@990 | 26 | |
nkeynes@365 | 27 | #include "x86dasm/x86dasm.h" |
nkeynes@363 | 28 | #include "sh4/sh4trans.h" |
nkeynes@363 | 29 | #include "sh4/sh4core.h" |
nkeynes@586 | 30 | #include "sh4/sh4mmio.h" |
nkeynes@963 | 31 | #include "sh4/mmu.h" |
nkeynes@586 | 32 | |
nkeynes@820 | 33 | struct dreamcast_module sh4_module; |
nkeynes@586 | 34 | struct mmio_region mmio_region_MMU; |
nkeynes@820 | 35 | struct mmio_region mmio_region_PMM; |
nkeynes@586 | 36 | struct breakpoint_struct sh4_breakpoints[MAX_BREAKPOINTS]; |
nkeynes@586 | 37 | int sh4_breakpoint_count = 0; |
nkeynes@363 | 38 | |
nkeynes@363 | 39 | #define MAX_INS_SIZE 32 |
nkeynes@363 | 40 | |
nkeynes@930 | 41 | |
nkeynes@930 | 42 | struct mem_region_fn **sh4_address_space = (void *)0x12345432; |
nkeynes@945 | 43 | struct mem_region_fn **sh4_user_address_space = (void *)0x12345678; |
nkeynes@363 | 44 | char *option_list = "s:o:d:h"; |
nkeynes@363 | 45 | struct option longopts[1] = { { NULL, 0, 0, 0 } }; |
nkeynes@363 | 46 | |
nkeynes@363 | 47 | char *input_file = NULL; |
nkeynes@363 | 48 | char *diff_file = NULL; |
nkeynes@363 | 49 | char *output_file = NULL; |
nkeynes@602 | 50 | gboolean sh4_starting; |
nkeynes@363 | 51 | uint32_t start_addr = 0x8C010000; |
nkeynes@365 | 52 | uint32_t sh4_cpu_period = 5; |
nkeynes@934 | 53 | unsigned char dc_main_ram[4096]; |
nkeynes@934 | 54 | unsigned char dc_boot_rom[4096]; |
nkeynes@363 | 55 | FILE *in; |
nkeynes@363 | 56 | |
nkeynes@363 | 57 | char *inbuf; |
nkeynes@365 | 58 | |
nkeynes@365 | 59 | struct x86_symbol local_symbols[] = { |
nkeynes@919 | 60 | { "sh4r+128", ((char *)&sh4r)+128 }, |
nkeynes@919 | 61 | { "sh4_cpu_period", &sh4_cpu_period }, |
nkeynes@945 | 62 | { "sh4_address_space", (void *)0x12345432 }, |
nkeynes@945 | 63 | { "sh4_user_address_space", (void *)0x12345678 }, |
nkeynes@919 | 64 | { "sh4_write_fpscr", sh4_write_fpscr }, |
nkeynes@919 | 65 | { "sh4_write_sr", sh4_write_sr }, |
nkeynes@919 | 66 | { "sh4_read_sr", sh4_read_sr }, |
nkeynes@919 | 67 | { "sh4_sleep", sh4_sleep }, |
nkeynes@919 | 68 | { "sh4_fsca", sh4_fsca }, |
nkeynes@919 | 69 | { "sh4_ftrv", sh4_ftrv }, |
nkeynes@919 | 70 | { "sh4_switch_fr_banks", sh4_switch_fr_banks }, |
nkeynes@919 | 71 | { "sh4_execute_instruction", sh4_execute_instruction }, |
nkeynes@919 | 72 | { "signsat48", signsat48 }, |
nkeynes@919 | 73 | { "xlat_get_code_by_vma", xlat_get_code_by_vma }, |
nkeynes@919 | 74 | { "xlat_get_code", xlat_get_code } |
nkeynes@365 | 75 | }; |
nkeynes@363 | 76 | |
nkeynes@363 | 77 | // Stubs |
nkeynes@802 | 78 | gboolean sh4_execute_instruction( ) { return TRUE; } |
nkeynes@363 | 79 | void sh4_accept_interrupt() {} |
nkeynes@586 | 80 | void sh4_set_breakpoint( uint32_t pc, breakpoint_type_t type ) { } |
nkeynes@802 | 81 | gboolean sh4_clear_breakpoint( uint32_t pc, breakpoint_type_t type ) { return TRUE; } |
nkeynes@775 | 82 | gboolean dreamcast_is_running() { return FALSE; } |
nkeynes@802 | 83 | int sh4_get_breakpoint( uint32_t pc ) { return 0; } |
nkeynes@948 | 84 | void sh4_finalize_instruction() { } |
nkeynes@740 | 85 | void sh4_core_exit( int exit_code ){} |
nkeynes@1091 | 86 | void sh4_crashdump() {} |
nkeynes@363 | 87 | void event_execute() {} |
nkeynes@363 | 88 | void TMU_run_slice( uint32_t nanos ) {} |
nkeynes@968 | 89 | void CCN_set_cache_control( int val ) { } |
nkeynes@884 | 90 | void PMM_write_control( int ctr, uint32_t val ) { } |
nkeynes@363 | 91 | void SCIF_run_slice( uint32_t nanos ) {} |
nkeynes@905 | 92 | void FASTCALL sh4_write_fpscr( uint32_t val ) { } |
nkeynes@905 | 93 | void FASTCALL sh4_write_sr( uint32_t val ) { } |
nkeynes@905 | 94 | uint32_t FASTCALL sh4_read_sr( void ) { return 0; } |
nkeynes@905 | 95 | void FASTCALL sh4_sleep() { } |
nkeynes@905 | 96 | void FASTCALL sh4_fsca( uint32_t angle, float *fr ) { } |
nkeynes@905 | 97 | void FASTCALL sh4_ftrv( float *fv ) { } |
nkeynes@905 | 98 | void FASTCALL signsat48(void) { } |
nkeynes@669 | 99 | void sh4_switch_fr_banks() { } |
nkeynes@918 | 100 | void mem_copy_to_sh4( sh4addr_t addr, sh4ptr_t src, size_t size ) { } |
nkeynes@602 | 101 | gboolean sh4_has_page( sh4vma_t vma ) { return TRUE; } |
nkeynes@385 | 102 | void syscall_invoke( uint32_t val ) { } |
nkeynes@586 | 103 | void dreamcast_stop() {} |
nkeynes@586 | 104 | void dreamcast_reset() {} |
nkeynes@951 | 105 | void FASTCALL sh4_raise_reset( int exc ) { } |
nkeynes@951 | 106 | void FASTCALL sh4_raise_exception( int exc ) { } |
nkeynes@951 | 107 | void FASTCALL sh4_raise_tlb_exception( int exc, sh4vma_t vma ) { } |
nkeynes@951 | 108 | void FASTCALL sh4_raise_tlb_multihit( sh4vma_t vma) { } |
nkeynes@951 | 109 | void FASTCALL sh4_raise_trap( int exc ) { } |
nkeynes@939 | 110 | void FASTCALL sh4_flush_store_queue( sh4addr_t addr ) { } |
nkeynes@939 | 111 | void FASTCALL sh4_flush_store_queue_mmu( sh4addr_t addr, void *exc ) { } |
nkeynes@1189 | 112 | void sh4_handle_pending_events() { } |
nkeynes@802 | 113 | uint32_t sh4_sleep_run_slice(uint32_t nanosecs) { return nanosecs; } |
nkeynes@802 | 114 | gboolean gui_error_dialog( const char *fmt, ... ) { return TRUE; } |
nkeynes@939 | 115 | gboolean FASTCALL mmu_update_icache( sh4vma_t addr ) { return TRUE; } |
nkeynes@939 | 116 | void MMU_ldtlb() { } |
nkeynes@1112 | 117 | void event_schedule(int event, uint32_t nanos) { } |
nkeynes@586 | 118 | struct sh4_icache_struct sh4_icache; |
nkeynes@930 | 119 | struct mem_region_fn mem_region_unmapped; |
nkeynes@1091 | 120 | const struct cpu_desc_struct sh4_cpu_desc; |
nkeynes@1091 | 121 | sh4addr_t FASTCALL mmu_vma_to_phys_disasm( sh4vma_t vma ) { return vma; } |
nkeynes@363 | 122 | |
nkeynes@363 | 123 | void usage() |
nkeynes@363 | 124 | { |
nkeynes@363 | 125 | fprintf( stderr, "Usage: testsh4x86 [options] <input bin file>\n"); |
nkeynes@363 | 126 | fprintf( stderr, "Options:\n"); |
nkeynes@363 | 127 | fprintf( stderr, " -d <filename> Diff results against contents of file\n" ); |
nkeynes@363 | 128 | fprintf( stderr, " -h Display this help message\n" ); |
nkeynes@363 | 129 | fprintf( stderr, " -o <filename> Output disassembly to file [stdout]\n" ); |
nkeynes@363 | 130 | fprintf( stderr, " -s <addr> Specify start address of binary [8C010000]\n" ); |
nkeynes@363 | 131 | } |
nkeynes@363 | 132 | |
nkeynes@363 | 133 | void emit( void *ptr, int level, const gchar *source, const char *msg, ... ) |
nkeynes@363 | 134 | { |
nkeynes@363 | 135 | va_list ap; |
nkeynes@363 | 136 | va_start( ap, msg ); |
nkeynes@363 | 137 | vfprintf( stderr, msg, ap ); |
nkeynes@363 | 138 | fprintf( stderr, "\n" ); |
nkeynes@363 | 139 | va_end(ap); |
nkeynes@363 | 140 | } |
nkeynes@363 | 141 | |
nkeynes@363 | 142 | |
nkeynes@363 | 143 | struct sh4_registers sh4r; |
nkeynes@363 | 144 | |
nkeynes@363 | 145 | |
nkeynes@363 | 146 | int main( int argc, char *argv[] ) |
nkeynes@363 | 147 | { |
nkeynes@363 | 148 | struct stat st; |
nkeynes@363 | 149 | int opt; |
nkeynes@363 | 150 | while( (opt = getopt_long( argc, argv, option_list, longopts, NULL )) != -1 ) { |
nkeynes@363 | 151 | switch( opt ) { |
nkeynes@363 | 152 | case 'd': |
nkeynes@363 | 153 | diff_file = optarg; |
nkeynes@363 | 154 | break; |
nkeynes@363 | 155 | case 'o': |
nkeynes@363 | 156 | output_file = optarg; |
nkeynes@363 | 157 | break; |
nkeynes@363 | 158 | case 's': |
nkeynes@363 | 159 | start_addr = strtoul(optarg, NULL, 0); |
nkeynes@363 | 160 | break; |
nkeynes@363 | 161 | case 'h': |
nkeynes@363 | 162 | usage(); |
nkeynes@363 | 163 | exit(0); |
nkeynes@363 | 164 | } |
nkeynes@363 | 165 | } |
nkeynes@363 | 166 | if( optind < argc ) { |
nkeynes@363 | 167 | input_file = argv[optind++]; |
nkeynes@363 | 168 | } else { |
nkeynes@363 | 169 | usage(); |
nkeynes@363 | 170 | exit(1); |
nkeynes@363 | 171 | } |
nkeynes@363 | 172 | |
nkeynes@919 | 173 | mmio_region_MMU.mem = malloc(4096); |
nkeynes@919 | 174 | memset( mmio_region_MMU.mem, 0, 4096 ); |
nkeynes@919 | 175 | |
nkeynes@929 | 176 | ((uint32_t *)mmio_region_MMU.mem)[4] = 1; |
nkeynes@929 | 177 | |
nkeynes@363 | 178 | in = fopen( input_file, "ro" ); |
nkeynes@363 | 179 | if( in == NULL ) { |
nkeynes@363 | 180 | perror( "Unable to open input file" ); |
nkeynes@363 | 181 | exit(2); |
nkeynes@363 | 182 | } |
nkeynes@363 | 183 | fstat( fileno(in), &st ); |
nkeynes@363 | 184 | inbuf = malloc( st.st_size ); |
nkeynes@363 | 185 | fread( inbuf, st.st_size, 1, in ); |
nkeynes@919 | 186 | sh4_icache.mask = 0xFFFFF000; |
nkeynes@919 | 187 | sh4_icache.page_vma = start_addr & 0xFFFFF000; |
nkeynes@919 | 188 | sh4_icache.page = (unsigned char *)(inbuf - (sh4_icache.page_vma&0xFFF)); |
nkeynes@919 | 189 | sh4_icache.page_ppa = start_addr & 0xFFFFF000; |
nkeynes@363 | 190 | |
nkeynes@365 | 191 | xlat_cache_init(); |
nkeynes@925 | 192 | uintptr_t pc; |
nkeynes@365 | 193 | uint8_t *buf = sh4_translate_basic_block( start_addr ); |
nkeynes@919 | 194 | uint32_t buflen = xlat_get_code_size(buf); |
nkeynes@968 | 195 | x86_disasm_init( buf, (uintptr_t)buf, buflen ); |
nkeynes@919 | 196 | x86_set_symtab( local_symbols, sizeof(local_symbols)/sizeof(struct x86_symbol) ); |
nkeynes@968 | 197 | for( pc = (uintptr_t)buf; pc < ((uintptr_t)buf) + buflen; ) { |
nkeynes@363 | 198 | char buf[256]; |
nkeynes@363 | 199 | char op[256]; |
nkeynes@925 | 200 | uintptr_t pc2 = x86_disasm_instruction( pc, buf, sizeof(buf), op ); |
nkeynes@990 | 201 | fprintf( stdout, "%p: %s\n", (void *)pc, buf ); |
nkeynes@363 | 202 | pc = pc2; |
nkeynes@363 | 203 | } |
nkeynes@802 | 204 | return 0; |
nkeynes@363 | 205 | } |
.