Mon, 14 Jan 2013 09:22:12 +0000
More bus error fixes for FreeBee
I have fixed two more bus error handling bugs in FreeBee. First, the CPU core was executing the instruction regardless of whether a bus error occurs when fetching the opcode (which caused it to execute a bogus instruction in such cases). The other one was related to one of my previous fixes - the jump to the bus error vector was at the beginning of the main loop, so it wouldn't be called immediately after the bus error occurred if the timeslot expired, causing the return address to be off.
With these fixes, Unix now runs enough to get into userspace and run the install script (it is also possible to break out and get a shell prompt). However, many commands segfault semi-randomly (or more specifically, it seems that some child processes forked by the shell might be segfaulting before they can exec the command program), so installing the system isn't possible yet. I am not sure exactly what the bug is, but it seems to be related to some function in the shell returning null when the code calling it is assuming that it won't. What the function is, or why it is returning null, I'm not sure (the shell is built without the shared libc and is stripped, making identifying the function harder). I suspect that the function might be in libc, but that is hard to tell.
Author: Andrew Warkentin <andreww591 gmail com>
philpem@18 | 1 | #ifndef _STATE_H |
philpem@18 | 2 | #define _STATE_H |
philpem@18 | 3 | |
philpem@18 | 4 | #include <stddef.h> |
philpem@18 | 5 | #include <stdint.h> |
philpem@18 | 6 | #include <stdbool.h> |
philpem@52 | 7 | #include "wd279x.h" |
philpem@112 | 8 | #include "wd2010.h" |
philpem@80 | 9 | #include "keyboard.h" |
philpem@18 | 10 | |
philpem@18 | 11 | // Maximum size of the Boot PROMs. Must be a binary power of two. |
philpem@18 | 12 | #define ROM_SIZE 32768 |
philpem@18 | 13 | |
philpem@18 | 14 | /** |
philpem@55 | 15 | * State error codes |
philpem@55 | 16 | */ |
philpem@55 | 17 | typedef enum { |
philpem@55 | 18 | STATE_E_OK = 0, ///< Operation succeeded |
philpem@55 | 19 | STATE_E_BAD_RAMSIZE = -1, ///< Bad RAM size specified (not a multiple of 512K, or less than 512K) |
philpem@55 | 20 | STATE_E_NO_MEMORY = -2, ///< Out of memory while allocating state variables |
philpem@55 | 21 | STATE_E_ROM_LOAD_FAIL = -3 ///< Error loading ROMs |
philpem@55 | 22 | } STATE_ERR; |
philpem@55 | 23 | |
philpem@55 | 24 | /** |
philpem@18 | 25 | * @brief Emulator state storage |
philpem@18 | 26 | * |
philpem@18 | 27 | * This structure stores the internal state of the emulator. |
philpem@18 | 28 | */ |
philpem@18 | 29 | typedef struct { |
philpem@18 | 30 | // Boot PROM can be up to 32Kbytes total size |
philpem@18 | 31 | uint8_t rom[ROM_SIZE]; ///< Boot PROM data buffer |
philpem@18 | 32 | |
philpem@52 | 33 | //// Main system RAM |
philpem@60 | 34 | uint8_t *base_ram; ///< Base RAM data buffer |
philpem@60 | 35 | size_t base_ram_size; ///< Size of Base RAM buffer in bytes |
philpem@62 | 36 | uint8_t *exp_ram; ///< Expansion RAM data buffer |
philpem@62 | 37 | size_t exp_ram_size; ///< Size of Expansion RAM buffer in bytes |
philpem@18 | 38 | |
philpem@52 | 39 | /// Video RAM |
philpem@52 | 40 | uint8_t vram[0x8000]; |
philpem@24 | 41 | |
philpem@52 | 42 | /// Map RAM |
philpem@52 | 43 | uint8_t map[0x800]; |
philpem@26 | 44 | |
philpem@52 | 45 | //// Registers |
philpem@37 | 46 | uint16_t genstat; ///< General Status Register |
philpem@37 | 47 | uint16_t bsr0; ///< Bus Status Register 0 |
philpem@37 | 48 | uint16_t bsr1; ///< Bus Status Register 1 |
philpem@32 | 49 | |
philpem@52 | 50 | //// MISCELLANEOUS CONTROL REGISTER |
philpem@52 | 51 | bool dma_reading; ///< True if Disc DMA reads from the controller, false otherwise |
philpem@46 | 52 | uint8_t leds; ///< LED status, 1=on, in order red3/green2/yellow1/red0 from bit3 to bit0 |
philpem@46 | 53 | |
philpem@97 | 54 | bool timer_enabled; |
philpem@97 | 55 | bool timer_asserted; |
philpem@97 | 56 | |
philpem@52 | 57 | //// GENERAL CONTROL REGISTER |
philpem@18 | 58 | /// GENCON.ROMLMAP -- false ORs the address with 0x800000, forcing the |
philpem@18 | 59 | /// 68010 to access ROM instead of RAM when booting. TRM page 2-36. |
philpem@24 | 60 | bool romlmap; |
philpem@44 | 61 | /// GENCON.PIE -- Parity Error Check Enable |
philpem@44 | 62 | bool pie; |
philpem@101 | 63 | /// GENCON.EE -- Error Enable |
philpem@101 | 64 | bool ee; |
philpem@52 | 65 | |
philpem@52 | 66 | /// DMA Address Register |
philpem@52 | 67 | uint32_t dma_address; |
philpem@52 | 68 | |
philpem@53 | 69 | /// DMA count |
philpem@53 | 70 | uint32_t dma_count; |
philpem@53 | 71 | |
philpem@53 | 72 | /// DMA direction |
philpem@53 | 73 | bool idmarw; |
philpem@53 | 74 | /// DMA enable |
philpem@53 | 75 | bool dmaen; |
philpem@53 | 76 | bool dmaenb; |
philpem@53 | 77 | |
philpem@112 | 78 | /// DMA device selection flags |
philpem@112 | 79 | bool fd_selected; |
philpem@112 | 80 | bool hd_selected; |
philpem@52 | 81 | /// Floppy disc controller context |
philpem@52 | 82 | WD2797_CTX fdc_ctx; |
philpem@95 | 83 | /// Current disc image file |
philpem@95 | 84 | FILE *fdc_disc; |
philpem@80 | 85 | |
philpem@112 | 86 | /// Hard disc controller context |
philpem@112 | 87 | WD2010_CTX hdc_ctx; |
philpem@112 | 88 | FILE *hdc_disc0; |
philpem@112 | 89 | FILE *hdc_disc1; |
philpem@112 | 90 | |
philpem@80 | 91 | /// Keyboard controller context |
philpem@80 | 92 | KEYBOARD_STATE kbd; |
philpem@18 | 93 | } S_state; |
philpem@18 | 94 | |
philpem@18 | 95 | // Global emulator state. Yes, I know global variables are evil, please don't |
philpem@18 | 96 | // email me and lecture me about it. -philpem |
philpem@18 | 97 | #ifndef _STATE_C |
philpem@18 | 98 | extern S_state state; |
philpem@18 | 99 | #else |
philpem@18 | 100 | S_state state; |
philpem@18 | 101 | #endif |
philpem@18 | 102 | |
philpem@18 | 103 | /** |
philpem@18 | 104 | * @brief Initialise system state |
philpem@18 | 105 | * |
philpem@62 | 106 | * @param base_ram_size Base RAM size in bytes -- must be a multiple of 512KiB, min 512KiB, max 2MiB. |
philpem@62 | 107 | * @param exp_ram_size Expansion RAM size in bytes -- must be a multiple of 512KiB, min 0, max 2MiB. |
philpem@18 | 108 | * |
philpem@18 | 109 | * Initialises the emulator's internal state. |
philpem@18 | 110 | */ |
philpem@62 | 111 | int state_init(size_t base_ram_size, size_t exp_ram_size); |
philpem@18 | 112 | |
philpem@18 | 113 | /** |
philpem@18 | 114 | * @brief Deinitialise system state |
philpem@18 | 115 | * |
philpem@18 | 116 | * Deinitialises the saved state, and frees all memory. Call this function |
philpem@18 | 117 | * before exiting your program to avoid memory leaks. |
philpem@18 | 118 | */ |
philpem@18 | 119 | void state_done(); |
philpem@18 | 120 | |
philpem@18 | 121 | #endif |