trunk/src/emu/cpu/i386/i386.c
| r18941 | r18942 | |
| 2797 | 2797 | |
| 2798 | 2798 | /*************************************************************************/ |
| 2799 | 2799 | |
| 2800 | static UINT8 read8_debug(i386_state *cpustate, UINT32 ea, UINT8 *data) |
| 2801 | { |
| 2802 | UINT32 address = ea, error; |
| 2803 | |
| 2804 | if (cpustate->cr[0] & 0x80000000) // page translation enabled |
| 2805 | { |
| 2806 | if(!translate_address(cpustate,-1,&address,&error)) |
| 2807 | return 0; |
| 2808 | } |
| 2809 | |
| 2810 | address &= cpustate->a20_mask; |
| 2811 | *data = cpustate->program->read_byte(address); |
| 2812 | return 1; |
| 2813 | } |
| 2814 | |
| 2815 | static UINT32 i386_get_debug_desc(i386_state *cpustate, I386_SREG *seg) |
| 2816 | { |
| 2817 | UINT32 base, limit, address; |
| 2818 | union { UINT8 b[8]; UINT32 w[2]; } data; |
| 2819 | UINT8 ret; |
| 2820 | int entry; |
| 2821 | |
| 2822 | if ( seg->selector & 0x4 ) |
| 2823 | { |
| 2824 | base = cpustate->ldtr.base; |
| 2825 | limit = cpustate->ldtr.limit; |
| 2826 | } else { |
| 2827 | base = cpustate->gdtr.base; |
| 2828 | limit = cpustate->gdtr.limit; |
| 2829 | } |
| 2830 | |
| 2831 | entry = seg->selector & ~0x7; |
| 2832 | if (limit == 0 || entry + 7 > limit) |
| 2833 | return 0; |
| 2834 | |
| 2835 | address = entry + base; |
| 2836 | |
| 2837 | // todo: bigendian |
| 2838 | ret = read8_debug( cpustate, address+0, &data.b[0] ); |
| 2839 | ret += read8_debug( cpustate, address+1, &data.b[1] ); |
| 2840 | ret += read8_debug( cpustate, address+2, &data.b[2] ); |
| 2841 | ret += read8_debug( cpustate, address+3, &data.b[3] ); |
| 2842 | ret += read8_debug( cpustate, address+4, &data.b[4] ); |
| 2843 | ret += read8_debug( cpustate, address+5, &data.b[5] ); |
| 2844 | ret += read8_debug( cpustate, address+6, &data.b[6] ); |
| 2845 | ret += read8_debug( cpustate, address+7, &data.b[7] ); |
| 2846 | |
| 2847 | if(ret != 8) |
| 2848 | return 0; |
| 2849 | |
| 2850 | seg->flags = (data.w[1] >> 8) & 0xf0ff; |
| 2851 | seg->base = (data.w[1] & 0xff000000) | ((data.w[1] & 0xff) << 16) | ((data.w[0] >> 16) & 0xffff); |
| 2852 | seg->limit = (data.w[1] & 0xf0000) | (data.w[0] & 0xffff); |
| 2853 | if (seg->flags & 0x8000) |
| 2854 | seg->limit = (seg->limit << 12) | 0xfff; |
| 2855 | seg->d = (seg->flags & 0x4000) ? 1 : 0; |
| 2856 | seg->valid = (seg->selector & ~3)?(true):(false); |
| 2857 | |
| 2858 | return seg->valid; |
| 2859 | } |
| 2860 | |
| 2800 | 2861 | static UINT64 i386_debug_segbase(symbol_table &table, void *ref, int params, const UINT64 *param) |
| 2801 | 2862 | { |
| 2802 | 2863 | legacy_cpu_device *device = (legacy_cpu_device *)ref; |
| r18941 | r18942 | |
| 2804 | 2865 | UINT32 result; |
| 2805 | 2866 | I386_SREG seg; |
| 2806 | 2867 | |
| 2807 | | if (PROTECTED_MODE) |
| 2868 | if(param[0] > 65535) |
| 2869 | return 0; |
| 2870 | |
| 2871 | if (PROTECTED_MODE && !V8086_MODE) |
| 2808 | 2872 | { |
| 2809 | 2873 | memset(&seg, 0, sizeof(seg)); |
| 2810 | | seg.selector = (UINT16) param[0]; |
| 2811 | | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 2874 | seg.selector = param[0]; |
| 2875 | if(!i386_get_debug_desc(cpustate,&seg)) |
| 2876 | return 0; |
| 2812 | 2877 | result = seg.base; |
| 2813 | 2878 | } |
| 2814 | 2879 | else |
| r18941 | r18942 | |
| 2825 | 2890 | UINT32 result = 0; |
| 2826 | 2891 | I386_SREG seg; |
| 2827 | 2892 | |
| 2828 | | if (PROTECTED_MODE) |
| 2893 | if (PROTECTED_MODE && !V8086_MODE) |
| 2829 | 2894 | { |
| 2830 | 2895 | memset(&seg, 0, sizeof(seg)); |
| 2831 | | seg.selector = (UINT16) param[0]; |
| 2832 | | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 2896 | seg.selector = param[0]; |
| 2897 | if(!i386_get_debug_desc(cpustate,&seg)) |
| 2898 | return 0; |
| 2833 | 2899 | result = seg.limit; |
| 2834 | 2900 | } |
| 2835 | 2901 | return result; |
| 2836 | 2902 | } |
| 2837 | 2903 | |
| 2904 | static UINT64 i386_debug_segofftovirt(symbol_table &table, void *ref, int params, const UINT64 *param) |
| 2905 | { |
| 2906 | legacy_cpu_device *device = (legacy_cpu_device *)ref; |
| 2907 | i386_state *cpustate = get_safe_token(device); |
| 2908 | UINT32 result = 0; |
| 2909 | I386_SREG seg; |
| 2910 | |
| 2911 | if(param[0] > 65535) |
| 2912 | return 0; |
| 2913 | |
| 2914 | if (PROTECTED_MODE && !V8086_MODE) |
| 2915 | { |
| 2916 | memset(&seg, 0, sizeof(seg)); |
| 2917 | seg.selector = param[0]; |
| 2918 | if(!i386_get_debug_desc(cpustate,&seg)) |
| 2919 | return 0; |
| 2920 | if((seg.flags & 0x0090) != 0x0090) // not system and present |
| 2921 | return 0; |
| 2922 | if((seg.flags & 0x0018) == 0x0010 && seg.flags & 0x0004) // expand down |
| 2923 | { |
| 2924 | if(param[1] <= seg.limit) |
| 2925 | return 0; |
| 2926 | } |
| 2927 | else |
| 2928 | { |
| 2929 | if(param[1] > seg.limit) |
| 2930 | return 0; |
| 2931 | } |
| 2932 | result = seg.base+param[1]; |
| 2933 | } |
| 2934 | else |
| 2935 | { |
| 2936 | if(param[1] > 65535) |
| 2937 | return 0; |
| 2938 | |
| 2939 | result = (param[0] << 4) + param[1]; |
| 2940 | } |
| 2941 | return result; |
| 2942 | } |
| 2943 | |
| 2944 | static UINT64 i386_debug_virttophys(symbol_table &table, void *ref, int params, const UINT64 *param) |
| 2945 | { |
| 2946 | legacy_cpu_device *device = (legacy_cpu_device *)ref; |
| 2947 | i386_state *cpustate = get_safe_token(device); |
| 2948 | UINT32 result = param[0], error; |
| 2949 | |
| 2950 | if (cpustate->cr[0] & 0x80000000) |
| 2951 | { |
| 2952 | if(!translate_address(cpustate,-1,&result,&error)) |
| 2953 | return 0; |
| 2954 | } |
| 2955 | return result; |
| 2956 | } |
| 2957 | |
| 2838 | 2958 | static CPU_DEBUG_INIT( i386 ) |
| 2839 | 2959 | { |
| 2840 | 2960 | device->debug()->symtable().add("segbase", (void *)device, 1, 1, i386_debug_segbase); |
| 2841 | 2961 | device->debug()->symtable().add("seglimit", (void *)device, 1, 1, i386_debug_seglimit); |
| 2962 | device->debug()->symtable().add("segofftovirt", (void *)device, 2, 2, i386_debug_segofftovirt); |
| 2963 | device->debug()->symtable().add("virttophys", (void *)device, 1, 1, i386_debug_virttophys); |
| 2842 | 2964 | } |
| 2843 | 2965 | |
| 2844 | 2966 | /*************************************************************************/ |