From 5c04f4f7fced8f90816be87e9efde53441447d7a Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Mon, 27 Jan 1997 21:34:50 +0000 Subject: [PATCH] January 23rd merge --- sim/ppc/BUGS | 47 + sim/ppc/ChangeLog | 1001 +++++++++++++++- sim/ppc/Makefile.in | 76 +- sim/ppc/configure | 1463 ++++++++++++++---------- sim/ppc/configure.in | 10 +- sim/ppc/device.c | 2208 +++++++++++++++++++----------------- sim/ppc/device.h | 397 +++++-- sim/ppc/emul_chirp.c | 1860 +++++++++++++++++++++--------- sim/ppc/gen-icache.c | 325 +++--- sim/ppc/gen-idecode.c | 337 ++++-- sim/ppc/igen.c | 34 +- sim/ppc/main.c | 55 +- sim/ppc/ppc-cache-rules | 18 +- sim/ppc/ppc-instructions | 407 +++++-- sim/ppc/ppc-opcode-complex | 6 +- sim/ppc/psim.c | 283 +++-- sim/ppc/sim_calls.c | 14 +- sim/ppc/tree.c | 1273 +++++++++++++++++++++ 18 files changed, 7018 insertions(+), 2796 deletions(-) create mode 100644 sim/ppc/BUGS create mode 100644 sim/ppc/tree.c diff --git a/sim/ppc/BUGS b/sim/ppc/BUGS new file mode 100644 index 00000000000..81e7870b885 --- /dev/null +++ b/sim/ppc/BUGS @@ -0,0 +1,47 @@ +ChangeLog + +See the ChangeLog file looking for lines taged with the word FIXME. + +COREFILE.C: + +The implementation of corefile.c (defined by corefile.h) isn't the +best. It is intended to be functionaly correct rather than fast. One +option being considered is to add a data cache to reduce the overhead +of the most common case of data read/writes. + +VEA + +Missing VEA system calls. + +ppc-instructions: + +Missing or commented out instructions. + +64bit: + +64bit target untested. 64bit host broken. For instance use of scanf +"%x", &long long. + +events.c: + +Event code for pending events from within signal handlers not +finished/tested. + +hw_*.c: + +Better and more devices. + +PORTABILITY: + +(Notes taken from Michael Meissner): Heavy use of the ## operator - +fix using the clasic X/**/Y hack; Use of the signed keyword. In +particular, signed char has no analogue in classic C (though most +implementations of classic C use signed chars); Use of long long which +restricts the target compiler to be GCC. + + +device_ioctl(): + +Should have an extra argument (unsigned request) as standard. + + diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog index 4bf6282dad2..d7f31be13ef 100644 --- a/sim/ppc/ChangeLog +++ b/sim/ppc/ChangeLog @@ -1,15 +1,774 @@ +Thu Jan 23 09:07:26 1997 Andrew Cagney + + * hw_trace.c (hw_trace_init_data): Delete. The trace options need + to be initialized independant of the rest of the simulation + initalization. Otherwize a trace option explictly set from gdb + could be overridden by hw_trace. + + * psim.c (psim_options): Clarify reason why the trace ioctl occures. + + * FIXME: The trace code is too scattered - hw_trace.c, psim.c, + debug.c. It could be much simpler. + +Thu Jan 23 09:07:26 1997 Andrew Cagney + + * Some devices support removable media. Add hooks to the disk + device so that it supports this. + + * device.c (device_add_string_array_property, + device_find_string_array_property): New functions, manipulate + properties containing an array of strings. + (device_find_string_property): Allow a string array. + (device_init_static_properties): Update. + (device_init_runtime_properties): Update. + + * hw_disk.c (hw_disk_ioctl): Add ioctl for changing the disk + media. If no file image is specified, use the next one in the + image property list. + (hw_disk_init_address): Change the file property so that it is a + string array - use the first entry for the initial file image. + + * tree.c (print_string_aray_property): New function - print a + string array. + (print_properties): Adjust. + (print_string): Write a string, handling double quotes. + + * device.h: Define an ioctl to `change-media' with an optional new + media image. + + * hw_disk.c: Allow floppy disk devices to be specified. + + * psim.c (psim_command): New function, parse more complex psim + commands such as "change-media" and "trace". + * sim_calls.c (sim_do_command): Use. + +Wed Jan 22 09:38:33 1997 Andrew Cagney + + * For expressions like (RA == 0) that are entered in to the cache + as RA_is_0. If possible generate the result of the expression so + that the compiler gets a better chance of eliminating dead + branches. + + * gen-icache.c (print_icache_extraction): For a cache entry of + the form _is_ where it is a boolean field, generate + the result of the expression instead of the expression its self. + (print_icache_body): Remove code that was looking for *_is_0 and + then generating corresponding definitions. + + * gen-icache.c (print_icache_struct): If there is no cache, do not + output expressions in idecode.h file. + + * gen-icache.c (print_icache_body): Output them here. + + * ppc-opcode-complex: Clarify constant values for SPR==LR register + expansion. + + * ppc-cache-rules (RA_is_0, SPR_is_256): Two new cache entries. + +Wed Jan 22 12:24:52 1997 Andrew Cagney + + * The code that put values in and extracted values from the cache + was too compilicated. The cache table did not allow values to be + computed from cache entries. #defines could only be used when a + cache was present, remove the restriction. + + * ld-cache.h, ld-cache.c: Add a new cache entry type - SCRATCH. A + scratch variable is defined when a cache entry is beinf + filled. Change the definition of a COMPUTE variable to be defined + when the cache entry is being used. + * gen-icache.c: Update. + + * ld-cache.h, ld-cache.c: Change field names so that their meaning + is more obvious. old_name->field_name, new_name->derived_name. + * gen-icache.c: Update + + * gen-icache.h, gen-icache.c (print_icache_body): Make the three + different types of cache code - put into cache, extract from + cache, no cache - an explicit argument to print_icache_body. + * gen-icache.c (print_icache_extraction): Ditto. + + * gen-semantics.c (print_c_semantic): Update use. + * gen-idecode.c (print_jump_insn): Update use. + * gen-icache.c (print_icache_function): Update use. + + * igen.c (main): Change 'R' option so that it does not force the + cache. + + * configure.in (enable-sim-icache): Clarify description. Make + #define one of the defaults regardless of the cache. Probably + should revamp and add a separate option. + +Tue Jan 21 13:26:10 1997 Andrew Cagney + + * pk_disklabel.c (block_is_fdisk): Tidy up traces - use dos + partition numbering. + (pk_disklabel_create_instance): Partition 1..4 are valid - not + 1..3. + (is_iso9660): New function, verify a CD9660 File system. + (pk_disklabel_create_instance): Start expanding so that active + partition selection is supported. + +Mon Jan 20 11:20:15 1997 Andrew Cagney + + * The cap object was retaining a reference to the instance of a + device after it was deleted. Instead add and remove cap's from the + cap db as they are created and deleted. This ensuring that a + capibility is only used during the lifetime of the corresponding + object. + + * cap.h, cap.c: Correct cap type - was signed32 should be + signed_cell. + + * cap.c (cap_add, cap_remove): New methods for cap object that + allow the explicit addition and removal of internal objects that + the cap knows about. + + * cap.c (cap_init): Rewrite. Verify that the only objects + remaining in the cap data base are those that were entered first. + Thse objects will be the permenant ones. + * device.c (device_init_address): Remember to initialize the cap + database. + + * device.c (device_create_instance_from): Explicitly add device + instances to the cap database. Simplify create code. + (device_instance_delete): Explicitly remove device instances from + the cap database. + + * device.c (device_create_from): Explicitly add a device to the + cap data base. + + * device.c (device_create_from): Always set the cap members. + + * hw_disk.c: Output the instance when tracing. + +Sun Jan 19 16:44:29 1997 Andrew Cagney + + * tree.c (split_device_specifier): Add support for aliases when + looking up a device. Now needs a device as an argument. + (split_property_specifier): Ditto. + +Sun Jan 19 15:28:23 1997 Andrew Cagney + + * The memory "claim" and "release" methods take an address and + size as arguments. These may be multi cell values. Initially fix + the memory code so that they check/detect this. Leave the + adjustment of any clients to later. + + * hw_memory.c (hw_memory_instance_claim, + hw_memory_instance_release): Handle multi-cell memory devices. + + * hw_memory.c (hw_memory_instance_claim): Be tolerant towards the + release of memory regions that were not claimed. + +Fri Jan 17 12:01:07 1997 Andrew Cagney + + * device.h, device.c (device_instance_call_method): Correct return + type - can return either 0 or -1, hence should be a signed type. + * device_table.h: Ditto. + + * hw_memory.c (hw_memory_instance_claim, + hw_memory_instance_release): Update. + * hw_disk.c (hw_disk_max_transfer, hw_disk_block_size, + hw_disk_nr_blocks): Ditto. + +Fri Jan 17 11:50:13 1997 Andrew Cagney + + * emul_chirp.c (chirp_emul_claim): Implement using the "claim" + method belonging to "/chosen/memory". + (chirm_emul_release): Ditto. + + * Makefile.in (LIB_INLINE_SRC): Remove emul_* from list of files + that are inlined. These modules are called via a table and are + not made inline. + + * hw_init.c (update_for_binary_section): Fix failure to allocate + memory used by the binary in real-mode executions. If "claim" + property is present, allocate memory from the "/chosen/memory" + device. + + * emul_chirp.c (emul_chirp_create): Specify that memory should be + claimed when loading a real image. + + * hw_memory.c (hw_memory_instance_claim): Don't page align memory + allocations. + + * hw_memory.c (hw_memory_instance_release): Avoid infinite loop + when merging adjacent memory chunks. + +Thu Jan 16 08:51:25 1997 Andrew Cagney + + * vm.h (vm_data_map_read_buffer, vm_data_map_write_buffer): Add + optional PROCESSOR & CIA args so that this routine also abort an + access. + + * vm_n.h (vm_data_map_read_N, vm_data_map_write_N): For a + miss-aligned access when a transfer fails abort. + + * emul_bugapi.c (emul_bugapi_do_write): Use emul_read_buffer + instead of the vm_read_buffer. + * emul_netbsd.c (do_write): Ditto. + * emul_unix.c (do_unix_write): Ditto. + +Wed Jan 15 14:38:25 1997 Andrew Cagney + + * configure.in (--enable-sim-jump): Default is NULL and not -E. + * configure: Regenerate. + + * basics.h (__attribute__): Enable attributes if GCC >= 2.6. + (UNUSED): Only enable UNUSED if GCC >= 2.7. + + * gen-icache.c (print_icache_extraction): Print UNUSED macro + instead of explicit __unused__ attribute. + (print_icache_body): Ditto. + * idecode_expression.h (FPSCR_BEGIN): Use UNUSED. + +Wed Jan 15 13:54:50 1997 Andrew Cagney + + * cpu.h, cpu.c (cpu_synchronize_context): Add CIA argument as + reference point. + + * vm.c (vm_synchronize_context): Add PROCESSOR and CIA as + arguments so that there is a reference point for recovery. + (vm_synchronize_context): Pass processor+cia for errors. + (om_unpack_sr): Ditto. + (om_unpack_srs): Ditto. + * vm.c (vm_create): Review error messages. + + * vm.c: Include "cpu.h" so that cpu_error is visible. + + * ppc-instructions (Return From Interrupt): Pass CIA. + (Instruction Synchronize): Ditto. + * psim.c (psim_init): Ditto. + +Wed Jan 15 12:25:11 1997 Andrew Cagney + + * cpu.h, cpu.c (cpu_error): Aborts simulation with error message, + but also saves current processor state. + + * basics.h: Move #include to here from device_table.h. + + * interrupts.c (perform_oea_interrupt): Use. No longer loose CIA + when simulation aborted. + (program_interrupt): Ditto. + (floating_point_unavailable_interrupt): Ditto. + (alignment_interrupt): Ditto. + (floating_point_assist_interrupt): Ditto. + (perform_oea_interrupt): Ditto. + (machine_check_interrupt): Ditto. + +Tue Jan 14 12:19:10 1997 Andrew Cagney + + * ppc-instructions (Move from Special Purpose Register): Support + move from DEC. + +Mon Jan 13 16:58:12 1997 Andrew Cagney + + * debug.h, debug.c: Add "interrupts" trace option. + + * interrupts.c (data_storage_interrupt): Add tracing. + (machine_check_interrupt): Ditto. + (instruction_storage_interrupt): Ditto. + (alignment_interrupt): Ditto. + (program_interrupt): Ditto. + (floating_point_unavailable_interrupt): Ditto. + (system_call_interrupt): Ditto. + (floating_point_assist_interrupt): Ditto. + (deliver_hardware_interrupt): Ditto. + + * interrupts.c (program_interrupt): For UEA mode, halt the + processor - so that the current state is saved - instead of + aborting. + (floating_point_unavailable_interrupt): Ditto. + (floating_point_assist_interrupt): Ditto. + +Thu Jan 2 09:10:41 1997 Andrew Cagney + + * interrupts.c (perform_oea_interrupt): Halt rather than abort on + a double interrupt. + +Wed Jan 1 22:54:52 1997 Andrew Cagney + + * ppc-instructions (Store Multiple Word, Load Multiple Word): + Enable. + + * tree.c (print_properties): For an array consider printing it out + as an integer array. + + * hw_memory.c (hw_memory_init_address): If an "available" property + is present, use that to initialize the available memory instead of + using the reg property. + + * emul_generic.c (emul_add_tree_hardware): Add "available" + property to memory device. + +Fri Dec 20 13:19:07 1996 Andrew Cagney + + * ppc-instructions (Rotate Left Word then AND with Mask): Enable. + + * device.c (device_instance_call_method): Was only looking at the + first method. + + * hw_disk.c (hw_disk_nr_blocks): Implement #blocks method. + (hw_disk_block_size): Implement block-size method. + (hw_disk_max_transfer): Implement max-transfer method. + + * hw_phb.c (hw_phb_init_address): Reinit the rest of the PHB. + + * emul_chirp.c (chirp_emul_instance_to_path): Recover from an + invalid ihandle. + (chirp_emul_instance_to_package): Ditto. + (chirp_emul_method): Ditto. + (chirp_emul_read): Ditto. + (chirp_emul_write): Ditto. + (chirp_emul_close): Ditto. + (chirp_emul_seek): Ditto. + (chirp_emul_package_to_path): Ditto (for phandle). + (chirp_emul_package_to_path): Return the length. + + * psim.c (psim_merge_device_file): Allow continuation lines. + +Thu Dec 19 11:09:43 1996 Andrew Cagney + + * emul_chirp.c (chirp_emul_boot): Implement. Well report the new + string and exit. + + * emul_chirp.c (chirp_emul_exit): Correct type of args struct + members - *_cell not host dependant int. + +Wed Dec 18 17:49:59 1996 Andrew Cagney + + * interrupts.c (perform_oea_interrupt): Print additional + information if a double interrupt is encountered. + +Wed Dec 18 17:49:59 1996 Andrew Cagney + + * psim.c (psim_merge_device_file): Tolerate an incorrect file-name + being specified with the -f option. + (psim_merge_device_file): Correct check for end of string. + +Wed Dec 18 17:49:59 1996 Andrew Cagney + + * emul_chirp.c (chirp_emul_peer): Was falling off the end of the + list of devices. Return zero to the client instead. + * emul_chirp.c (chirp_emul_child): Ditto + * emul_chirp.c (chirp_emul_parent): Ditto + + * device.c (device_root): Assert assumption about the device being + valid. + +Tue Dec 17 15:12:38 1996 Andrew Cagney + + * emul_chirp.c (emul_chirp_create): Add description property to + each significant node in the device tree. + * emul_bugapi.c (emul_bugapi_create): Ditto. + +Fri Dec 13 14:30:31 1996 Andrew Cagney + + * main.c (sim_io_read_stdin): For a single byte STDIO read, use a + tempoary two byte buffer. Single byte read with fgets will not + work. + * main.c: Include errno.h. + (sim_io_read_stdin): For non-STDIO, make it work. + + * emul_chirp.c (chirp_emul_read): Return the correct error status. + +Fri Dec 13 14:30:31 1996 Andrew Cagney + + * std-config.h (WITH_STDIO): Don't hard-wire the STDIO mechanism. + Instead have each emulation default it to DO_USE_STDIO. + + * emul_generic.c (emul_add_tree_options): Select the STDIO I/O + mechanism as the default if enabled or if nothing selected. + + * sim_calls.c (sim_io_read_stdin): Passify GCC's desire for a + return value. + (sim_io_write_stdout): Ditto. + (sim_io_write_stderr): Ditto. + * main.c (sim_io_write_stdout): Ditto. + (sim_io_write_stderr): Ditto. + (sim_io_read_stdin): Ditto. + +Tue Dec 10 10:31:48 1996 Michael Meissner + + * emul_chirp.c (emul_chirp_instruction_call): Make *printf calls + type correct. + * vm.c (om_effective_to_virtual): Ditto. + * events.c (event_queue_schedule{,_after_signal}): Ditto. + (event_queue_{deschedule,process}): Ditto. + * hw_htab.c (htab_decode_hash_table): Ditto. + (htab_map_{page,binary}): Ditto. + * hw_opic.c (hw_opic_init_data): Ditto. + (handle_interrupt): Ditto. + (do_processor_init_register_{read,write}): Ditto. + (write_vector_priority_register): Ditto. + ({read,write}_destination_register): Ditto. + (do_suprious_vector_register_{read,write}): Ditto. + (do_current_task_priority_register_N_{read,write}): Ditto. + (do_timer_frequency_reporting_register_{read,write}): Ditto. + (do_timer_N_{current,base}_count_register_{read,write}): Ditto. + (do_ipi_N_dispatch_register_write): Ditto. + (do_vendor_identification_register_read): Ditto. + (do_feature_reporting_register_N_read): Ditto. + (do_global_configuration_register_N_{read,write}): Ditto. + * hw_phb.c (hw_phb_attach_address): Ditto. + (hw_phb_unit_decode): Ditto. + (hw_phb_address_to_attach_address): Ditto. + (hw_phb_io_{read,write}_buffer): Ditto. + * hw_ide.c (setup_fifo): Ditto. + + * sim_calls.c ({defs,callback,remote-sim}.h): Find gdb include + files via -I instead of using "../../gdb/" prefixes. + +Tue Dec 10 10:12:44 1996 Andrew Cagney + + * debug.h: Add tracing for the pal device. + * hw_pal.c: Update. + + * emul_chirp.c (chirp_emul_getprop): More tracing. + +Tue Dec 10 10:12:44 1996 Andrew Cagney + + * device.h, device.c (device_find_ihandle_runtime_property): New + function. Reverse of add_ihandle_runtime property. + (device_init_runtime_properties): Use it. + + * device.c (find_property_entry): New function returns the + internal property spec. + (device_set_property): Use. + (device_find_property): Use. + +Tue Dec 10 10:12:44 1996 Andrew Cagney + + * psim.c (psim_merge_device_file): Strip newline from device + specs. + +Tue Dec 10 10:12:44 1996 Andrew Cagney + + * hw_htab.c (htab_map_binary): For overlapping text / data maps + merge the two. Also check that the merge is safe. + + * emul_chirp.c (emul_chirp_create): Add a description property to + the pte's so that they are easier to identify. + + (emul_chirp_create): Don't specify a load address for the CHRP + image. Always use the values specified by the executable. + + * hw_htab.c (htab_map_page): Abort if a duplicate map is + encountered. + +Mon Dec 9 12:08:46 1996 Andrew Cagney + + * hw_htab.c (htab_map_page): Formatting. + + * emul_chirp.c (emul_chirp_instruction_call): Check for a NULL + method name when handling the client call. Also check for other + bad call arguments. + + * emul_chirp.c (emul_chirp_create): Allow real-mode?, real-base, + etc to be overriden. + +Mon Dec 9 12:08:46 1996 Andrew Cagney + + * os_emul.c (os_emul_create): Use tree find property instead of + device find property - sigh. + +Thu Dec 5 10:46:42 1996 Andrew Cagney + + * 961205: Release snapshot 961205. + +Thu Dec 5 10:46:42 1996 Andrew Cagney + + * configure.in (hostbitsize, bitsize): Fix typo in error message - + cannot contain a comma. + (sim-warnings): Check for more potential errors. + + * psim.c (psim_usage): Add -f option. Specifies a file + containing device tree specifications that should be merged into + the device tree. + + * configure.in: Sort options. + * configure: Rebuild + +Wed Dec 4 13:57:31 1996 Andrew Cagney + + * psim.c (psim_usage): Add -n option - specify number of + processors. + + * emul_chirp.c: Add description. + * emul_bugapi.c: Ditto. + * emul_unix.c: Ditto. + * emul_netbsd.c: Ditto. + +Fri Nov 29 11:12:22 1996 Andrew Cagney + + * hw_pal.c (hw_pal_attach_address): New function, if an attach is + encountered, assume that it is the single disk. + * hw_pal.c: Add generic device/size decode methods. + + * hw_nvram.c (hw_nvram_init_address): Use the first nonzero reg + property entry when determining the nvram size. + + * hw_core.c: Add generic address/size decode methods. + + * emul_chirp.c (emul_chirp_instruction_call): Return and trace + nonzero status from client functions. + + * main.c (error): Always include a cariage return when writing out + errors. + Wed Nov 20 00:36:55 1996 Doug Evans - * Makefile.in (LIBCOMMON): Define. - ($(TARGETLIB)): Add files from $(LIBCOMMON). + * sim_calls.c (sim_resume): Reset sim_should_run if single + stepping. + +Thu Nov 28 13:19:46 1996 Andrew Cagney + + * emul_bugapi.c (emul_bugapi_do_diskio): Add support for multiple + optional disks. + + * emul_generic.c (emul_add_tree_hardware): Drop the dummy eeprom. + Attach the pal - for I/O - as a pseudo device haning from the + firmware sub tree. + + * emul_bugapi.c (emul_bugapi_create): Add a small memory device to + the device tree at the address of the hi-mem interrupt vector + addreses. Used by bugapi to establish its trap instructions. + + * debug.h: Add a new macro DITRACE for tracing device instances. + + * debug.h: Extend the DTRACE macro so that it can also tests for + device specific tracint. + + * device.h, device.c (device_trace): Add method to determine + device specific tracing. + (device_init_address): Set the devices tracing level. + +Thu Nov 21 12:05:32 1996 Andrew Cagney + + * tree.h, tree.c (tree_device): New files - separate out the + device parser and other tree operations from the device. + + * inline.h, inline.c (INLINE_TREE): Add. + * device.h, device.c (device_tree_add_parsed): Delete. + * Makefile.in (tree.c): Add rules for new file. + * Makefile.in: Better order the emul_* files. + + * emul_generic.c (emul_add_tree_hardware): Update. + * emul_netbsd.c (emul_netbsd_create): Update. + * emul_unix.c (emul_unix_create): Ditto. + * emul_chirp.c (emul_chirp_create): Ditto. + * emul_bugapi.c (emul_bugapi_create): Ditto. + * psim.c (psim_tree): Ditto. + * hw_init.c: Ditto. + + * emul_generic.h: Include tree.h + * Makefile.in: Add to EMUL_GENERIC_H dependencies. + + * device.h, device.c (device_root): New function - returns the + root of the tree. + * corefile.c: Use. + + * device.h, device.c (device_clean): New function, clean up device + ready for next simulation run. This includes things like deleting + interrupt edges and properties created during the simulation and + also scrubbing any pre-defined properties. + * tree.c (tree_init): Use. + + * device.h, device.c (device_init_static_properties): New + function. Initialize any static predefined properties. By static + we mean those that have values that can be determined before the + device tree initialization has started. + * tree.c (tree_init): Use. + + * device.h, device.c (device_init_address): Add code to + check/verify the devices #address-cells and #size-cells. + (device_add_integer_property): Delete corresponding code. + (device_nr_address_cells, device_nr_data_cells): Check for + property when returning value. + + * device.h, device.c (device_init_runtime_properties): New + function. Initialize those properties that are not `static'. At + present the only such property is the ihandle. + * tree.c (tree_init): Use. + + * device.h, device.c (reg, ranges): Rework these so that they use + an array of the fundamental type - single reg or single range + entry. + + * device.h, device.c (device_add_ihandle_runtime_property): + Re-implement the adding of an ihandle during tree construction so + that it better fits in with device initialization. + +Thu Nov 21 12:05:32 1996 Andrew Cagney + + * device.h, device.c (device_ioctl): Add additional argument - + request - so that the caller must always specify the type of + the ioctl request. + + * device_table.h: Update. + * hw_trace.c (hw_trace_ioctl): Ditto. + * hw_vm.c (hw_vm_ioctl_callback): Ditto. + * hw_init.c (hw_stack_ioctl_callback): Ditto. + * psim.c (psim_options): Ditto. + +Thu Nov 21 12:05:32 1996 Andrew Cagney + + * BUGS: Updated a bit. + +Wed Nov 20 14:06:37 1996 Andrew Cagney + + * hw_opic.c: Finish - third round. - * sim_calls.c (sim_resume): Reset sim_should_run if single stepping. +Wed Nov 20 12:02:08 1996 Andrew Cagney + * hw_glue.c (hw_glue_io_read_buffer_callback): Fix miscalc of glue + reg index. + (hw_glue_io_write_buffer_callback): Ditto. + +Tue Nov 19 21:17:08 1996 Andrew Cagney + + * events.c (event_queue_process): Was incorrectly consuming future + events on the queue when they should be left alone. + + * debug.h, debug.c (events): Add support for event queue tracing. + * events.c: Add event tracing. + + * debug.h, debug.c: Order device trace options. + Fri Nov 15 15:23:39 1996 Michael Meissner * pk_disklabel.c (pk_disklabel_create_instance): Fix up some warnings generated by GCC. +Sun Nov 17 17:59:14 1996 Andrew Cagney + + * sim-endian.h: Add LE versions of byte swap macros. Needed for + PCI devices which are little-endian. + + * sim-endian-n.h (endian_le2h_N, endian_h2le_N): Ditto + +Sun Nov 17 17:59:14 1996 Andrew Cagney + + * hw_iobus.c (hw_iobus_attach_address_callback): Change the iobus + so that it is implementing a 1-1 address map. + + * emul_generic.c (emul_add_tree_hardware): Adjust. + + * emul_generic.c (emul_add_tree_hardware): Don't add the nvram as + a default. + +Sun Nov 17 17:59:14 1996 Andrew Cagney + + * device.c (split_find_device): Be tolerant of missing unit + addresses. + +Fri Nov 15 16:49:49 1996 Andrew Cagney + + * basics.h (port_direction): New type, specify the direction of + any `port'. + + * device.h, device.c (device_interrupt_decode): Include + specification of port direction in operations. + (device_interrupt_encode): Ditto. + + * device_table.h: Add a direction field to the interrupt port + table. + + * device.c (device_tree_add_parsed): Specify port direction. + +Thu Nov 14 21:38:13 1996 Andrew Cagney + + * hw_opic.c: Finish - second round. + +Thu Nov 7 00:18:59 1996 Andrew Cagney + + * hw_htab.c (htab_init_data_callback): Allow the virtual-address + to be specified as an array which allows 64bit addresses. + + * device.c (device_find_integer_array_property): New function. + Simplify the querying of elements of an integer array. + (device_add_integer_property, device_find_integer_property): + Update to correctly use the cell type. + + * vm.c (om_unpack_sr): Clarify shifting comment. + (om_pte_0_masked_vsid): Ditto. Add 64bit version. + + * emul_chirp.c (emul_chirp_create): Initialize the segment + registers. + + * vm.c (om_effective_to_virtual): Trace segment register use. + + * hw_htab.c (htab_map_page): Print out the pteg base address to + simplify cross checking between vm and the htab. + (htab_decode_hash_table): Use device_error instead of error. + (htab_map_page): Ditto. + (htab_dma_binary): Ditto. + (htab_map_binary): Ditto. + (htab_init_data_callback): Ditto. + +Wed Nov 6 20:20:58 1996 Andrew Cagney + + * interrupts.h: Clarify what the optional instruction program + interrupt is - a subset of illegal instruction program interrupt. + + * interrupts.c (program_interrupt): For UEA mode, clarify what an + optional instruction program interrupt is. + (program_interrupt): For OEA mode, as per spec, generate an + illegal instruction program interrupt when an optional instruction + is encountered. + + * gen-semantics.c (print_semantic_body): Delete code + differentiating between an unimplemented floating point and normal + instruction. Instead, such a case can be handled explicitly. + + * ppc-instructions (store floating-point as integer word indexed): + Mark as optional. + (Floating Convert to Integer Doubleword): Make the floating point + assist interrupt explicit. + (Floating Convert To Integer Doubleword with round towards Zero): + Ditto. + (Floating Convert To Integer Word): Ditto + (Move From FPSCR): Ditto. + (Move to Condition Register from FPSCR): Ditto. + (Move To FPSCR Fields): Ditto. + (Move To FPSCR Field Immediate): Ditto. + (Move To FPSCR Bit 0): Ditto. + (Move To FPSCR Bit 1): Ditto. + +Mon Nov 4 12:49:13 1996 Andrew Cagney + + * corefile.c (core_map_read_buffer, core_map_write_buffer): Avoid + breaking up transfers. + + * corefile.c: Adjust arguments so that the client server + relationship is clarified. + + * hw_glue.c (hw_glue_init_address): Update so it can be attached + to a PCI bus. + + * hw_disk.c (hw_disk_instance_write): Add more checks to disk IO - + looking for things like overflow/underflow. + +Sun Nov 3 18:45:20 1996 Andrew Cagney + + * emul_generic.c (emul_add_tree_hardware): Hang the disk off the + PAL device instead of the IOBUS. The disk must be attached to a + logical bus. + + * hw_disk.c (hw_disk_init_address): Just use the unit address + directly in the attach - the rest isn't relevant. + +Sat Nov 2 21:48:57 1996 Andrew Cagney + + * configure.in (sim-hardware, sim-packages): Allow additional + hardware and packages to be prefixed as well as appended. + + * Makefile.in (tmp-hw, tmp-pk): Retain the user specified order of + packages when building them. Consequently, a user can override a + standard device by prefixing their own version. + + * Makefile.in (hw_opic.o, hw_pci.o, hw_ide.o): Add dependencies. + Fri Nov 1 14:42:57 1996 Michael Meissner * mon.c (_cpu_mon): Add fields for counting 1, 2, 4, and 8 byte @@ -29,6 +788,139 @@ Tue Oct 29 17:55:43 1996 Michael Meissner (solaris_descriptors): Make sigaltstack and sigaction nops. ({solaris,linux}_descriptors): Add support for access. +Tue, 8 Oct 18:42:26 1996 Jason Molenda + + * Makefile.in (clean): Move config.log to distclean. + +Fri Nov 1 16:44:28 1996 Andrew Cagney + + * corefile-n.h (core_map_write_N): Improve abort messages. + + * device.h, device.c (device_attach_address): Remove unused name + parameter. + (device_detach_address): Ditto. + * device_table.h, device_table.c: Update. + * hw_iobus.c (hw_iobus_attach_address_callback): Ditto. + * hw_nvram.c (hw_nvram_init_address): Ditto. + * hw_memory.c (hw_memory_init_address): Ditto. + * hw_vm.c (hw_vm_init_address_callback): Ditto. + (hw_vm_attach_address): Ditto. + (hw_vm_add_space): Ditto. + * hw_init.c (update_for_binary_section): Ditto. + * hw_core.c (hw_core_attach_address_callback): Ditto. + + * hw_iobus.c (hw_iobus_attach_address_callback): Rewrite to handle + configurable parent busses. + +Wed Oct 30 18:46:32 1996 Andrew Cagney + + * device_table.c (generic_device_size_to_attach_size): Provide + limited support for multi-cell sizes. + (generic_device_address_to_attach_address): Ditto for addresses. + +Tue Oct 29 02:01:29 1996 Andrew Cagney + + * device.c (device_add_integer_property): Check for setting of + #address-cells and #size-cells properties. For these, update the + corresponding device values. + (device_nr_address_cells, device_nr_size_cells): Use the value + from the device instead of the property. + + * hw_core.c: Use generic address and size conversions for the top + bus. + + * hw_memory.c (hw_memory_init_address): Tolerate case where + #address and #size cells is greater than 1. + + * device.c (device_tree_print_device): Clean out printing of + properties. + + * device.c (split_device_specifier): Don't detect comments here - + "#" can be a valid prefix - eg #size-cells. + + * psim.c (psim_merge_device_file): Suppress comments and blank + lines here. + + * emul_generic.c (emul_add_tree_hardware): Fix typo of incorrect + pal unit address. Add the property /#address-cells to the root of + the tree. + + * device.c (device_template_create_device): Check that the unit + address was successfully parsed. + + * device_table.c (generic_device_unit_decode): Rewrite to better + handle multi-cell addresses. + (generic_device_unit_encode): Ditto. + + * emul_generic.c (emul_add_tree_hardware): "reg" properties no + longer need the explicit array type - the parser takes care of it. + + * pk_disklabel.c (pk_disklabel_create_instance): Add NULL return + to keep GCC happy. + +Mon Oct 28 22:55:48 1996 Andrew Cagney + + * hw_ide.c: New file. Model of a basic IDE interface attached to + a PCI bus. + + * configure.in (hardware): Add the ide device to the default + configuration. + * configure: Regenerate. + + * debug.h, debug.c: Add tracing option for the IDE device. + +Fri Oct 25 21:28:25 1996 Andrew Cagney + + * hw_phb.c, hw_phb.h: New files - implement a PHB. + + * configure.in (hardware): Add the phb to the list of devices to + build by default. + +Fri Oct 25 21:28:25 1996 Andrew Cagney + + * hw_com.c: Review description. + * hw_disk.c: Ditto. + * hw_htab.c: Ditto. + * hw_eeprom.c: Ditto. + * hw_init.c: Ditto. + * hw_cpu.c: Ditto. + + * hw_com.c: Update event handling. + + * hw_disk.c: Implement tracing. + +Fri Oct 25 21:28:25 1996 Andrew Cagney + + * device_table.c (generic_device_init_address): Use + assigned-addresses property in preference to any other reg + property. + +Fri Oct 25 21:28:25 1996 Andrew Cagney + + * device.h, device.c (device_find_ranges_property): New function. + Simplify the manipulation of "ranges" properties. + + * device.c (device_add_parsed): Extend to include support for the + ranges property. + + * device.c (device_add_parsed): Add assigned-addresses to the list + of reg type properties. + + * device.c (device_tree_print_device): Add code to format and + print a ranges property. + + * device.h, device.c (device_nr_address_cells, + device_nr_size_cells): New functions. Determine the values of the + standard properties #address-cells and #size-cells. Both of which + are optional and have default values of two and one respectfuly. + Previously, code that determined #address-cells was incorrectly + using a value of one. + +Fri Oct 25 21:28:25 1996 Andrew Cagney + + * debug.h, debug.c: Sort debug options, Add entries for the + comming PHB device. + Fri Oct 18 12:12:21 1996 Michael Meissner * ppc-instructions (Floating Select): Add support for fsel unless @@ -52,9 +944,108 @@ Fri Oct 18 12:12:21 1996 Michael Meissner information on program interrupts, particularly in user mode. Add support for optional_instruction_program_interrupt. -Thu Oct 3 16:15:20 1996 Jason Molenda (crash@godzilla.cygnus.co.jp) +Wed Sep 25 10:20:29 1996 Andrew Cagney - * Makefile.in (clean): Move config.log to distclean. + * hw_glue.c: New device. Hooks for manipulating interrupt ports. + + * debug.h, debug.c (trace_glue_device): Add tracing support for + the interrupt glue logic device. + + * configure.in (hardware): Add glue device. + * configure: Regenerate. + +Tue Sep 24 20:55:38 1996 Andrew Cagney + + * device.c (device_tree_parse_integer_property): New function, + parse a list of integers as an array property. + (device_tree_add_parsed): Call it. + + * device.c (device_tree_parse_string_property): New function, + parse a list of strings as a string property (with embeded + null's). For moment, don't try to implement a complext string + parser. + (device_tree_add_parsed): Call it. + +Tue Sep 24 16:30:48 1996 Andrew Cagney + + * hw_opic.c: New file. OpenPIC interrupt controller. + + * configure.in (hardware): Add opic device. + * configure: re-generate. + + * hw_pic.c: Delete, replaced with hw_opic.c. + + * debug.h, debug.c: Add debug option for OpenPIC device. - + opic-device. + +Tue Sep 24 16:30:48 1996 Andrew Cagney + + * Makefile.in (psim.o, idecode.o): Since idecode and not psim is + now the file that does all the inlining. + + * Makefile.in (LIB_SRC, LIB_INLINE_SRC, idecode.o): Break out the + library source code that could be involved in an inlining. Make + idecode.o only dependant on the inlined library source code. + + * Makefile.in (LIB_OBJ): Put options last on the list so that it + is compiled last. + + * std-config.h (DEVICE_INLINE): Only inline locals when the + default is to inline. + +Mon Sep 23 00:37:49 1996 Andrew Cagney + + * hw_htab.c (htab_sum_binary): Determine the real-base for the + binary. + + * hw_htab.c (htab_map_binary): Depending on the value of the + load-base, either map the program in as a contiguous section or as + separate sections controled by th binaries lma values. + (htab_init_data_callback): Ditto. + +Sun Sep 22 15:56:22 1996 Andrew Cagney + + * emul_generic.c (emul_add_tree_options): Remove load-base option. + + * emul_chirp.c (map_over_chirp_note): Add load_base field to note + struct. Don't require the load_base field to be present - just + issue warning - it is a recent addition. + (emul_chirp_create): Support both virtual and physical modes. + + * emul_chirp.c (emul_chirp_create): Add a stack initialization + property so that any arguments specified on the command line can + be passed on to user programs. + + * hw_init.c (create_ppc_chirp_bootargs): Add support for chirp + argument passing to the pseudo device stack. + +Sat Sep 21 19:39:56 1996 Andrew Cagney + + * device.c (device_error): Make it more tolerant to incomplete + devices. + + * hw_init.c (hw_data_init_data_callback): Extend the data device + so that it can perform initialization operations either dma or a + more complex instance open, seek, write operation. + * hw_init.c: Update the description of the data device to reflect + this. + +Sat Sep 21 00:13:02 1996 Andrew Cagney + + * device.c (device_event_queue_schedule, + device_event_queue_deschedule, device_event_queue_time): Have the + device object export the event operations. Making these available + from the device object should hopefully simplify writing device + models. + +Fri Sep 20 14:04:40 1996 Andrew Cagney + + * configure.in (sim-hardware): Add eeprom device to default build. + + * hw_eeprom.c: Rewrite so it works. + + * debug.h, debug.c: Add tracing support for the eeprom and com + devices. Thu Sep 19 14:40:40 1996 Andrew Cagney diff --git a/sim/ppc/Makefile.in b/sim/ppc/Makefile.in index 1d36f655f77..b14084e189b 100644 --- a/sim/ppc/Makefile.in +++ b/sim/ppc/Makefile.in @@ -196,12 +196,14 @@ DEVICE_TABLE_H = \ $(BASICS_H) \ device_table.h \ device.h \ + tree.h \ hw.h EMUL_GENERIC_H = \ $(CPU_H) \ $(IDECODE_H) \ emul_generic.h \ + tree.h \ os_emul.h @@ -227,7 +229,7 @@ BUILT_SRC = \ config.h \ ppc-config.h -LIB_SRC = \ +LIB_INLINE_SRC = \ psim.c \ bits.c \ debug.c \ @@ -239,21 +241,20 @@ LIB_SRC = \ corefile.c \ events.c \ os_emul.c \ - emul_generic.c \ - emul_netbsd.c \ - emul_unix.c \ - emul_chirp.c \ - emul_bugapi.c \ registers.c \ cpu.c \ interrupts.c \ device.c \ + tree.c \ device_table.c \ cap.c \ mon.c \ - options.c \ + options.c + +LIB_SRC = \ $(PACKAGE_SRC) \ - $(HW_SRC) + $(HW_SRC) \ + $(LIB_INLINE_SRC) MAIN_SRC = \ main.c \ @@ -269,10 +270,10 @@ LIB_OBJ = \ sim-endian.o \ os_emul.o \ emul_generic.o \ + emul_bugapi.o \ + emul_chirp.o \ emul_netbsd.o \ emul_unix.o \ - emul_chirp.o \ - emul_bugapi.o \ registers.o \ vm.o \ corefile.o \ @@ -283,6 +284,7 @@ LIB_OBJ = \ events.o \ cap.o \ device.o \ + tree.o \ device_table.o \ itable.o \ mon.o \ @@ -291,9 +293,9 @@ LIB_OBJ = \ idecode.o \ support.o \ psim.o \ - options.o \ $(PACKAGE_OBJ) \ - $(HW_OBJ) + $(HW_OBJ) \ + options.o GDB_OBJ = sim_calls.o @@ -317,9 +319,7 @@ $(TARGETLIB): tmp-igen tmp-dgen tmp-hw tmp-pk $(LIB_OBJ) $(GDB_OBJ) $(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ) $(RANLIB) $(TARGETLIB) -# Given that inlines are turned on now, rebuild psim whenever -# anything changes. -psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) +psim.o: psim.c psim.h tree.h $(CPU_H) $(IDECODE_H) bits.o: bits.c $(BASICS_H) @@ -331,10 +331,10 @@ sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H) os_emul.o: os_emul.c emul_netbsd.h emul_unix.h emul_chirp.h emul_bugapi.h $(EMUL_GENERIC_H) emul_generic.o: emul_generic.c $(EMUL_GENERIC_H) +emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H) +emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H) emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H) emul_unix.o: emul_unix.c emul_unix.h $(EMUL_GENERIC_H) -emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H) -emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H) registers.o: registers.c $(REGISTERS_H) $(BASICS_H) @@ -342,13 +342,14 @@ cpu.o: cpu.c $(CPU_H) $(IDECODE_H) interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) os_emul.h -idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h +# Given that inlines are turned on now, rebuild idecode whenever +# anything changes. +idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h $(LIB_INLINE_SRC) $(BUILT_SRC) $(CC) -c $(NOWARN_CFLAGS) $< # double.o: double.c dp-bit.c -vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \ - device.h corefile.h interrupts.h itable.h mon.h +vm.o: vm.c vm.h vm_n.h $(CPU_H) corefile.o: corefile.c corefile.h corefile-n.h $(BASICS_H) $(DEVICE_TABLE_H) @@ -364,6 +365,8 @@ main.o: main.c $(PSIM_H) itable.h options.h device.o: device.c $(DEVICE_TABLE_H) cap.h +tree.o: tree.c tree.h device.h $(DEVICE_TABLE_H) + device_table.o: device_table.c $(DEVICE_TABLE_H) events.h hw.c cap.o: cap.c cap.h $(BASICS_H) @@ -381,9 +384,12 @@ itable.o: itable.c itable.h mon.o: mon.c $(CPU_H) # Rebuild options whenever something changes so the date/time is up to date. -options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile +options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile defines.h $(CC) -c $(STD_CFLAGS) '-DOPCODE_RULES="@sim_opcode@"' '-DIGEN_FLAGS="$(IGEN_FLAGS)"' '-DDGEN_FLAGS="$(DGEN_FLAGS)"' $< +defines.h: config.h Makefile + rm -f defines.h + sed -n -e '/^#define HAVE_/s/ 1$$/",/' -e '/^#define HAVE_/s//"HAVE_/p' < config.h > defines.h # # Rules to create the built c source code files # @@ -510,13 +516,13 @@ misc.o: misc.c misc.h filter_filename.h # real hardware tmp-hw: Makefile $(HW_SRC) $(srcdir)/../../move-if-change for hw in $(HW_SRC) ; do echo $$hw ; done \ - | sort -u \ + | cat -n | sort +1 -u | sort -n \ | sed -e 's/^.*\(hw_.*\)\.c/\1/' \ -e 's/^/extern const device_descriptor /' \ -e 's/$$/_device_descriptor\[\];/' \ > tmp-hw.h for hw in $(HW_SRC) ; do echo $$hw ; done \ - | sort -u \ + | cat -n | sort +1 -u | sort -n \ | sed -e 's/^.*\(hw_.*\)\.c/\1/' \ -e 's/^/ /' \ -e 's/$$/_device_descriptor,/' \ @@ -526,17 +532,21 @@ tmp-hw: Makefile $(HW_SRC) $(srcdir)/../../move-if-change touch tmp-hw hw_cpu.o: hw_cpu.c $(DEVICE_TABLE_H) +hw_core.o: hw_core.c $(DEVICE_TABLE_H) +hw_disk.o: hw_disk.c $(DEVICE_TABLE_H) pk.h +hw_glue.o: hw_glue.c $(DEVICE_TABLE_H) +hw_htab.o: hw_htab.c $(DEVICE_TABLE_H) +hw_ide.o: hw_ide.c $(DEVICE_TABLE_H) +hw_init.o: hw_init.c $(DEVICE_TABLE_H) +hw_iobus.o: hw_iobus.c $(DEVICE_TABLE_H) hw_memory.o: hw_memory.c $(DEVICE_TABLE_H) hw_nvram.o: hw_nvram.c $(DEVICE_TABLE_H) -hw_iobus.o: hw_iobus.c $(DEVICE_TABLE_H) -hw_core.o: hw_core.c $(DEVICE_TABLE_H) +hw_opic.o: hw_opic.c $(DEVICE_TABLE_H) hw_pal.o: hw_pal.c $(DEVICE_TABLE_H) -hw_htab.o: hw_htab.c $(DEVICE_TABLE_H) -hw_disk.o: hw_disk.c $(DEVICE_TABLE_H) pk.h -hw_trace.o: hw_trace.c $(DEVICE_TABLE_H) +hw_phb.o: hw_phb.c $(DEVICE_TABLE_H) hw_phb.h hw_register.o: hw_register.c $(DEVICE_TABLE_H) +hw_trace.o: hw_trace.c $(DEVICE_TABLE_H) hw_vm.o: hw_vm.c $(DEVICE_TABLE_H) -hw_init.o: hw_init.c $(DEVICE_TABLE_H) # ignore this line, it stops make from getting confused @@ -544,8 +554,8 @@ hw_init.o: hw_init.c $(DEVICE_TABLE_H) # real packages tmp-pk: Makefile $(PACKAGE_SRC) $(srcdir)/../../move-if-change for pk in $(PACKAGE_SRC) ; do echo $$pk ; done \ - | sort -u \ - | sed -e 's/^pk_\(.*\)\.c/\1/' \ + | cat -n | sort +1 -u | sort -n \ + | sed -e 's/^.*pk_\(.*\)\.c/\1/' \ -e 's/^/extern package_create_instance_callback pk_/' \ -e 's/$$/_create_instance;/' \ > tmp-pk.h @@ -563,10 +573,10 @@ TAGS: $(BUILT_SRC) etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC) clean mostlyclean: - rm -f tmp-* *.[oasi] core psim run igen dgen config.log $(BUILT_SRC_WO_CONFIG) + rm -f tmp-* *.[oasi] core psim run igen dgen $(BUILT_SRC_WO_CONFIG) distclean realclean: clean - rm -f TAGS Makefile config.cache config.status config.h stamp-h + rm -f TAGS Makefile config.cache config.status config.h defines.h stamp-h config.log maintainer-clean: distclean rm -f *~ *.log ppc-config.h core *.core diff --git a/sim/ppc/configure b/sim/ppc/configure index c405a5745a1..5dd42c89004 100755 --- a/sim/ppc/configure +++ b/sim/ppc/configure @@ -1,7 +1,7 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.10 +# Generated automatically using autoconf version 2.12 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation @@ -12,73 +12,73 @@ ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help - --enable-sim-cflags=opts Extra CFLAGS for use in building simulator" + --enable-sim-alignment=align Specify strict or nonstrict alignment." ac_help="$ac_help - --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o" + --enable-sim-assert Specify whether to perform random assertions." ac_help="$ac_help - --enable-sim-line-nr=opts Generate extra CPP code that references source rather than generated code" + --enable-sim-bitsize=n Specify target bitsize (32 or 64)." ac_help="$ac_help - --enable-sim-config=file Override default config file" + --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums." ac_help="$ac_help - --enable-sim-opcode=which Override default opcode lookup." + --enable-sim-cflags=opts Extra CFLAGS for use in building simulator" ac_help="$ac_help - --enable-sim-switch Use a switch instead of a table for instruction call." + --enable-sim-config=file Override default config file" +ac_help="$ac_help + --enable-sim-default-model=which Specify default PowerPC to model." ac_help="$ac_help --enable-sim-duplicate Expand (duplicate) semantic functions." ac_help="$ac_help - --enable-sim-jump Jump between semantic code (instead of call/return)." + --enable-sim-endian=endian Specify target byte endian orientation." +ac_help="$ac_help + --enable-sim-env=env Specify target environment (operating, virtual, user)." ac_help="$ac_help --enable-sim-filter=rule Specify filter rules." ac_help="$ac_help - --enable-sim-icache=size Specify instruction cache size." + --enable-sim-float Specify whether to use host floating point or simulate." ac_help="$ac_help --enable-sim-hardware=list Specify the hardware to be included in the build." ac_help="$ac_help - --enable-sim-packages=list Specify the packages to be included in the build." -ac_help="$ac_help - --enable-sim-inline=inlines Specify which functions should be inlined." -ac_help="$ac_help - --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums." + --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64)." ac_help="$ac_help - --enable-sim-endian=endian Specify target byte endian orientation." + --enable-sim-hostendain=end Specify host byte endian orientation." ac_help="$ac_help - --enable-sim-regparm=nr-parm Pass parameters in registers instead of on the stack - x86/GCC specific." + --enable-sim-icache=size Specify instruction-decode cache size and type." ac_help="$ac_help - --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific." + --enable-sim-inline=inlines Specify which functions should be inlined." ac_help="$ac_help - --enable-sim-hostendain=end Specify host byte endian orientation." + --enable-sim-jump Jump between semantic code (instead of call/return)." ac_help="$ac_help - --enable-sim-smp=n Specify number of processors to configure for." + --enable-sim-line-nr=opts Generate extra CPP code that references source rather than generated code" ac_help="$ac_help - --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8)." + --enable-sim-model=which Specify PowerPC to model." ac_help="$ac_help - --enable-sim-bitsize=n Specify target bitsize (32 or 64)." + --enable-sim-model-issue Specify whether to simulate model specific actions" ac_help="$ac_help - --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64)." + --enable-sim-monitor=mon Specify whether to enable monitoring events." ac_help="$ac_help - --enable-sim-env=env Specify target environment (operating, virtual, user)." + --enable-sim-opcode=which Override default opcode lookup." ac_help="$ac_help - --enable-sim-timebase Specify whether the PPC timebase is supported." + --enable-sim-packages=list Specify the packages to be included in the build." ac_help="$ac_help - --enable-sim-alignment=align Specify strict or nonstrict alignment." + --enable-sim-regparm=nr-parm Pass parameters in registers instead of on the stack - x86/GCC specific." ac_help="$ac_help - --enable-sim-trace Specify whether tracing is supported." + --enable-sim-reserved-bits Specify whether to check reserved bits in instruction." ac_help="$ac_help - --enable-sim-assert Specify whether to perform random assertions." + --enable-sim-smp=n Specify number of processors to configure for." ac_help="$ac_help - --enable-sim-reserved-bits Specify whether to check reserved bits in instruction." + --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific." ac_help="$ac_help - --enable-sim-float Specify whether to use host floating point or simulate." + --enable-sim-stdio Specify whether to use stdio for console input/output." ac_help="$ac_help - --enable-sim-monitor=mon Specify whether to enable monitoring events." + --enable-sim-switch Use a switch instead of a table for instruction call." ac_help="$ac_help - --enable-sim-model=which Specify PowerPC to model." + --enable-sim-timebase Specify whether the PPC timebase is supported." ac_help="$ac_help - --enable-sim-default-model=which Specify default PowerPC to model." + --enable-sim-trace Specify whether tracing is supported." ac_help="$ac_help - --enable-sim-model-issue Specify whether to simulate model specific actions" + --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o" ac_help="$ac_help - --enable-sim-stdio Specify whether to use stdio for console input/output." + --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8)." # Initialize some variables set by options. # The variables have the same names as the options, with @@ -117,6 +117,8 @@ mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 ac_prev= for ac_option @@ -398,7 +400,7 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.10" + echo "configure generated by autoconf version 2.12" exit 0 ;; -with-* | --with-*) @@ -500,11 +502,14 @@ do done # NLS nuisances. -# Only set LANG and LC_ALL to C if already set. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). -if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h @@ -566,6 +571,7 @@ ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. @@ -611,11 +617,12 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:621: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in @@ -638,7 +645,7 @@ else ;; esac done - IFS="$ac_save_ifs" + IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then @@ -662,6 +669,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:673: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -690,6 +698,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:702: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -736,7 +745,47 @@ fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:750: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:784: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:789: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -745,7 +794,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:749: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -753,29 +802,34 @@ fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + if test $ac_cv_prog_gcc = yes; then GCC=yes - if test "${CFLAGS+set}" != set; then - echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:813: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then - ac_cv_prog_gcc_g=yes + ac_cv_prog_cc_g=yes else - ac_cv_prog_gcc_g=no + ac_cv_prog_cc_g=no fi rm -f conftest* fi -echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 - if test $ac_cv_prog_gcc_g = yes; then - CFLAGS="-g -O" - else - CFLAGS="-O" - fi +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" fi else GCC= @@ -784,83 +838,94 @@ fi # Put a plausible default for CC_FOR_BUILD in Makefile. -# If we cannot run a trivial program, we must be cross compiling. -echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_c_cross=yes -else -cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } -if test -s conftest && (./conftest; exit) 2>/dev/null; then - ac_cv_c_cross=no + +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' else - ac_cv_c_cross=yes + CC_FOR_BUILD=gcc fi + + +# Check whether --enable-sim-alignment or --disable-sim-alignment was given. +if test "${enable_sim_alignment+set}" = set; then + enableval="$enable_sim_alignment" + case "${enableval}" in + yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";; + no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";; + 0 | default | DEFAULT) sim_alignment="-DWITH_ALIGNMENT=0";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";; +esac +if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then + echo "Setting alignment flags = $sim_alignment" 6>&1 fi -rm -fr conftest* +else + sim_alignment="" fi -echo "$ac_t""$ac_cv_c_cross" 1>&6 -cross_compiling=$ac_cv_c_cross -if test "x$cross_compiling" = "xno"; then - CC_FOR_BUILD='$(CC)' +# Check whether --enable-sim-assert or --disable-sim-assert was given. +if test "${enable_sim_assert+set}" = set; then + enableval="$enable_sim_assert" + case "${enableval}" in + yes) sim_assert="-DWITH_ASSERT=1";; + no) sim_assert="-DWITH_ASSERT=0";; + *) { echo "configure: error: "--enable-sim-assert does not take a value"" 1>&2; exit 1; }; sim_assert="";; +esac +if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then + echo "Setting assert flags = $sim_assert" 6>&1 +fi else - CC_FOR_BUILD=gcc + sim_assert="" fi -# Check whether --enable-sim-cflags or --disable-sim-cflags was given. -if test "${enable_sim_cflags+set}" = set; then - enableval="$enable_sim_cflags" + +# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given. +if test "${enable_sim_bitsize+set}" = set; then + enableval="$enable_sim_bitsize" case "${enableval}" in - yes) sim_cflags="-O2 -fomit-frame-pointer";; - no) sim_cflags="";; - *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; + 32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";; + *) { echo "configure: error: "--enable-sim-bitsize was given $enableval. Expected 32 or 64"" 1>&2; exit 1; }; sim_bitsize="";; esac -if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then - echo "Setting sim cflags = $sim_cflags" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then + echo "Setting bitsize flags = $sim_bitsize" 6>&1 fi else - sim_cflags="" + sim_bitsize="" fi -# Check whether --enable-sim-warnings or --disable-sim-warnings was given. -if test "${enable_sim_warnings+set}" = set; then - enableval="$enable_sim_warnings" + +# Check whether --enable-sim-bswap or --disable-sim-bswap was given. +if test "${enable_sim_bswap+set}" = set; then + enableval="$enable_sim_bswap" case "${enableval}" in - yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes";; - no) sim_warnings="-w";; - *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;; + yes) sim_bswap="-DWITH_BSWAP=1";; + no) sim_bswap="-DWITH_BSWAP=0";; + *) { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";; esac -if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then - echo "Setting warning flags = $sim_warnings" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then + echo "Setting bswap flags = $sim_bswap" 6>&1 fi else - sim_warnings="" + sim_bswap="" fi -# Check whether --enable-sim-line-nr or --disable-sim-line-nr was given. -if test "${enable_sim_line_nr+set}" = set; then - enableval="$enable_sim_line_nr" + +# Check whether --enable-sim-cflags or --disable-sim-cflags was given. +if test "${enable_sim_cflags+set}" = set; then + enableval="$enable_sim_cflags" case "${enableval}" in - yes) sim_line_nr="";; - no) sim_line_nr="-L";; - *) { echo "configure: error: "--enable-sim-line-nr does not take a value"" 1>&2; exit 1; }; sim_line_nr="";; + yes) sim_cflags="-O2 -fomit-frame-pointer";; + no) sim_cflags="";; + *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; esac -if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then - echo "Setting warning flags = $sim_line_nr" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then + echo "Setting sim cflags = $sim_cflags" 6>&1 fi else - sim_line_nr="" + sim_cflags="" fi + # Check whether --enable-sim-config or --disable-sim-config was given. if test "${enable_sim_config+set}" = set; then enableval="$enable_sim_config" @@ -885,48 +950,22 @@ if test x"$silent" != x"yes"; then fi fi -# Check whether --enable-sim-opcode or --disable-sim-opcode was given. -if test "${enable_sim_opcode+set}" = set; then - enableval="$enable_sim_opcode" - case "${enableval}" in - yes|no) { echo "configure: error: "No value supplied for --enable-sim-opcode=file"" 1>&2; exit 1; };; - *) if test -f "${srcdir}/${enableval}"; then - sim_opcode="${enableval}" - elif test -f "${srcdir}/ppc-opcode-${enableval}"; then - sim_opcode="ppc-opcode-${enableval}" - else - { echo "configure: error: "File $enableval is not an opcode rules file"" 1>&2; exit 1; }; - sim_opcode="ppc-opcode-complex" - fi;; -esac -if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then - echo "Setting opcode flags = $sim_opcode" 6>&1 -fi -else - sim_opcode="ppc-opcode-complex" -if test x"$silent" != x"yes"; then - echo "Setting opcode flags = $sim_opcode" -fi -fi -# Check whether --enable-sim-switch or --disable-sim-switch was given. -if test "${enable_sim_switch+set}" = set; then - enableval="$enable_sim_switch" +# Check whether --enable-sim-default-model or --disable-sim-default-model was given. +if test "${enable_sim_default_model+set}" = set; then + enableval="$enable_sim_default_model" case "${enableval}" in - yes) sim_switch="-s";; - no) sim_switch="";; - *) { echo "configure: error: "--enable-sim-switch does not take a value"" 1>&2; exit 1; }; sim_switch="";; + yes|no) { echo "configure: error: "No value supplied for --enable-sim-default-model=model"" 1>&2; exit 1; };; + *) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";; esac -if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then - echo "Setting switch flags = $sim_switch" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then + echo "Setting default-model flags = $sim_default_model" 6>&1 fi else - sim_switch=""; -if test x"$silent" != x"yes"; then - echo "Setting switch flags = $sim_switch" 6>&1 -fi + sim_model="" fi + # Check whether --enable-sim-duplicate or --disable-sim-duplicate was given. if test "${enable_sim_duplicate+set}" = set; then enableval="$enable_sim_duplicate" @@ -945,23 +984,46 @@ if test x"$silent" != x"yes"; then fi fi -# Check whether --enable-sim-jump or --disable-sim-jump was given. -if test "${enable_sim_jump+set}" = set; then - enableval="$enable_sim_jump" + +# Check whether --enable-sim-endian or --disable-sim-endian was given. +if test "${enable_sim_endian+set}" = set; then + enableval="$enable_sim_endian" case "${enableval}" in - yes) sim_jump="-J";; - no) sim_jump="";; - *) { echo "configure: error: "--enable-sim-jump does not take a value"" 1>&2; exit 1; }; sim_jump="";; + yes) case "$target" in + *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";; + *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";; + *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";; + esac;; + no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";; + b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";; + l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";; + *) { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";; esac -if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then - echo "Setting jump flag = $sim_jump" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then + echo "Setting endian flags = $sim_endian" 6>&1 fi else - sim_jump="-E" -if test x"$silent" != x"yes"; then - echo "Setting jump flag = $sim_jump" 6>&1 + sim_endian="" fi + + +# Check whether --enable-sim-env or --disable-sim-env was given. +if test "${enable_sim_env+set}" = set; then + enableval="$enable_sim_env" + case "${enableval}" in + operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";; + virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";; + user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";; + no) sim_env="-DWITH_ENVIRONMENT=0";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-env"" 1>&2; exit 1; }; sim_env="";; +esac +if test x"$silent" != x"yes" && test x"$sim_env" != x""; then + echo "Setting env flags = $sim_env" 6>&1 fi +else + sim_env="" +fi + # Check whether --enable-sim-filter or --disable-sim-filter was given. if test "${enable_sim_filter+set}" = set; then @@ -975,51 +1037,39 @@ if test x"$silent" != x"yes" && test x"$sim_filter" != x""; then echo "Setting filter flags = $sim_filter" 6>&1 fi else - sim_filter="-F 32,f" + sim_filter="-F 32,f,o" if test x"$silent" != x"yes"; then echo "Setting filter flags = $sim_filter" 6>&1 fi fi -# Check whether --enable-sim-icache or --disable-sim-icache was given. -if test "${enable_sim_icache+set}" = set; then - enableval="$enable_sim_icache" - icache="" - case "${enableval}" in - yes) icache="1024"; sim_icache="-I $icache";; - no) sim_icache="";; - *) icache=1024 - sim_icache="-" - for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do - case "$x" in - define) sim_icache="${sim_icache}R";; - semantic) sim_icache="${sim_icache}C";; - insn) sim_icache="${sim_icache}S";; - 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) icache=$x;; - *) { echo "configure: error: "Unknown value $x for --enable-sim-icache"" 1>&2; exit 1; }; sim_icache="";; - esac - done - sim_icache="${sim_icache}I $icache";; + +# Check whether --enable-sim-float or --disable-sim-float was given. +if test "${enable_sim_float+set}" = set; then + enableval="$enable_sim_float" + case "${enableval}" in + yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";; + no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";; esac -if test x"$silent" != x"yes" && test x"$icache" != x""; then - echo "Setting instruction cache size to $icache ($sim_icache)" +if test x"$silent" != x"yes" && test x"$sim_float" != x""; then + echo "Setting float flags = $sim_float" 6>&1 fi else - sim_icache="-CSI 1024" -if test x"$silent" != x"yes"; then - echo "Setting instruction cache size to 1024 ($sim_icache)" -fi + sim_float="" fi + # Check whether --enable-sim-hardware or --disable-sim-hardware was given. if test "${enable_sim_hardware+set}" = set; then enableval="$enable_sim_hardware" - hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal" + hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide" case "${enableval}" in yes) ;; no) { echo "configure: error: "List of hardware must be specified for --enable-sim-hardware"" 1>&2; exit 1; }; hardware="";; ,*) hardware="${hardware}${enableval}";; - *) hardware="${enableval}";; + *,) hardware="${enableval}${hardware}";; + *) hardware="${enableval}"'';; esac sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'` sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'` @@ -1027,7 +1077,7 @@ if test x"$silent" != x"yes" && test x"$hardware" != x""; then echo "Setting hardware to $sim_hw_src, $sim_hw_obj" fi else - hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal" + hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide" sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'` sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'` if test x"$silent" != x"yes"; then @@ -1036,135 +1086,20 @@ fi fi -# Check whether --enable-sim-packages or --disable-sim-packages was given. -if test "${enable_sim_packages+set}" = set; then - enableval="$enable_sim_packages" - packages=disklabel -case "${enableval}" in - yes) ;; - no) { echo "configure: error: "List of packages must be specified for --enable-sim-packages"" 1>&2; exit 1; }; packages="";; - ,*) packages="${packages}${enableval}";; - *) packages="${enableval}"'' -esac -sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'` -sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'` -if test x"$silent" != x"yes" && test x"$packages" != x""; then - echo "Setting packages to $sim_pk_src, $sim_pk_obj" -fi -else - packages=disklabel -sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'` -sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'` -if test x"$silent" != x"yes"; then - echo "Setting packages to $sim_pk_src, $sim_pk_obj" -fi -fi - -# Check whether --enable-sim-inline or --disable-sim-inline was given. -if test "${enable_sim_inline+set}" = set; then - enableval="$enable_sim_inline" - sim_inline="" -case "$enableval" in - no) sim_inline="-DDEFAULT_INLINE=0";; - 0) sim_inline="-DDEFAULT_INLINE=0";; - yes | 2) sim_inline="-DDEFAULT_INLINE=ALL_INLINE";; - 1) sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS";; - *) for x in `echo "$enableval" | sed -e "s/,/ /g"`; do - new_flag="" - case "$x" in - *_INLINE=*) new_flag="-D$x";; - *=*) new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;; - *_INLINE) new_flag="-D$x=ALL_INLINE";; - *) new_flag="-D$x""_INLINE=ALL_INLINE";; - esac - if test x"$sim_inline" = x""; then - sim_inline="$new_flag" - else - sim_inline="$sim_inline $new_flag" - fi - done;; -esac -if test x"$silent" != x"yes" && test x"$sim_inline" != x""; then - echo "Setting inline flags = $sim_inline" 6>&1 -fi -else - if test x"$GCC" != ""; then - sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS" - if test x"$silent" != x"yes"; then - echo "Setting inline flags = $sim_inline" 6>&1 - fi -else - sim_inline="" -fi -fi - -# Check whether --enable-sim-bswap or --disable-sim-bswap was given. -if test "${enable_sim_bswap+set}" = set; then - enableval="$enable_sim_bswap" - case "${enableval}" in - yes) sim_bswap="-DWITH_BSWAP=1";; - no) sim_bswap="-DWITH_BSWAP=0";; - *) { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";; -esac -if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then - echo "Setting bswap flags = $sim_bswap" 6>&1 -fi -else - sim_bswap="" -fi - -# Check whether --enable-sim-endian or --disable-sim-endian was given. -if test "${enable_sim_endian+set}" = set; then - enableval="$enable_sim_endian" +# Check whether --enable-sim-hostbitsize or --disable-sim-hostbitsize was given. +if test "${enable_sim_hostbitsize+set}" = set; then + enableval="$enable_sim_hostbitsize" case "${enableval}" in - yes) case "$target" in - *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";; - *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";; - *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";; - esac;; - no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";; - b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";; - l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";; - *) { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";; + 32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";; + *) { echo "configure: error: "--enable-sim-hostbitsize was given $enableval. Expected 32 or 64"" 1>&2; exit 1; }; sim_hostbitsize="";; esac -if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then - echo "Setting endian flags = $sim_endian" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then + echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1 fi else - sim_endian="" + sim_hostbitsize="" fi -# Check whether --enable-sim-regparm or --disable-sim-regparm was given. -if test "${enable_sim_regparm+set}" = set; then - enableval="$enable_sim_regparm" - case "${enableval}" in - 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) sim_regparm="-DWITH_REGPARM=${enableval}";; - no) sim_regparm="" ;; - yes) sim_regparm="-DWITH_REGPARM=3";; - *) { echo "configure: error: "Unknown value $enableval for --enable-sim-regparm"" 1>&2; exit 1; }; sim_regparm="";; -esac -if test x"$silent" != x"yes" && test x"$sim_regparm" != x""; then - echo "Setting regparm flags = $sim_regparm" 6>&1 -fi -else - sim_regparm="" -fi - -# Check whether --enable-sim-stdcall or --disable-sim-stdcall was given. -if test "${enable_sim_stdcall+set}" = set; then - enableval="$enable_sim_stdcall" - case "${enableval}" in - no) sim_stdcall="" ;; - std*) sim_stdcall="-DWITH_STDCALL=1";; - yes) sim_stdcall="-DWITH_STDCALL=1";; - *) { echo "configure: error: "Unknown value $enableval for --enable-sim-stdcall"" 1>&2; exit 1; }; sim_stdcall="";; -esac -if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then - echo "Setting function call flags = $sim_stdcall" 6>&1 -fi -else - sim_stdcall="" -fi # Check whether --enable-sim-hostendian or --disable-sim-hostendian was given. if test "${enable_sim_hostendian+set}" = set; then @@ -1182,58 +1117,60 @@ else if test "x$cross_compiling" = "xno"; then echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:1121: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN bogus endian macros #endif ; return 0; } EOF -if { (eval echo configure:1204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1139: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } EOF -if { (eval echo configure:1220: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1154: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_bigendian=no fi rm -f conftest* - +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - if test $ac_cv_c_bigendian = unknown; then if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else -cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1187: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_c_bigendian=no else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_c_bigendian=yes fi -fi rm -fr conftest* +fi + fi fi @@ -1275,6 +1216,245 @@ else fi fi + +# Check whether --enable-sim-icache or --disable-sim-icache was given. +if test "${enable_sim_icache+set}" = set; then + enableval="$enable_sim_icache" + icache="-R" + case "${enableval}" in + yes) icache="1024"; sim_icache="-I $icache";; + no) sim_icache="-R";; + *) icache=1024 + sim_icache="-" + for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do + case "$x" in + define) sim_icache="${sim_icache}R";; + semantic) sim_icache="${sim_icache}C";; + insn) sim_icache="${sim_icache}S";; + 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) icache=$x;; + *) { echo "configure: error: "Unknown value $x for --enable-sim-icache"" 1>&2; exit 1; }; sim_icache="";; + esac + done + sim_icache="${sim_icache}I $icache";; +esac +if test x"$silent" != x"yes" && test x"$icache" != x""; then + echo "Setting instruction cache size to $icache ($sim_icache)" +fi +else + sim_icache="-CSRI 1024" +if test x"$silent" != x"yes"; then + echo "Setting instruction cache size to 1024 ($sim_icache)" +fi +fi + + +# Check whether --enable-sim-inline or --disable-sim-inline was given. +if test "${enable_sim_inline+set}" = set; then + enableval="$enable_sim_inline" + sim_inline="" +case "$enableval" in + no) sim_inline="-DDEFAULT_INLINE=0";; + 0) sim_inline="-DDEFAULT_INLINE=0";; + yes | 2) sim_inline="-DDEFAULT_INLINE=ALL_INLINE";; + 1) sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS";; + *) for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + new_flag="" + case "$x" in + *_INLINE=*) new_flag="-D$x";; + *=*) new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;; + *_INLINE) new_flag="-D$x=ALL_INLINE";; + *) new_flag="-D$x""_INLINE=ALL_INLINE";; + esac + if test x"$sim_inline" = x""; then + sim_inline="$new_flag" + else + sim_inline="$sim_inline $new_flag" + fi + done;; +esac +if test x"$silent" != x"yes" && test x"$sim_inline" != x""; then + echo "Setting inline flags = $sim_inline" 6>&1 +fi +else + if test x"$GCC" != ""; then + sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS" + if test x"$silent" != x"yes"; then + echo "Setting inline flags = $sim_inline" 6>&1 + fi +else + sim_inline="" +fi +fi + + +# Check whether --enable-sim-jump or --disable-sim-jump was given. +if test "${enable_sim_jump+set}" = set; then + enableval="$enable_sim_jump" + case "${enableval}" in + yes) sim_jump="-J";; + no) sim_jump="";; + *) { echo "configure: error: "--enable-sim-jump does not take a value"" 1>&2; exit 1; }; sim_jump="";; +esac +if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then + echo "Setting jump flag = $sim_jump" 6>&1 +fi +else + sim_jump="" +if test x"$silent" != x"yes"; then + echo "Setting jump flag = $sim_jump" 6>&1 +fi +fi + + +# Check whether --enable-sim-line-nr or --disable-sim-line-nr was given. +if test "${enable_sim_line_nr+set}" = set; then + enableval="$enable_sim_line_nr" + case "${enableval}" in + yes) sim_line_nr="";; + no) sim_line_nr="-L";; + *) { echo "configure: error: "--enable-sim-line-nr does not take a value"" 1>&2; exit 1; }; sim_line_nr="";; +esac +if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then + echo "Setting warning flags = $sim_line_nr" 6>&1 +fi +else + sim_line_nr="" +fi + + +# Check whether --enable-sim-model or --disable-sim-model was given. +if test "${enable_sim_model+set}" = set; then + enableval="$enable_sim_model" + case "${enableval}" in + yes|no) { echo "configure: error: "No value supplied for --enable-sim-model=model"" 1>&2; exit 1; };; + *) sim_model="-DWITH_MODEL=${enableval}";; +esac +if test x"$silent" != x"yes" && test x"$sim_model" != x""; then + echo "Setting model flags = $sim_model" 6>&1 +fi +else + sim_model="" +fi + + +# Check whether --enable-sim-model-issue or --disable-sim-model-issue was given. +if test "${enable_sim_model_issue+set}" = set; then + enableval="$enable_sim_model_issue" + case "${enableval}" in + yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";; + no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";; + *) { echo "configure: error: "--enable-sim-model-issue does not take a value"" 1>&2; exit 1; }; sim_model_issue="";; +esac +if test x"$silent" != x"yes"; then + echo "Setting model-issue flags = $sim_model_issue" 6>&1 +fi +else + sim_model_issue="" +fi + + +# Check whether --enable-sim-monitor or --disable-sim-monitor was given. +if test "${enable_sim_monitor+set}" = set; then + enableval="$enable_sim_monitor" + case "${enableval}" in + yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";; + no) sim_monitor="-DWITH_MON=0";; + instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";; + memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-mon"" 1>&2; exit 1; }; sim_env="";; +esac +if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then + echo "Setting monitor flags = $sim_monitor" 6>&1 +fi +else + sim_monitor="" +fi + + +# Check whether --enable-sim-opcode or --disable-sim-opcode was given. +if test "${enable_sim_opcode+set}" = set; then + enableval="$enable_sim_opcode" + case "${enableval}" in + yes|no) { echo "configure: error: "No value supplied for --enable-sim-opcode=file"" 1>&2; exit 1; };; + *) if test -f "${srcdir}/${enableval}"; then + sim_opcode="${enableval}" + elif test -f "${srcdir}/ppc-opcode-${enableval}"; then + sim_opcode="ppc-opcode-${enableval}" + else + { echo "configure: error: "File $enableval is not an opcode rules file"" 1>&2; exit 1; }; + sim_opcode="ppc-opcode-complex" + fi;; +esac +if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then + echo "Setting opcode flags = $sim_opcode" 6>&1 +fi +else + sim_opcode="ppc-opcode-complex" +if test x"$silent" != x"yes"; then + echo "Setting opcode flags = $sim_opcode" +fi +fi + + +# Check whether --enable-sim-packages or --disable-sim-packages was given. +if test "${enable_sim_packages+set}" = set; then + enableval="$enable_sim_packages" + packages=disklabel +case "${enableval}" in + yes) ;; + no) { echo "configure: error: "List of packages must be specified for --enable-sim-packages"" 1>&2; exit 1; }; packages="";; + ,*) packages="${packages}${enableval}";; + *,) packages="${enableval}${packages}";; + *) packages="${enableval}"'';; +esac +sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'` +sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'` +if test x"$silent" != x"yes" && test x"$packages" != x""; then + echo "Setting packages to $sim_pk_src, $sim_pk_obj" +fi +else + packages=disklabel +sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'` +sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'` +if test x"$silent" != x"yes"; then + echo "Setting packages to $sim_pk_src, $sim_pk_obj" +fi +fi + + +# Check whether --enable-sim-regparm or --disable-sim-regparm was given. +if test "${enable_sim_regparm+set}" = set; then + enableval="$enable_sim_regparm" + case "${enableval}" in + 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) sim_regparm="-DWITH_REGPARM=${enableval}";; + no) sim_regparm="" ;; + yes) sim_regparm="-DWITH_REGPARM=3";; + *) { echo "configure: error: "Unknown value $enableval for --enable-sim-regparm"" 1>&2; exit 1; }; sim_regparm="";; +esac +if test x"$silent" != x"yes" && test x"$sim_regparm" != x""; then + echo "Setting regparm flags = $sim_regparm" 6>&1 +fi +else + sim_regparm="" +fi + + +# Check whether --enable-sim-reserved-bits or --disable-sim-reserved-bits was given. +if test "${enable_sim_reserved_bits+set}" = set; then + enableval="$enable_sim_reserved_bits" + case "${enableval}" in + yes) sim_reserved="-DWITH_RESERVED_BITS=1";; + no) sim_reserved="-DWITH_RESERVED_BITS=0";; + *) { echo "configure: error: "--enable-sim-reserved-bits does not take a value"" 1>&2; exit 1; }; sim_reserved="";; +esac +if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then + echo "Setting reserved flags = $sim_reserved" 6>&1 +fi +else + sim_reserved="" +fi + + # Check whether --enable-sim-smp or --disable-sim-smp was given. if test "${enable_sim_smp+set}" = set; then enableval="$enable_sim_smp" @@ -1293,66 +1473,59 @@ if test x"$silent" != x"yes"; then fi fi -# Check whether --enable-sim-xor-endian or --disable-sim-xor-endian was given. -if test "${enable_sim_xor_endian+set}" = set; then - enableval="$enable_sim_xor_endian" - case "${enableval}" in - yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";; - no) sim_xor_endian="-DWITH_XOR_ENDIAN=0";; - *) sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";; -esac -if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then - echo "Setting xor-endian flag = $sim_xor_endian" 6>&1 -fi -else - sim_xor_endian="" -fi -# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given. -if test "${enable_sim_bitsize+set}" = set; then - enableval="$enable_sim_bitsize" +# Check whether --enable-sim-stdcall or --disable-sim-stdcall was given. +if test "${enable_sim_stdcall+set}" = set; then + enableval="$enable_sim_stdcall" case "${enableval}" in - 32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";; - *) { echo "configure: error: "--enable-sim-bitsize was given $enableval" 1>&2; exit 1; }; sim_bitsize="";; + no) sim_stdcall="" ;; + std*) sim_stdcall="-DWITH_STDCALL=1";; + yes) sim_stdcall="-DWITH_STDCALL=1";; + *) { echo "configure: error: "Unknown value $enableval for --enable-sim-stdcall"" 1>&2; exit 1; }; sim_stdcall="";; esac -if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then - echo "Setting bitsize flags = $sim_bitsize" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then + echo "Setting function call flags = $sim_stdcall" 6>&1 fi else - sim_bitsize="" + sim_stdcall="" fi -# Check whether --enable-sim-hostbitsize or --disable-sim-hostbitsize was given. -if test "${enable_sim_hostbitsize+set}" = set; then - enableval="$enable_sim_hostbitsize" + +# Check whether --enable-sim-stdio or --disable-sim-stdio was given. +if test "${enable_sim_stdio+set}" = set; then + enableval="$enable_sim_stdio" case "${enableval}" in - 32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";; - *) { echo "configure: error: "--enable-sim-hostbitsize was given $enableval" 1>&2; exit 1; }; sim_hostbitsize="";; + yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; + no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";; esac -if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then - echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then + echo "Setting stdio flags = $sim_stdio" 6>&1 fi else - sim_hostbitsize="" + sim_stdio="" fi -# Check whether --enable-sim-env or --disable-sim-env was given. -if test "${enable_sim_env+set}" = set; then - enableval="$enable_sim_env" + +# Check whether --enable-sim-switch or --disable-sim-switch was given. +if test "${enable_sim_switch+set}" = set; then + enableval="$enable_sim_switch" case "${enableval}" in - operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";; - virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";; - user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";; - no) sim_env="-DWITH_ENVIRONMENT=0";; - *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-env"" 1>&2; exit 1; }; sim_env="";; + yes) sim_switch="-s";; + no) sim_switch="";; + *) { echo "configure: error: "--enable-sim-switch does not take a value"" 1>&2; exit 1; }; sim_switch="";; esac -if test x"$silent" != x"yes" && test x"$sim_env" != x""; then - echo "Setting env flags = $sim_env" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then + echo "Setting switch flags = $sim_switch" 6>&1 fi else - sim_env="" + sim_switch=""; +if test x"$silent" != x"yes"; then + echo "Setting switch flags = $sim_switch" 6>&1 +fi fi + # Check whether --enable-sim-timebase or --disable-sim-timebase was given. if test "${enable_sim_timebase+set}" = set; then enableval="$enable_sim_timebase" @@ -1368,21 +1541,6 @@ else sim_timebase="" fi -# Check whether --enable-sim-alignment or --disable-sim-alignment was given. -if test "${enable_sim_alignment+set}" = set; then - enableval="$enable_sim_alignment" - case "${enableval}" in - yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";; - no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";; - 0 | default | DEFAULT) sim_alignment="-DWITH_ALIGNMENT=0";; - *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";; -esac -if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then - echo "Setting alignment flags = $sim_alignment" 6>&1 -fi -else - sim_alignment="" -fi # Check whether --enable-sim-trace or --disable-sim-trace was given. if test "${enable_sim_trace+set}" = set; then @@ -1399,125 +1557,38 @@ else sim_trace="" fi -# Check whether --enable-sim-assert or --disable-sim-assert was given. -if test "${enable_sim_assert+set}" = set; then - enableval="$enable_sim_assert" - case "${enableval}" in - yes) sim_assert="-DWITH_ASSERT=1";; - no) sim_assert="-DWITH_ASSERT=0";; - *) { echo "configure: error: "--enable-sim-assert does not take a value"" 1>&2; exit 1; }; sim_assert="";; -esac -if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then - echo "Setting assert flags = $sim_assert" 6>&1 -fi -else - sim_assert="" -fi - -# Check whether --enable-sim-reserved-bits or --disable-sim-reserved-bits was given. -if test "${enable_sim_reserved_bits+set}" = set; then - enableval="$enable_sim_reserved_bits" - case "${enableval}" in - yes) sim_reserved="-DWITH_RESERVED_BITS=1";; - no) sim_reserved="-DWITH_RESERVED_BITS=0";; - *) { echo "configure: error: "--enable-sim-reserved-bits does not take a value"" 1>&2; exit 1; }; sim_reserved="";; -esac -if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then - echo "Setting reserved flags = $sim_reserved" 6>&1 -fi -else - sim_reserved="" -fi - -# Check whether --enable-sim-float or --disable-sim-float was given. -if test "${enable_sim_float+set}" = set; then - enableval="$enable_sim_float" - case "${enableval}" in - yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";; - no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";; - *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";; -esac -if test x"$silent" != x"yes" && test x"$sim_float" != x""; then - echo "Setting float flags = $sim_float" 6>&1 -fi -else - sim_float="" -fi - -# Check whether --enable-sim-monitor or --disable-sim-monitor was given. -if test "${enable_sim_monitor+set}" = set; then - enableval="$enable_sim_monitor" - case "${enableval}" in - yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";; - no) sim_monitor="-DWITH_MON=0";; - instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";; - memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";; - *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-mon"" 1>&2; exit 1; }; sim_env="";; -esac -if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then - echo "Setting monitor flags = $sim_monitor" 6>&1 -fi -else - sim_monitor="" -fi -# Check whether --enable-sim-model or --disable-sim-model was given. -if test "${enable_sim_model+set}" = set; then - enableval="$enable_sim_model" +# Check whether --enable-sim-warnings or --disable-sim-warnings was given. +if test "${enable_sim_warnings+set}" = set; then + enableval="$enable_sim_warnings" case "${enableval}" in - yes|no) { echo "configure: error: "No value supplied for --enable-sim-model=model"" 1>&2; exit 1; };; - *) sim_model="-DWITH_MODEL=${enableval}";; + yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations ";; + no) sim_warnings="-w";; + *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;; esac -if test x"$silent" != x"yes" && test x"$sim_model" != x""; then - echo "Setting model flags = $sim_model" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then + echo "Setting warning flags = $sim_warnings" 6>&1 fi else - sim_model="" + sim_warnings="" fi -# Check whether --enable-sim-default-model or --disable-sim-default-model was given. -if test "${enable_sim_default_model+set}" = set; then - enableval="$enable_sim_default_model" - case "${enableval}" in - yes|no) { echo "configure: error: "No value supplied for --enable-sim-default-model=model"" 1>&2; exit 1; };; - *) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";; -esac -if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then - echo "Setting default-model flags = $sim_default_model" 6>&1 -fi -else - sim_model="" -fi -# Check whether --enable-sim-model-issue or --disable-sim-model-issue was given. -if test "${enable_sim_model_issue+set}" = set; then - enableval="$enable_sim_model_issue" +# Check whether --enable-sim-xor-endian or --disable-sim-xor-endian was given. +if test "${enable_sim_xor_endian+set}" = set; then + enableval="$enable_sim_xor_endian" case "${enableval}" in - yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";; - no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";; - *) { echo "configure: error: "--enable-sim-model-issue does not take a value"" 1>&2; exit 1; }; sim_model_issue="";; + yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";; + no) sim_xor_endian="-DWITH_XOR_ENDIAN=0";; + *) sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";; esac -if test x"$silent" != x"yes"; then - echo "Setting model-issue flags = $sim_model_issue" 6>&1 +if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then + echo "Setting xor-endian flag = $sim_xor_endian" 6>&1 fi else - sim_model_issue="" + sim_xor_endian="" fi -# Check whether --enable-sim-stdio or --disable-sim-stdio was given. -if test "${enable_sim_stdio+set}" = set; then - enableval="$enable_sim_stdio" - case "${enableval}" in - yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; - no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; - *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";; -esac -if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then - echo "Setting stdio flags = $sim_stdio" 6>&1 -fi -else - sim_stdio="" -fi ac_aux_dir= for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do @@ -1566,6 +1637,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1641: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -1580,12 +1652,13 @@ NONE) esac host=`$ac_config_sub $host_alias` -host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` -host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` -host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:1662: checking target system type" >&5 target_alias=$target case "$target_alias" in @@ -1597,12 +1670,13 @@ NONE) esac target=`$ac_config_sub $target_alias` -target_cpu=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` -target_vendor=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` -target_os=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:1680: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1614,9 +1688,9 @@ NONE) esac build=`$ac_config_sub $build_alias` -build_cpu=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` -build_vendor=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` -build_os=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$build" 1>&6 test "$host_alias" != "$target_alias" && @@ -1649,28 +1723,29 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6 +echo "configure:1727: checking for st_blksize in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { struct stat s; s.st_blksize; ; return 0; } EOF -if { (eval echo configure:1666: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1740: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blksize=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_st_blksize=no fi rm -f conftest* - fi echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6 @@ -1682,28 +1757,29 @@ EOF fi echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6 +echo "configure:1761: checking for st_blocks in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { struct stat s; s.st_blocks; ; return 0; } EOF -if { (eval echo configure:1699: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1774: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blocks=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_st_blocks=no fi rm -f conftest* - fi echo "$ac_t""$ac_cv_struct_st_blocks" 1>&6 @@ -1717,28 +1793,29 @@ else fi echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6 +echo "configure:1797: checking for st_rdev in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { struct stat s; s.st_rdev; ; return 0; } EOF -if { (eval echo configure:1734: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1810: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_rdev=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_st_rdev=no fi rm -f conftest* - fi echo "$ac_t""$ac_cv_struct_st_rdev" 1>&6 @@ -1750,28 +1827,29 @@ EOF fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 +echo "configure:1831: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:1767: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1844: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_tm=sys/time.h fi rm -f conftest* - fi echo "$ac_t""$ac_cv_struct_tm" 1>&6 @@ -1783,28 +1861,29 @@ EOF fi echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6 +echo "configure:1865: checking for tm_zone in struct tm" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_cv_struct_tm> -int main() { return 0; } -int t() { +int main() { struct tm tm; tm.tm_zone; ; return 0; } EOF -if { (eval echo configure:1800: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1878: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm_zone=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_struct_tm_zone=no fi rm -f conftest* - fi echo "$ac_t""$ac_cv_struct_tm_zone" 1>&6 @@ -1815,30 +1894,31 @@ EOF else echo $ac_n "checking for tzname""... $ac_c" 1>&6 +echo "configure:1898: checking for tzname" >&5 if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #ifndef tzname /* For SGI. */ extern char *tzname[]; /* RS6000 and others reject char **tzname. */ #endif -int main() { return 0; } -int t() { +int main() { atoi(*tzname); ; return 0; } EOF -if { (eval echo configure:1834: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:1913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_var_tzname=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_var_tzname=no fi rm -f conftest* - fi echo "$ac_t""$ac_cv_var_tzname" 1>&6 @@ -1852,6 +1932,7 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1936: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1866,33 +1947,37 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1876: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1957: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1891: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1974: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi @@ -1908,11 +1993,12 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:1997: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF @@ -1941,14 +2027,15 @@ EOF fi echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 +echo "configure:2031: checking type of array argument to getgroups" >&5 if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_type_getgroups=cross else -cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:2064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_type_getgroups=gid_t else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_type_getgroups=int fi -fi rm -fr conftest* +fi + if test $ac_cv_type_getgroups = cross; then cat > conftest.$ac_ext < EOF @@ -2007,11 +2098,12 @@ EOF echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:2102: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2019,13 +2111,15 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2023: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2115: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi @@ -2034,7 +2128,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2052,7 +2146,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2072,8 +2166,8 @@ if test $ac_cv_header_stdc = yes; then if test "$cross_compiling" = yes; then : else -cat > conftest.$ac_ext < conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2084,14 +2178,18 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -{ (eval echo configure:2088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:2182: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_header_stdc=no fi -fi rm -fr conftest* +fi + fi fi @@ -2104,19 +2202,21 @@ EOF fi echo $ac_n "checking for mode_t""... $ac_c" 1>&6 +echo "configure:2206: checking for mode_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include +#include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "mode_t" >/dev/null 2>&1; then + egrep "mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_mode_t=yes else @@ -2135,19 +2235,21 @@ EOF fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:2239: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include +#include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "off_t" >/dev/null 2>&1; then + egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_off_t=yes else @@ -2166,19 +2268,21 @@ EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 +echo "configure:2272: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include +#include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "pid_t" >/dev/null 2>&1; then + egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_pid_t=yes else @@ -2197,11 +2301,12 @@ EOF fi echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:2305: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2214,20 +2319,20 @@ extern "C" void (*signal (int, void (*)(int)))(int); void (*signal ()) (); #endif -int main() { return 0; } -int t() { +int main() { int i; ; return 0; } EOF -if { (eval echo configure:2223: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2327: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_type_signal=int fi rm -f conftest* - fi echo "$ac_t""$ac_cv_type_signal" 1>&6 @@ -2237,19 +2342,21 @@ EOF echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:2346: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include +#include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "size_t" >/dev/null 2>&1; then + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else @@ -2268,11 +2375,12 @@ EOF fi echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:2379: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF @@ -2301,14 +2409,15 @@ EOF fi -for ac_func in cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink +for ac_func in access cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2416: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:2444: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* - fi + if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` @@ -2357,24 +2467,27 @@ done for ac_hdr in fcntl.h stdlib.h string.h strings.h sys/ioctl.h sys/mount.h sys/param.h sys/resource.h sys/stat.h sys/termio.h sys/termios.h sys/time.h sys/times.h sys/types.h time.h unistd.h do -ac_safe=`echo "$ac_hdr" | tr './\055' '___'` +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2473: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2372: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2483: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi @@ -2382,7 +2495,7 @@ rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'` + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 +echo "configure:2514: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> -int main() { return 0; } -int t() { +int main() { DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:2414: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2527: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=no" fi rm -f conftest* - fi if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdedfghijklmnopqrstuvwxyz./\055' 'ABCDEDFGHIJKLMNOPQRSTUVWXYZ___'` + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 -ac_lib_var=`echo dir'_'opendir | tr './+\055' '__p_'` +echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 +echo "configure:2552: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:2571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -2472,30 +2588,32 @@ else fi else -echo $ac_n "checking for -lx""... $ac_c" 1>&6 -ac_lib_var=`echo x'_'opendir | tr './+\055' '__p_'` +echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 +echo "configure:2593: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then +if { (eval echo configure:2612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi @@ -2515,16 +2633,16 @@ fi sim_termio="" echo $ac_n "checking for struct termios""... $ac_c" 1>&6 +echo "configure:2637: checking for struct termios" >&5 if eval "test \"`echo '$''{'ac_cv_termios_struct'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { static struct termios x; x.c_iflag = 0; x.c_oflag = 0; @@ -2533,15 +2651,16 @@ static struct termios x; x.c_cc[NCCS] = 0; ; return 0; } EOF -if { (eval echo configure:2537: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2655: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_termios_struct=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_termios_struct=no fi rm -f conftest* - fi echo "$ac_t""$ac_cv_termios_struct" 1>&6 @@ -2551,28 +2670,29 @@ fi if test "$ac_cv_termios_struct" = "yes"; then echo $ac_n "checking for c_line field in struct termios""... $ac_c" 1>&6 +echo "configure:2674: checking for c_line field in struct termios" >&5 if eval "test \"`echo '$''{'ac_cv_termios_cline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { static struct termios x; x.c_line = 0; ; return 0; } EOF -if { (eval echo configure:2568: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2687: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_termios_cline=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_termios_cline=no fi rm -f conftest* - fi @@ -2586,16 +2706,16 @@ fi if test "$ac_cv_termios_struct" != "yes"; then echo $ac_n "checking for struct termio""... $ac_c" 1>&6 +echo "configure:2710: checking for struct termio" >&5 if eval "test \"`echo '$''{'ac_cv_termio_struct'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { static struct termio x; x.c_iflag = 0; x.c_oflag = 0; @@ -2604,15 +2724,16 @@ static struct termio x; x.c_cc[NCC] = 0; ; return 0; } EOF -if { (eval echo configure:2608: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2728: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_termio_struct=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_termio_struct=no fi rm -f conftest* - fi echo "$ac_t""$ac_cv_termio_struct" 1>&6 @@ -2625,28 +2746,29 @@ fi if test "$ac_cv_termio_struct" = "yes"; then echo $ac_n "checking for c_line field in struct termio""... $ac_c" 1>&6 +echo "configure:2750: checking for c_line field in struct termio" >&5 if eval "test \"`echo '$''{'ac_cv_termio_cline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include -int main() { return 0; } -int t() { +int main() { static struct termio x; x.c_line = 0; ; return 0; } EOF -if { (eval echo configure:2642: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2763: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_termio_cline=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_termio_cline=no fi rm -f conftest* - fi @@ -2658,6 +2780,56 @@ else ac_cv_termio_cline=no fi +sim_devzero="" +echo $ac_n "checking for /dev/zero""... $ac_c" 1>&6 +echo "configure:2786: checking for /dev/zero" >&5 +if eval "test \"`echo '$''{'ac_cv_devzero'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_devzero=no +else + cat > conftest.$ac_ext < +main () { + char buf[2048]; + int i; + int fd = open ("/dev/zero", O_RDONLY); + if (fd < 0) + return 1; + for (i = 0; i < sizeof (buf); i++) + buf[i] = 1; + if (read (fd, buf, sizeof (buf)) != sizeof (buf)) + return 1; + for (i = 0; i < sizeof (buf); i++) + if (buf[i]) + return 1; + return 0; +} +EOF +if { (eval echo configure:2813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_devzero=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_devzero=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_devzero" 1>&6 +if test $ac_cv_devzero = yes; then + sim_devzero="-DHAVE_DEVZERO" +else + sim_devzero="" +fi + @@ -2666,6 +2838,7 @@ AR=${AR-ar} # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2842: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2728,6 +2901,7 @@ fi + trap '' 1 2 15 @@ -2747,11 +2921,25 @@ cat > confcache <<\EOF # --recheck option to rerun configure. # EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | - sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \ - >> confcache + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache if cmp -s $cache_file confcache; then : else @@ -2806,7 +2994,7 @@ do echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.10" + echo "$CONFIG_STATUS generated by autoconf version 2.12" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -2909,23 +3097,60 @@ s%@sim_default_model@%$sim_default_model%g s%@sim_model_issue@%$sim_model_issue%g s%@sim_stdio@%$sim_stdio%g s%@sim_termio@%$sim_termio%g +s%@sim_devzero@%$sim_devzero%g CEOF EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then - # Support "outfile[:infile]", defaulting infile="outfile.in". + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac - # Adjust relative srcdir, etc. for subdirectories. + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` @@ -2953,6 +3178,7 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac + echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." @@ -2961,14 +3187,16 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # $configure_input" ;; *) ac_comsub= ;; esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g -" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done -rm -f conftest.subs +rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. @@ -2989,11 +3217,17 @@ ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' -CONFIG_HEADERS=${CONFIG_HEADERS-"config.h:config.in"} +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then - # Support "outfile[:infile]", defaulting infile="outfile.in". + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac @@ -3001,7 +3235,8 @@ for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then echo creating $ac_file rm -f conftest.frag conftest.in conftest.out - cp $ac_given_srcdir/$ac_file_in conftest.in + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in EOF @@ -3029,8 +3264,6 @@ EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. -# Maximum number of lines to put in a single here document. -ac_max_here_lines=12 rm -f conftest.tail while : @@ -3072,7 +3305,11 @@ cat >> $CONFIG_STATUS <<\EOF fi fi; done +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac exit 0 EOF diff --git a/sim/ppc/configure.in b/sim/ppc/configure.in index fa6ae13d118..1d34ab4417d 100644 --- a/sim/ppc/configure.in +++ b/sim/ppc/configure.in @@ -237,11 +237,11 @@ fi])dnl AC_ARG_ENABLE(sim-icache, -[ --enable-sim-icache=size Specify instruction cache size.], -[icache="" +[ --enable-sim-icache=size Specify instruction-decode cache size and type.], +[icache="-R" case "${enableval}" in yes) icache="1024"; sim_icache="-I $icache";; - no) sim_icache="";; + no) sim_icache="-R";; *) icache=1024 sim_icache="-" for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do @@ -257,7 +257,7 @@ AC_ARG_ENABLE(sim-icache, esac if test x"$silent" != x"yes" && test x"$icache" != x""; then echo "Setting instruction cache size to $icache ($sim_icache)" -fi],[sim_icache="-CSI 1024" +fi],[sim_icache="-CSRI 1024" if test x"$silent" != x"yes"; then echo "Setting instruction cache size to 1024 ($sim_icache)" fi])dnl @@ -307,7 +307,7 @@ AC_ARG_ENABLE(sim-jump, esac if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then echo "Setting jump flag = $sim_jump" 6>&1 -fi],[sim_jump="-E" +fi],[sim_jump="" if test x"$silent" != x"yes"; then echo "Setting jump flag = $sim_jump" 6>&1 fi])dnl diff --git a/sim/ppc/device.c b/sim/ppc/device.c index 83d9e3fd4ff..7d69c3fa912 100644 --- a/sim/ppc/device.c +++ b/sim/ppc/device.c @@ -27,6 +27,9 @@ #include "device_table.h" #include "cap.h" +#include "events.h" +#include "psim.h" + #ifdef HAVE_STDLIB_H #include #endif @@ -42,7 +45,6 @@ #include STATIC_INLINE_DEVICE (void) clean_device_properties(device *); -STATIC_INLINE_DEVICE (void) init_device_properties(device *, void*); /* property entries */ @@ -97,13 +99,13 @@ detach_device_interrupt_edge(device *me, && old_edge->dest_port == dest_port && old_edge->my_port == my_port) { if (old_edge->disposition == permenant_object) - device_error(me, "attempt to delete permenant interrupt\n"); + device_error(me, "attempt to delete permenant interrupt"); *list = old_edge->next; zfree(old_edge); return; } } - device_error(me, "attempt to delete unattached interrupt\n"); + device_error(me, "attempt to delete unattached interrupt"); } STATIC_INLINE_DEVICE\ @@ -133,6 +135,8 @@ struct _device { const char *name; device_unit unit_address; const char *path; + int nr_address_cells; + int nr_size_cells; /* device tree */ device *parent; @@ -156,6 +160,9 @@ struct _device { cap *ihandles; cap *phandles; psim *system; + + /* debugging */ + int trace; }; @@ -175,76 +182,13 @@ struct _device_instance { -/* Device node: */ - -INLINE_DEVICE\ -(device *) -device_parent(device *me) -{ - return me->parent; -} - -INLINE_DEVICE\ -(device *) -device_sibling(device *me) -{ - return me->sibling; -} - -INLINE_DEVICE\ -(device *) -device_child(device *me) -{ - return me->children; -} - -INLINE_DEVICE\ -(const char *) -device_name(device *me) -{ - return me->name; -} - -INLINE_DEVICE\ -(const char *) -device_path(device *me) -{ - return me->path; -} - -INLINE_DEVICE\ -(void *) -device_data(device *me) -{ - return me->data; -} - -INLINE_DEVICE\ -(psim *) -device_system(device *me) -{ - return me->system; -} - -INLINE_DEVICE\ -(const device_unit *) -device_unit_address(device *me) -{ - return &me->unit_address; -} - - - -/* device template: */ - -/* determine the full name of the device. If buf is specified it is - stored in there. Failing that, a safe area of memory is allocated */ +/* creation */ STATIC_INLINE_DEVICE\ (const char *) device_full_name(device *leaf, - char *buf, - unsigned sizeof_buf) + char *buf, + unsigned sizeof_buf) { /* get a buffer */ char full_name[1024]; @@ -256,23 +200,23 @@ device_full_name(device *leaf, /* construct a name */ if (leaf->parent == NULL) { if (sizeof_buf < 1) - error("device_full_name: buffer overflow\n"); + error("device_full_name: buffer overflow"); *buf = '\0'; } else { char unit[1024]; device_full_name(leaf->parent, buf, sizeof_buf); if (leaf->parent != NULL - && leaf->parent->callback->convert.encode_unit(leaf->parent, - &leaf->unit_address, - unit+1, - sizeof(unit)-1) > 0) + && device_encode_unit(leaf->parent, + &leaf->unit_address, + unit+1, + sizeof(unit)-1) > 0) unit[0] = '@'; else unit[0] = '\0'; if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit) - >= sizeof_buf) - error("device_full_name: buffer overflow\n"); + >= sizeof_buf) + error("device_full_name: buffer overflow"); strcat(buf, "/"); strcat(buf, leaf->name); strcat (buf, unit); @@ -280,271 +224,10 @@ device_full_name(device *leaf, /* return it usefully */ if (buf == full_name) - buf = strdup(full_name); + buf = (char *) strdup(full_name); return buf; } -/* manipulate/lookup device names */ - -typedef struct _name_specifier { - /* components in the full length name */ - char *path; - char *property; - char *value; - /* current device */ - char *name; - char *unit; - char *args; - /* previous device */ - char *last_name; - char *last_unit; - char *last_args; - /* work area */ - char buf[1024]; -} name_specifier; - -/* Given a device specifier, break it up into its main components: - path (and if present) property name and property value. */ -STATIC_INLINE_DEVICE\ -(int) -split_device_specifier(const char *device_specifier, - name_specifier *spec) -{ - char *chp; - if (strlen(device_specifier) >= sizeof(spec->buf)) - error("split_device_specifier: buffer overflow\n"); - - /* expand aliases (later) */ - strcpy(spec->buf, device_specifier); - - /* strip the leading spaces and check that remainder isn't a comment */ - chp = spec->buf; - while (*chp != '\0' && isspace(*chp)) - chp++; - if (*chp == '\0' || *chp == '#') - return 0; - - /* find the path and terminate it with null */ - spec->path = chp; - while (*chp != '\0' && !isspace(*chp)) - chp++; - if (*chp != '\0') { - *chp = '\0'; - chp++; - } - - /* and any value */ - while (*chp != '\0' && isspace(*chp)) - chp++; - spec->value = chp; - - /* now go back and chop the property off of the path */ - if (spec->value[0] == '\0') { - spec->property = NULL; /*not a property*/ - spec->value = NULL; - } - else if (spec->value[0] == '>' - || spec->value[0] == '<') { - /* an interrupt spec */ - spec->property = NULL; - } - else { - chp = strrchr(spec->path, '/'); - if (chp == NULL) { - spec->property = spec->path; - spec->path = strchr(spec->property, '\0'); - } - else { - *chp = '\0'; - spec->property = chp+1; - } - } - - /* and mark the rest as invalid */ - spec->name = NULL; - spec->unit = NULL; - spec->args = NULL; - spec->last_name = NULL; - spec->last_unit = NULL; - spec->last_args = NULL; - - return 1; -} - -/* given a device specifier break it up into its main components - - path and property name - assuming that the last `device' is a - property name. */ -STATIC_INLINE_DEVICE\ -(int) -split_property_specifier(const char *property_specifier, - name_specifier *spec) -{ - if (split_device_specifier(property_specifier, spec)) { - if (spec->property == NULL) { - /* force the last name to be a property name */ - char *chp = strrchr(spec->path, '/'); - if (chp == NULL) { - spec->property = spec->path; - spec->path = strrchr(spec->property, '\0');; - } - else { - *chp = '\0'; - spec->property = chp+1; - } - } - return 1; - } - else - return 0; -} - -/* parse the next device name and split it up, return 0 when no more - names to parse */ -STATIC_INLINE_DEVICE\ -(int) -split_device_name(name_specifier *spec) -{ - char *chp; - /* remember what came before */ - spec->last_name = spec->name; - spec->last_unit = spec->unit; - spec->last_args = spec->args; - /* finished? */ - if (spec->path[0] == '\0') { - spec->name = NULL; - spec->unit = NULL; - spec->args = NULL; - return 0; - } - /* break the device name from the path */ - spec->name = spec->path; - chp = strchr(spec->name, '/'); - if (chp == NULL) - spec->path = strchr(spec->name, '\0'); - else { - spec->path = chp+1; - *chp = '\0'; - } - /* now break out the unit */ - chp = strchr(spec->name, '@'); - if (chp == NULL) { - spec->unit = NULL; - chp = spec->name; - } - else { - *chp = '\0'; - chp += 1; - spec->unit = chp; - } - /* finally any args */ - chp = strchr(chp, ':'); - if (chp == NULL) - spec->args = NULL; - else { - *chp = '\0'; - spec->args = chp+1; - } - return 1; -} - -/* parse the value, returning the next non-space token */ - -STATIC_INLINE_DEVICE\ -(char *) -split_value(name_specifier *spec) -{ - char *token; - if (spec->value == NULL) - return NULL; - /* skip leading white space */ - while (isspace(spec->value[0])) - spec->value++; - if (spec->value[0] == '\0') { - spec->value = NULL; - return NULL; - } - token = spec->value; - /* find trailing space */ - while (spec->value[0] != '\0' && !isspace(spec->value[0])) - spec->value++; - /* chop this value out */ - if (spec->value[0] != '\0') { - spec->value[0] = '\0'; - spec->value++; - } - return token; -} - - - -/* traverse the path specified by spec starting at current */ - -STATIC_INLINE_DEVICE\ -(device *) -split_find_device(device *current, - name_specifier *spec) -{ - /* strip off (and process) any leading ., .., ./ and / */ - while (1) { - if (strncmp(spec->path, "/", strlen("/")) == 0) { - /* cd /... */ - while (current != NULL && current->parent != NULL) - current = current->parent; - spec->path += strlen("/"); - } - else if (strncmp(spec->path, "./", strlen("./")) == 0) { - /* cd ./... */ - current = current; - spec->path += strlen("./"); - } - else if (strncmp(spec->path, "../", strlen("../")) == 0) { - /* cd ../... */ - if (current != NULL && current->parent != NULL) - current = current->parent; - spec->path += strlen("../"); - } - else if (strcmp(spec->path, ".") == 0) { - /* cd . */ - current = current; - spec->path += strlen("."); - } - else if (strcmp(spec->path, "..") == 0) { - /* cd . */ - if (current != NULL && current->parent != NULL) - current = current->parent; - spec->path += strlen(".."); - } - else - break; - } - - /* now go through the path proper */ - - if (current == NULL) { - split_device_name(spec); - return current; - } - - while (split_device_name(spec)) { - device_unit phys; - device *child; - current->callback->convert.decode_unit(current, spec->unit, &phys); - for (child = current->children; child != NULL; child = child->sibling) { - if (strcmp(spec->name, child->name) == 0) { - if (phys.nr_cells == 0 - || memcmp(&phys, &child->unit_address, sizeof(device_unit)) == 0) - break; - } - } - if (child == NULL) - return current; /* search failed */ - current = child; - } - - return current; -} - - STATIC_INLINE_DEVICE\ (device *) device_create_from(const char *name, @@ -566,7 +249,7 @@ device_create_from(const char *name, } /* give it a name */ - new_device->name = strdup(name); + new_device->name = (char *) strdup(name); new_device->unit_address = *unit_address; new_device->path = device_full_name(new_device, NULL, 0); @@ -582,35 +265,36 @@ device_create_from(const char *name, new_device->ihandles = cap_create(name); new_device->phandles = cap_create(name); } + else { + new_device->ihandles = device_root(parent)->ihandles; + new_device->phandles = device_root(parent)->phandles; + } + cap_add(new_device->phandles, new_device); return new_device; } -STATIC_INLINE_DEVICE\ + +INLINE_DEVICE\ (device *) -device_template_create_device(device *parent, - const char *name, - const char *unit_address, - const char *args) +device_create(device *parent, + const char *base, + const char *name, + const char *unit_address, + const char *args) { const device_descriptor *const *table; - int name_len; - char *chp; - chp = strchr(name, '@'); - name_len = (chp == NULL ? strlen(name) : chp - name); for (table = device_table; *table != NULL; table++) { const device_descriptor *descr; for (descr = *table; descr->name != NULL; descr++) { - if (strncmp(name, descr->name, name_len) == 0 - && (descr->name[name_len] == '\0' - || descr->name[name_len] == '@')) { + if (strcmp(base, descr->name) == 0) { device_unit address = { 0 }; void *data = NULL; - if (parent != NULL && parent->callback->convert.decode_unit != NULL) - parent->callback->convert.decode_unit(parent, - unit_address, - &address); + if (parent != NULL) + if (device_decode_unit(parent, unit_address, &address) < 0) + device_error(parent, "invalid address %s for device %s", + unit_address, name); if (descr->creator != NULL) data = descr->creator(name, &address, args); return device_create_from(name, &address, data, @@ -618,10 +302,207 @@ device_template_create_device(device *parent, } } } - device_error(parent, "attempt to attach unknown device %s\n", name); - return NULL; + device_error(parent, "attempt to attach unknown device %s", name); + return NULL; +} + + + +INLINE_DEVICE\ +(void) +device_usage(int verbose) +{ + const device_descriptor *const *table; + if (verbose == 1) { + int pos = 0; + for (table = device_table; *table != NULL; table++) { + const device_descriptor *descr; + for (descr = *table; descr->name != NULL; descr++) { + pos += strlen(descr->name) + 2; + if (pos > 75) { + pos = strlen(descr->name) + 2; + printf_filtered("\n"); + } + printf_filtered(" %s", descr->name); + } + printf_filtered("\n"); + } + } + if (verbose > 1) { + for (table = device_table; *table != NULL; table++) { + const device_descriptor *descr; + for (descr = *table; descr->name != NULL; descr++) { + printf_filtered(" %s:\n", descr->name); + /* interrupt ports */ + if (descr->callbacks->interrupt.ports != NULL) { + const device_interrupt_port_descriptor *ports = + descr->callbacks->interrupt.ports; + printf_filtered(" interrupt ports:"); + while (ports->name != NULL) { + printf_filtered(" %s", ports->name); + ports++; + } + printf_filtered("\n"); + } + /* general info */ + if (descr->callbacks->usage != NULL) + descr->callbacks->usage(verbose); + } + } + } +} + + + + + +/* Device node: */ + +INLINE_DEVICE\ +(device *) +device_parent(device *me) +{ + return me->parent; +} + +INLINE_DEVICE\ +(device *) +device_root(device *me) +{ + ASSERT(me != NULL); + while (me->parent != NULL) + me = me->parent; + return me; +} + +INLINE_DEVICE\ +(device *) +device_sibling(device *me) +{ + return me->sibling; +} + +INLINE_DEVICE\ +(device *) +device_child(device *me) +{ + return me->children; +} + +INLINE_DEVICE\ +(const char *) +device_name(device *me) +{ + return me->name; +} + +INLINE_DEVICE\ +(const char *) +device_path(device *me) +{ + return me->path; +} + +INLINE_DEVICE\ +(void *) +device_data(device *me) +{ + return me->data; +} + +INLINE_DEVICE\ +(psim *) +device_system(device *me) +{ + return me->system; +} + +INLINE_DEVICE\ +(const device_unit *) +device_unit_address(device *me) +{ + return &me->unit_address; +} + + +INLINE_DEVICE\ +(int) +device_address_to_attach_address(device *me, + const device_unit *address, + int *attach_space, + unsigned_word *attach_address, + device *client) +{ + if (me->callback->convert.address_to_attach_address == NULL) + device_error(me, "no convert.address_to_attach_address method"); + return me->callback->convert.address_to_attach_address(me, address, attach_space, attach_address, client); +} + + +INLINE_DEVICE\ +(int) +device_size_to_attach_size(device *me, + const device_unit *size, + unsigned *nr_bytes, + device *client) +{ + if (me->callback->convert.size_to_attach_size == NULL) + device_error(me, "no convert.size_to_attach_size method"); + return me->callback->convert.size_to_attach_size(me, size, nr_bytes, client); +} + + +INLINE_DEVICE\ +(int) +device_decode_unit(device *bus, + const char *unit, + device_unit *address) +{ + if (bus->callback->convert.decode_unit == NULL) + device_error(bus, "no convert.decode_unit method"); + return bus->callback->convert.decode_unit(bus, unit, address); +} + + +INLINE_DEVICE\ +(int) +device_encode_unit(device *bus, + const device_unit *unit_address, + char *buf, + int sizeof_buf) +{ + if (bus->callback->convert.encode_unit == NULL) + device_error(bus, "no convert.encode_unit method"); + return bus->callback->convert.encode_unit(bus, unit_address, buf, sizeof_buf); +} + +INLINE_DEVICE\ +(unsigned) +device_nr_address_cells(device *me) +{ + if (me->nr_address_cells == 0) { + if (device_find_property(me, "#address-cells") != NULL) + me->nr_address_cells = device_find_integer_property(me, "#address-cells"); + else + me->nr_address_cells = 2; + } + return me->nr_address_cells; +} + +INLINE_DEVICE\ +(unsigned) +device_nr_size_cells(device *me) +{ + if (me->nr_size_cells == 0) { + if (device_find_property(me, "#size-cells") != NULL) + me->nr_size_cells = device_find_integer_property(me, "#size-cells"); + else + me->nr_size_cells = 1; + } + return me->nr_size_cells; } + /* device-instance: */ @@ -636,29 +517,40 @@ device_create_instance_from(device *me, { device_instance *instance = ZALLOC(device_instance); if ((me == NULL) == (parent == NULL)) - device_error(me, "can't have both parent instance and parent device\n"); - instance->owner = me; - instance->parent = parent; - instance->data = data; - instance->args = (args == NULL ? NULL : strdup(args)); - instance->path = (path == NULL ? NULL : strdup(path)); - instance->callback = callbacks; + device_error(me, "can't have both parent instance and parent device"); /*instance->unit*/ + /* link this instance into the devices list */ if (me != NULL) { + ASSERT(parent == NULL); + instance->owner = me; + instance->parent = NULL; + /* link this instance into the front of the devices instance list */ instance->next = me->instances; me->instances = instance; } if (parent != NULL) { device_instance **previous; + ASSERT(parent->child == NULL); parent->child = instance; + ASSERT(me == NULL); instance->owner = parent->owner; + instance->parent = parent; + /* in the devices instance list replace the parent instance with + this one */ instance->next = parent->next; /* replace parent with this new node */ previous = &instance->owner->instances; - while (*previous != parent) + while (*previous != parent) { + ASSERT(*previous != NULL); previous = &(*previous)->next; + } *previous = instance; } + instance->data = data; + instance->args = (args == NULL ? NULL : (char *) strdup(args)); + instance->path = (path == NULL ? NULL : (char *) strdup(path)); + instance->callback = callbacks; + cap_add(instance->owner->ihandles, instance); return instance; } @@ -666,22 +558,16 @@ device_create_instance_from(device *me, INLINE_DEVICE\ (device_instance *) device_create_instance(device *me, - const char *device_specifier) + const char *path, + const char *args) { - /* find the device node */ - name_specifier spec; - if (!split_device_specifier(device_specifier, &spec)) - return NULL; - me = split_find_device(me, &spec); - if (spec.name != NULL) - return NULL; /* create the instance */ if (me->callback->instance_create == NULL) - device_error(me, "no instance_create method\n"); - return me->callback->instance_create(me, - device_specifier, spec.last_args); + device_error(me, "no instance_create method"); + return me->callback->instance_create(me, path, args); } + STATIC_INLINE_DEVICE\ (void) clean_device_instances(device *me) @@ -694,24 +580,40 @@ clean_device_instances(device *me) } } + INLINE_DEVICE\ (void) device_instance_delete(device_instance *instance) { device *me = instance->owner; - device_instance **curr; if (instance->callback->delete == NULL) - device_error(me, "no delete method\n"); + device_error(me, "no delete method"); instance->callback->delete(instance); if (instance->args != NULL) zfree(instance->args); if (instance->path != NULL) zfree(instance->path); - curr = &me->instances; - while (*curr != NULL && *curr != instance) - curr = &(*curr)->next; - ASSERT(*curr != NULL); - *curr = instance->next; + if (instance->child == NULL) { + /* only remove leaf nodes */ + device_instance **curr = &me->instances; + while (*curr != instance) { + ASSERT(*curr != NULL); + curr = &(*curr)->next; + } + *curr = instance->next; + } + else { + /* check it isn't in the instance list */ + device_instance *curr = me->instances; + while (curr != NULL) { + ASSERT(curr != instance); + curr = curr->next; + } + /* unlink the child */ + ASSERT(instance->child->parent == instance); + instance->child->parent = NULL; + } + cap_remove(me->ihandles, instance); zfree(instance); } @@ -723,7 +625,7 @@ device_instance_read(device_instance *instance, { device *me = instance->owner; if (instance->callback->read == NULL) - device_error(me, "no read method\n"); + device_error(me, "no read method"); return instance->callback->read(instance, addr, len); } @@ -735,7 +637,7 @@ device_instance_write(device_instance *instance, { device *me = instance->owner; if (instance->callback->write == NULL) - device_error(me, "no write method\n"); + device_error(me, "no write method"); return instance->callback->write(instance, addr, len); } @@ -747,34 +649,36 @@ device_instance_seek(device_instance *instance, { device *me = instance->owner; if (instance->callback->seek == NULL) - device_error(me, "no seek method\n"); + device_error(me, "no seek method"); return instance->callback->seek(instance, pos_hi, pos_lo); } INLINE_DEVICE\ -(unsigned_word) -device_instance_claim(device_instance *instance, - unsigned_word address, - unsigned_word length, - unsigned_word alignment) +(int) +device_instance_call_method(device_instance *instance, + const char *method_name, + int n_stack_args, + unsigned_cell stack_args[/*n_stack_args*/], + int n_stack_returns, + unsigned_cell stack_returns[/*n_stack_args*/]) { device *me = instance->owner; - if (instance->callback->claim == NULL) - device_error(me, "no claim method\n"); - return instance->callback->claim(instance, address, length, alignment); + const device_instance_methods *method = instance->callback->methods; + if (method == NULL) { + device_error(me, "no methods (want %s)", method_name); + } + while (method->name != NULL) { + if (strcmp(method->name, method_name) == 0) { + return method->method(instance, + n_stack_args, stack_args, + n_stack_returns, stack_returns); + } + method++; + } + device_error(me, "no %s method", method_name); + return 0; } -INLINE_DEVICE\ -(void) -device_instance_release(device_instance *instance, - unsigned_word address, - unsigned_word length) -{ - device *me = instance->owner; - if (instance->callback->release == NULL) - device_error(me, "no release method\n"); - instance->callback->release(instance, address, length); -} INLINE_DEVICE\ (device *) @@ -799,64 +703,24 @@ device_instance_data(device_instance *instance) -/* Device initialization: */ - -STATIC_INLINE_DEVICE\ -(void) -clean_device(device *root, - void *data) -{ - psim *system; - system = (psim*)data; - clean_device_interrupt_edges(&root->interrupt_destinations); - clean_device_instances(root); - clean_device_properties(root); -} - -STATIC_INLINE_DEVICE\ -(void) -init_device_address(device *me, - void *data) -{ - psim *system = (psim*)data; - TRACE(trace_device_init, ("init_device_address() initializing %s\n", me->path)); - me->system = system; /* misc things not known until now */ - if (me->callback->init.address != NULL) - me->callback->init.address(me); -} +/* Device Properties: */ STATIC_INLINE_DEVICE\ -(void) -init_device_data(device *me, - void *data) -{ - TRACE(trace_device_init, ("device_init_data() initializing %s\n", me->path)); - if (me->callback->init.data != NULL) - me->callback->init.data(me); -} - -INLINE_DEVICE\ -(void) -device_tree_init(device *root, - psim *system) +(device_property_entry *) +find_property_entry(device *me, + const char *property) { - TRACE(trace_device_tree, ("device_tree_init(root=0x%lx, system=0x%lx)\n", - (long)root, - (long)system)); - /* remove the old, rebuild the new */ - device_tree_traverse(root, clean_device, NULL, system); - TRACE(trace_tbd, ("Need to dump the device tree here\n")); - device_tree_traverse(root, init_device_address, NULL, system); - device_tree_traverse(root, init_device_properties, NULL, system); - device_tree_traverse(root, init_device_data, NULL, system); - TRACE(trace_device_tree, ("device_tree_init() = void\n")); + device_property_entry *entry; + ASSERT(property != NULL); + entry = me->properties; + while (entry != NULL) { + if (strcmp(entry->value->name, property) == 0) + return entry; + entry = entry->next; + } + return NULL; } - - -/* Device Properties: */ - -/* local - not available externally */ STATIC_INLINE_DEVICE\ (void) device_add_property(device *me, @@ -871,8 +735,6 @@ device_add_property(device *me, { device_property_entry *new_entry = NULL; device_property *new_value = NULL; - void *new_array = NULL; - void *new_init_array = NULL; /* find the list end */ device_property_entry **insertion_point = &me->properties; @@ -884,26 +746,28 @@ device_add_property(device *me, /* create a new value */ new_value = ZALLOC(device_property); - new_value->name = strdup(property); + new_value->name = (char *) strdup(property); new_value->type = type; - new_value->sizeof_array = sizeof_array; - new_array = (sizeof_array > 0 ? zalloc(sizeof_array) : NULL); - new_value->array = new_array; + if (sizeof_array > 0) { + void *new_array = zalloc(sizeof_array); + memcpy(new_array, array, sizeof_array); + new_value->array = new_array; + new_value->sizeof_array = sizeof_array; + } new_value->owner = me; new_value->original = original; new_value->disposition = disposition; - if (sizeof_array > 0) - memcpy(new_array, array, sizeof_array); /* insert the value into the list */ new_entry = ZALLOC(device_property_entry); *insertion_point = new_entry; - new_entry->sizeof_init_array = sizeof_init_array; - new_init_array = (sizeof_init_array > 0 ? zalloc(sizeof_init_array) : NULL); - new_entry->init_array = new_init_array; - new_entry->value = new_value; - if (sizeof_init_array > 0) + if (sizeof_init_array > 0) { + void *new_init_array = zalloc(sizeof_init_array); memcpy(new_init_array, init_array, sizeof_init_array); + new_entry->init_array = new_init_array; + new_entry->sizeof_init_array = sizeof_init_array; + } + new_entry->value = new_value; } @@ -915,35 +779,35 @@ device_set_property(device *me, const char *property, device_property_type type, const void *array, - int sizeof_array, - const device_property *original) + int sizeof_array) { /* find the property */ - device_property_entry *entry = me->properties; - while (entry != NULL) { - if (strcmp(entry->value->name, property) == 0) { - void *new_array = 0; - device_property *value = entry->value; - /* check the type matches */ - if (value->type != type) - device_error(me, "conflict between type of new and old value for property %s\n", property); - /* replace its value */ - if (value->array != NULL) - zfree((void*)value->array); - new_array = (sizeof_array > 0 - ? zalloc(sizeof_array) - : (void*)0); - value->array = new_array; - value->sizeof_array = sizeof_array; - if (sizeof_array > 0) - memcpy(new_array, array, sizeof_array); - return; - } - entry = entry->next; + device_property_entry *entry = find_property_entry(me, property); + if (entry != NULL) { + /* existing property - update it */ + void *new_array = 0; + device_property *value = entry->value; + /* check the type matches */ + if (value->type != type) + device_error(me, "conflict between type of new and old value for property %s", property); + /* replace its value */ + if (value->array != NULL) + zfree((void*)value->array); + new_array = (sizeof_array > 0 + ? zalloc(sizeof_array) + : (void*)0); + value->array = new_array; + value->sizeof_array = sizeof_array; + if (sizeof_array > 0) + memcpy(new_array, array, sizeof_array); + return; + } + else { + /* new property - create it */ + device_add_property(me, property, type, + NULL, 0, array, sizeof_array, + NULL, tempoary_object); } - device_add_property(me, property, type, - NULL, 0, array, sizeof_array, - original, tempoary_object); } @@ -954,70 +818,105 @@ clean_device_properties(device *me) device_property_entry **delete_point = &me->properties; while (*delete_point != NULL) { device_property_entry *current = *delete_point; - device_property *property = current->value; switch (current->value->disposition) { case permenant_object: - { - /* delete the property, and replace it with the original */ - ASSERT(((property->array == NULL) == (current->init_array == NULL)) - || property->type == ihandle_property); - if (current->init_array != NULL) { - zfree((void*)current->value->array); - current->value->array = NULL; - if (property->type != ihandle_property) { - device_set_property(me, property->name, - property->type, - current->init_array, current->sizeof_init_array, - NULL); - } - } - delete_point = &(*delete_point)->next; + /* zap the current value, will be initialized later */ + ASSERT(current->init_array != NULL); + if (current->value->array != NULL) { + zfree((void*)current->value->array); + current->value->array = NULL; } + delete_point = &(*delete_point)->next; break; case tempoary_object: - { - /* zap the actual property, was created during simulation run */ - *delete_point = current->next; - if (current->value->array != NULL) - zfree((void*)current->value->array); - zfree(current->value); - zfree(current); - } + /* zap the actual property, was created during simulation run */ + ASSERT(current->init_array == NULL); + *delete_point = current->next; + if (current->value->array != NULL) + zfree((void*)current->value->array); + zfree(current->value); + zfree(current); break; } } } -STATIC_INLINE_DEVICE\ +INLINE_DEVICE\ +(void) +device_init_static_properties(device *me, + void *data) +{ + device_property_entry *property; + for (property = me->properties; + property != NULL; + property = property->next) { + ASSERT(property->init_array != NULL); + ASSERT(property->value->array == NULL); + ASSERT(property->value->disposition == permenant_object); + switch (property->value->type) { + case array_property: + case boolean_property: + case range_array_property: + case reg_array_property: + case string_property: + case string_array_property: + case integer_property: + /* delete the property, and replace it with the original */ + device_set_property(me, property->value->name, + property->value->type, + property->init_array, + property->sizeof_init_array); + break; + case ihandle_property: + break; + } + } +} + + +INLINE_DEVICE\ (void) -init_device_properties(device *me, - void *data) -{ - device_property_entry *property = me->properties; - while (property != NULL) { - /* now do the phandles */ - if (property->value->type == ihandle_property) { - if (property->value->original != NULL) { - const device_property *original = property->value->original; - if (original->array == NULL) { - init_device_properties(original->owner, data); +device_init_runtime_properties(device *me, + void *data) +{ + device_property_entry *property; + for (property = me->properties; + property != NULL; + property = property->next) { + switch (property->value->disposition) { + case permenant_object: + switch (property->value->type) { + case ihandle_property: + { + device_instance *ihandle; + ihandle_runtime_property_spec spec; + ASSERT(property->init_array != NULL); + ASSERT(property->value->array == NULL); + device_find_ihandle_runtime_property(me, property->value->name, &spec); + ihandle = device_create_instance(spec.phandle, + spec.full_path, + spec.args); + device_set_ihandle_property(me, property->value->name, ihandle); + break; } - ASSERT(original->array != NULL); - device_set_property(me, property->value->name, - ihandle_property, - original->array, original->sizeof_array, NULL); - } - else { - device_instance *instance = - device_create_instance(me, (char*)property->init_array); - unsigned32 ihandle = H2BE_4(device_instance_to_external(instance)); - device_set_property(me, property->value->name, - ihandle_property, - &ihandle, sizeof(ihandle), NULL); + case array_property: + case boolean_property: + case range_array_property: + case integer_property: + case reg_array_property: + case string_property: + case string_array_property: + ASSERT(property->init_array != NULL); + ASSERT(property->value->array != NULL); + break; } + break; + case tempoary_object: + ASSERT(property->init_array == NULL); + ASSERT(property->value->array != NULL); + break; } - property = property->next; } } @@ -1039,12 +938,12 @@ device_next_property(const device_property *property) return NULL; } + INLINE_DEVICE\ (const device_property *) device_find_property(device *me, const char *property) { - name_specifier spec; if (me == NULL) { return NULL; } @@ -1054,33 +953,25 @@ device_find_property(device *me, else return me->properties->value; } - else if (split_property_specifier(property, &spec)) { - me = split_find_device(me, &spec); - if (spec.name == NULL) { /*got to root*/ - device_property_entry *entry = me->properties; - while (entry != NULL) { - if (strcmp(entry->value->name, spec.property) == 0) - return entry->value; - entry = entry->next; - } - } + else { + device_property_entry *entry = find_property_entry(me, property); + if (entry != NULL) + return entry->value; } return NULL; } -STATIC_INLINE_DEVICE\ + +INLINE_DEVICE\ (void) device_add_array_property(device *me, - const char *property, - const void *array, - int sizeof_array) + const char *property, + const void *array, + int sizeof_array) { - TRACE(trace_devices, - ("device_add_array_property(me=0x%lx, property=%s, ...)\n", - (long)me, property)); device_add_property(me, property, array_property, - array, sizeof_array, array, sizeof_array, - NULL, permenant_object); + array, sizeof_array, array, sizeof_array, + NULL, permenant_object); } INLINE_DEVICE\ @@ -1090,10 +981,7 @@ device_set_array_property(device *me, const void *array, int sizeof_array) { - TRACE(trace_devices, - ("device_set_array_property(me=0x%lx, property=%s, ...)\n", - (long)me, property)); - device_set_property(me, property, array_property, array, sizeof_array, NULL); + device_set_property(me, property, array_property, array, sizeof_array); } INLINE_DEVICE\ @@ -1102,31 +990,25 @@ device_find_array_property(device *me, const char *property) { const device_property *node; - TRACE(trace_devices, - ("device_find_integer(me=0x%lx, property=%s)\n", - (long)me, property)); node = device_find_property(me, property); if (node == (device_property*)0 || node->type != array_property) - device_error(me, "property %s not found or of wrong type\n", property); + device_error(me, "property %s not found or of wrong type", property); return node; } -STATIC_INLINE_DEVICE\ +INLINE_DEVICE\ (void) device_add_boolean_property(device *me, - const char *property, - int boolean) + const char *property, + int boolean) { signed32 new_boolean = (boolean ? -1 : 0); - TRACE(trace_devices, - ("device_add_boolean(me=0x%lx, property=%s, boolean=%d)\n", - (long)me, property, boolean)); device_add_property(me, property, boolean_property, - &new_boolean, sizeof(new_boolean), - &new_boolean, sizeof(new_boolean), - NULL, permenant_object); + &new_boolean, sizeof(new_boolean), + &new_boolean, sizeof(new_boolean), + NULL, permenant_object); } INLINE_DEVICE\ @@ -1135,108 +1017,427 @@ device_find_boolean_property(device *me, const char *property) { const device_property *node; - unsigned32 boolean; - TRACE(trace_devices, - ("device_find_boolean(me=0x%lx, property=%s)\n", - (long)me, property)); + unsigned_cell boolean; node = device_find_property(me, property); if (node == (device_property*)0 || node->type != boolean_property) - device_error(me, "property %s not found or of wrong type\n", property); + device_error(me, "property %s not found or of wrong type", property); ASSERT(sizeof(boolean) == node->sizeof_array); memcpy(&boolean, node->array, sizeof(boolean)); return boolean; } -STATIC_INLINE_DEVICE\ + +INLINE_DEVICE\ (void) -device_add_ihandle_property(device *me, - const char *property, - const char *path) +device_add_ihandle_runtime_property(device *me, + const char *property, + const ihandle_runtime_property_spec *ihandle) { - TRACE(trace_devices, - ("device_add_ihandle_property(me=0x%lx, property=%s, path=%s)\n", - (long)me, property, path)); + unsigned_cell *cells; + char *chp; + unsigned sizeof_cells = (sizeof(unsigned_cell) * 3 + + (strlen(ihandle->full_path) + 1) + + (ihandle->args != NULL + ? (strlen(ihandle->args) + 1) + : 0)); + + /* the basics */ + cells = zalloc(sizeof_cells); + cells[0] = H2BE_cell(device_to_external(ihandle->phandle)); + cells[1] = (ihandle->full_path == NULL ? 0 : -1); + cells[2] = (ihandle->args == NULL ? 0 : -1); + chp = (char*)&cells[3]; + + /* the full path (if present) */ + if (ihandle->full_path != NULL) { + strcpy(chp, ihandle->full_path); + chp += strlen(ihandle->full_path) + 1; + } + + /* the args (if present) */ + if (ihandle->args != NULL) { + strcpy(chp, ihandle->args); + chp += strlen(ihandle->args) + 1; + } + + /* add it */ + ASSERT(sizeof_cells == (chp - (char*)cells)); device_add_property(me, property, ihandle_property, - path, strlen(path) + 1, + cells, sizeof_cells, NULL, 0, NULL, permenant_object); } +INLINE_DEVICE\ +(void) +device_find_ihandle_runtime_property(device *me, + const char *property, + ihandle_runtime_property_spec *ihandle) +{ + const unsigned_cell *cells; + const char *chp; + device_property_entry *entry = find_property_entry(me, property); + TRACE(trace_devices, + ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n", + (long)me, property)); + if (entry == NULL + || entry->value->type != ihandle_property + || entry->value->disposition != permenant_object) + device_error(me, "property %s not found or of wrong type", property); + cells = entry->init_array; + chp = (char*)&cells[3]; + ASSERT(entry->init_array != NULL); + /* the device to be opened */ + ihandle->phandle = external_to_device(me, BE2H_cell(cells[0])); + /* the full path */ + if (cells[1] != 0) { + ihandle->full_path = chp; + chp += strlen(ihandle->full_path) + 1; + } + else + ihandle->full_path = NULL; + /* the args */ + if (cells[2] != 0) { + ihandle->args = chp; + chp += strlen(ihandle->args) + 1; + } + else + ihandle->args = NULL; + /* reached the end? */ + ASSERT(entry->sizeof_init_array + == (chp - (char*)cells)); + return; +} + + + +INLINE_DEVICE\ +(void) +device_set_ihandle_property(device *me, + const char *property, + device_instance *ihandle) +{ + unsigned_cell cells; + cells = H2BE_cell(device_instance_to_external(ihandle)); + device_set_property(me, property, ihandle_property, + &cells, sizeof(cells)); + +} + INLINE_DEVICE\ (device_instance *) device_find_ihandle_property(device *me, const char *property) { const device_property *node; - unsigned32 ihandle; + unsigned_cell ihandle; device_instance *instance; - TRACE(trace_devices, - ("device_find_ihandle_property(me=0x%lx, property=%s)\n", - (long)me, property)); + node = device_find_property(me, property); if (node == NULL || node->type != ihandle_property) - device_error(me, "property %s not found or of wrong type\n", property); + device_error(me, "property %s not found or of wrong type", property); if (node->array == NULL) - device_error(me, "property %s not yet initialized\n", property); + device_error(me, "runtime property %s not yet initialized", property); + ASSERT(sizeof(ihandle) == node->sizeof_array); memcpy(&ihandle, node->array, sizeof(ihandle)); - BE2H(ihandle); - instance = external_to_device_instance(me, ihandle); + instance = external_to_device_instance(me, BE2H_cell(ihandle)); ASSERT(instance != NULL); return instance; } + +INLINE_DEVICE\ +(void) +device_add_integer_property(device *me, + const char *property, + signed_cell integer) +{ + H2BE(integer); + device_add_property(me, property, integer_property, + &integer, sizeof(integer), + &integer, sizeof(integer), + NULL, permenant_object); +} + +INLINE_DEVICE\ +(signed_cell) +device_find_integer_property(device *me, + const char *property) +{ + const device_property *node; + signed_cell integer; + TRACE(trace_devices, + ("device_find_integer(me=0x%lx, property=%s)\n", + (long)me, property)); + node = device_find_property(me, property); + if (node == (device_property*)0 + || node->type != integer_property) + device_error(me, "property %s not found or of wrong type", property); + ASSERT(sizeof(integer) == node->sizeof_array); + memcpy(&integer, node->array, sizeof(integer)); + return BE2H_cell(integer); +} + +INLINE_DEVICE\ +(int) +device_find_integer_array_property(device *me, + const char *property, + unsigned index, + signed_cell *integer) +{ + const device_property *node; + int sizeof_integer = sizeof(*integer); + signed_cell *cell; + TRACE(trace_devices, + ("device_find_integer(me=0x%lx, property=%s)\n", + (long)me, property)); + + /* check things sane */ + node = device_find_property(me, property); + if (node == (device_property*)0 + || (node->type != integer_property + && node->type != array_property)) + device_error(me, "property %s not found or of wrong type", property); + if ((node->sizeof_array % sizeof_integer) != 0) + device_error(me, "property %s contains an incomplete number of cells", property); + if (node->sizeof_array <= sizeof_integer * index) + return 0; + + /* Find and convert the value */ + cell = ((signed_cell*)node->array) + index; + *integer = BE2H_cell(*cell); + + return node->sizeof_array / sizeof_integer; +} + + +STATIC_INLINE_DEVICE\ +(unsigned_cell *) +unit_address_to_cells(const device_unit *unit, + unsigned_cell *cell, + int nr_cells) +{ + int i; + ASSERT(nr_cells == unit->nr_cells); + for (i = 0; i < unit->nr_cells; i++) { + *cell = H2BE_cell(unit->cells[i]); + cell += 1; + } + return cell; +} + + +STATIC_INLINE_DEVICE\ +(const unsigned_cell *) +cells_to_unit_address(const unsigned_cell *cell, + device_unit *unit, + int nr_cells) +{ + int i; + memset(unit, 0, sizeof(*unit)); + unit->nr_cells = nr_cells; + for (i = 0; i < unit->nr_cells; i++) { + unit->cells[i] = BE2H_cell(*cell); + cell += 1; + } + return cell; +} + + +STATIC_INLINE_DEVICE\ +(unsigned) +nr_range_property_cells(device *me, + int nr_ranges) +{ + return ((device_nr_address_cells(me) + + device_nr_address_cells(device_parent(me)) + + device_nr_size_cells(me)) + ) * nr_ranges; +} + +INLINE_DEVICE\ +(void) +device_add_range_array_property(device *me, + const char *property, + const range_property_spec *ranges, + unsigned nr_ranges) +{ + unsigned sizeof_cells = (nr_range_property_cells(me, nr_ranges) + * sizeof(unsigned_cell)); + unsigned_cell *cells = zalloc(sizeof_cells); + unsigned_cell *cell; + int i; + + /* copy the property elements over */ + cell = cells; + for (i = 0; i < nr_ranges; i++) { + const range_property_spec *range = &ranges[i]; + /* copy the child address */ + cell = unit_address_to_cells(&range->child_address, cell, + device_nr_address_cells(me)); + /* copy the parent address */ + cell = unit_address_to_cells(&range->parent_address, cell, + device_nr_address_cells(device_parent(me))); + /* copy the size */ + cell = unit_address_to_cells(&range->size, cell, + device_nr_size_cells(me)); + } + ASSERT(cell == &cells[nr_range_property_cells(me, nr_ranges)]); + + /* add it */ + device_add_property(me, property, range_array_property, + cells, sizeof_cells, + cells, sizeof_cells, + NULL, permenant_object); + + zfree(cells); +} + +INLINE_DEVICE\ +(int) +device_find_range_array_property(device *me, + const char *property, + unsigned index, + range_property_spec *range) +{ + const device_property *node; + unsigned sizeof_entry = (nr_range_property_cells(me, 1) + * sizeof(unsigned_cell)); + const unsigned_cell *cells; + + /* locate the property */ + node = device_find_property(me, property); + if (node == (device_property*)0 + || node->type != range_array_property) + device_error(me, "property %s not found or of wrong type", property); + + /* aligned ? */ + if ((node->sizeof_array % sizeof_entry) != 0) + device_error(me, "property %s contains an incomplete number of entries", + property); + + /* within bounds? */ + if (node->sizeof_array < sizeof_entry * (index + 1)) + return 0; + + /* find the range of interest */ + cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); + + /* copy the child address out - converting as we go */ + cells = cells_to_unit_address(cells, &range->child_address, + device_nr_address_cells(me)); + + /* copy the parent address out - converting as we go */ + cells = cells_to_unit_address(cells, &range->parent_address, + device_nr_address_cells(device_parent(me))); + + /* copy the size - converting as we go */ + cells = cells_to_unit_address(cells, &range->size, + device_nr_size_cells(me)); + + return node->sizeof_array / sizeof_entry; +} + + STATIC_INLINE_DEVICE\ -(void) -device_add_integer_property(device *me, - const char *property, - signed32 integer) +(unsigned) +nr_reg_property_cells(device *me, + int nr_regs) { - TRACE(trace_devices, - ("device_add_integer_property(me=0x%lx, property=%s, integer=%ld)\n", - (long)me, property, (long)integer)); - H2BE(integer); - device_add_property(me, property, integer_property, - &integer, sizeof(integer), - &integer, sizeof(integer), + return (device_nr_address_cells(device_parent(me)) + + device_nr_size_cells(device_parent(me)) + ) * nr_regs; +} + +INLINE_DEVICE\ +(void) +device_add_reg_array_property(device *me, + const char *property, + const reg_property_spec *regs, + unsigned nr_regs) +{ + unsigned sizeof_cells = (nr_reg_property_cells(me, nr_regs) + * sizeof(unsigned_cell)); + unsigned_cell *cells = zalloc(sizeof_cells); + unsigned_cell *cell; + int i; + + /* copy the property elements over */ + cell = cells; + for (i = 0; i < nr_regs; i++) { + const reg_property_spec *reg = ®s[i]; + /* copy the address */ + cell = unit_address_to_cells(®->address, cell, + device_nr_address_cells(device_parent(me))); + /* copy the size */ + cell = unit_address_to_cells(®->size, cell, + device_nr_size_cells(device_parent(me))); + } + ASSERT(cell == &cells[nr_reg_property_cells(me, nr_regs)]); + + /* add it */ + device_add_property(me, property, reg_array_property, + cells, sizeof_cells, + cells, sizeof_cells, NULL, permenant_object); + + zfree(cells); } INLINE_DEVICE\ -(signed_word) -device_find_integer_property(device *me, - const char *property) +(int) +device_find_reg_array_property(device *me, + const char *property, + unsigned index, + reg_property_spec *reg) { const device_property *node; - signed32 integer; - TRACE(trace_devices, - ("device_find_integer(me=0x%lx, property=%s)\n", - (long)me, property)); + unsigned sizeof_entry = (nr_reg_property_cells(me, 1) + * sizeof(unsigned_cell)); + const unsigned_cell *cells; + + /* locate the property */ node = device_find_property(me, property); if (node == (device_property*)0 - || node->type != integer_property) - device_error(me, "property %s not found or of wrong type\n", property); - ASSERT(sizeof(integer) == node->sizeof_array); - memcpy(&integer, node->array, sizeof(integer)); - BE2H(integer); - return integer; + || node->type != reg_array_property) + device_error(me, "property %s not found or of wrong type", property); + + /* aligned ? */ + if ((node->sizeof_array % sizeof_entry) != 0) + device_error(me, "property %s contains an incomplete number of entries", + property); + + /* within bounds? */ + if (node->sizeof_array < sizeof_entry * (index + 1)) + return 0; + + /* find the range of interest */ + cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); + + /* copy the address out - converting as we go */ + cells = cells_to_unit_address(cells, ®->address, + device_nr_address_cells(device_parent(me))); + + /* copy the size out - converting as we go */ + cells = cells_to_unit_address(cells, ®->size, + device_nr_size_cells(device_parent(me))); + + return node->sizeof_array / sizeof_entry; } -STATIC_INLINE_DEVICE\ + +INLINE_DEVICE\ (void) device_add_string_property(device *me, - const char *property, - const char *string) + const char *property, + const char *string) { - - TRACE(trace_devices, - ("device_add_property(me=0x%lx, property=%s, string=%s)\n", - (long)me, property, string)); device_add_property(me, property, string_property, - string, strlen(string) + 1, - string, strlen(string) + 1, - NULL, permenant_object); + string, strlen(string) + 1, + string, strlen(string) + 1, + NULL, permenant_object); } INLINE_DEVICE\ @@ -1246,32 +1447,133 @@ device_find_string_property(device *me, { const device_property *node; const char *string; - TRACE(trace_devices, - ("device_find_string(me=0x%lx, property=%s)\n", - (long)me, property)); node = device_find_property(me, property); if (node == (device_property*)0 || node->type != string_property) - device_error(me, "property %s not found or of wrong type\n", property); + device_error(me, "property %s not found or of wrong type", property); string = node->array; ASSERT(strlen(string) + 1 == node->sizeof_array); return string; } -STATIC_INLINE_DEVICE\ +INLINE_DEVICE\ +(void) +device_add_string_array_property(device *me, + const char *property, + const string_property_spec *strings, + unsigned nr_strings) +{ + int sizeof_array; + int string_nr; + char *array; + char *chp; + if (nr_strings == 0) + device_error(me, "property %s must be non-null", property); + /* total up the size of the needed array */ + for (sizeof_array = 0, string_nr = 0; + string_nr < nr_strings; + string_nr ++) { + sizeof_array += strlen(strings[string_nr]) + 1; + } + /* create the array */ + array = (char*)zalloc(sizeof_array); + chp = array; + for (string_nr = 0; + string_nr < nr_strings; + string_nr++) { + strcpy(chp, strings[string_nr]); + chp += strlen(chp) + 1; + } + ASSERT(chp == array + sizeof_array); + /* now enter it */ + device_add_property(me, property, string_array_property, + array, sizeof_array, + array, sizeof_array, + NULL, permenant_object); +} + +INLINE_DEVICE\ +(int) +device_find_string_array_property(device *me, + const char *property, + unsigned index, + string_property_spec *string) +{ + const device_property *node; + node = device_find_property(me, property); + if (node == (device_property*)0) + device_error(me, "property %s not found", property); + switch (node->type) { + default: + device_error(me, "property %s of wrong type", property); + break; + case string_property: + if (index == 0) { + *string = node->array; + ASSERT(strlen(*string) + 1 == node->sizeof_array); + return 1; + } + break; + case array_property: + if (node->sizeof_array == 0 + || ((char*)node->array)[node->sizeof_array - 1] != '\0') + device_error(me, "property %s invalid for string array", property); + /* FALL THROUGH */ + case string_array_property: + ASSERT(node->sizeof_array > 0); + ASSERT(((char*)node->array)[node->sizeof_array - 1] == '\0'); + { + const char *chp = node->array; + int nr_entries = 0; + /* count the number of strings, keeping an eye out for the one + we're looking for */ + *string = chp; + do { + if (*chp == '\0') { + /* next string */ + nr_entries++; + chp++; + if (nr_entries == index) + *string = chp; + } + else { + chp++; + } + } while (chp < (char*)node->array + node->sizeof_array); + if (index < nr_entries) + return nr_entries; + else { + *string = NULL; + return 0; + } + } + break; + } + return 0; +} + +INLINE_DEVICE\ (void) device_add_duplicate_property(device *me, const char *property, const device_property *original) { + device_property_entry *master; TRACE(trace_devices, ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n", (long)me, property)); if (original->disposition != permenant_object) - device_error(me, "Can only duplicate permenant objects\n"); + device_error(me, "Can only duplicate permenant objects"); + /* find the original's master */ + master = original->owner->properties; + while (master->value != original) { + master = master->next; + ASSERT(master != NULL); + } + /* now duplicate it */ device_add_property(me, property, original->type, - original->array, original->sizeof_array, + master->init_array, master->sizeof_init_array, original->array, original->sizeof_array, original, permenant_object); } @@ -1291,7 +1593,7 @@ device_io_read_buffer(device *me, unsigned_word cia) { if (me->callback->io.read_buffer == NULL) - device_error(me, "no io_read_buffer method\n"); + device_error(me, "no io.read_buffer method"); return me->callback->io.read_buffer(me, dest, space, addr, nr_bytes, processor, cia); @@ -1308,7 +1610,7 @@ device_io_write_buffer(device *me, unsigned_word cia) { if (me->callback->io.write_buffer == NULL) - device_error(me, "no io_write_buffer method\n"); + device_error(me, "no io.write_buffer method"); return me->callback->io.write_buffer(me, source, space, addr, nr_bytes, processor, cia); @@ -1323,7 +1625,7 @@ device_dma_read_buffer(device *me, unsigned nr_bytes) { if (me->callback->dma.read_buffer == NULL) - device_error(me, "no dma_read_buffer method\n"); + device_error(me, "no dma.read_buffer method"); return me->callback->dma.read_buffer(me, dest, space, addr, nr_bytes); } @@ -1338,7 +1640,7 @@ device_dma_write_buffer(device *me, int violate_read_only_section) { if (me->callback->dma.write_buffer == NULL) - device_error(me, "no dma_write_buffer method\n"); + device_error(me, "no dma.write_buffer method"); return me->callback->dma.write_buffer(me, source, space, addr, nr_bytes, violate_read_only_section); @@ -1347,35 +1649,33 @@ device_dma_write_buffer(device *me, INLINE_DEVICE\ (void) device_attach_address(device *me, - const char *name, attach_type attach, int space, unsigned_word addr, unsigned nr_bytes, access_type access, - device *who) /*callback/default*/ + device *client) /*callback/default*/ { if (me->callback->address.attach == NULL) - device_error(me, "no address_attach method\n"); - me->callback->address.attach(me, name, attach, space, - addr, nr_bytes, access, who); + device_error(me, "no address.attach method"); + me->callback->address.attach(me, attach, space, + addr, nr_bytes, access, client); } INLINE_DEVICE\ (void) device_detach_address(device *me, - const char *name, attach_type attach, int space, unsigned_word addr, unsigned nr_bytes, access_type access, - device *who) /*callback/default*/ + device *client) /*callback/default*/ { if (me->callback->address.detach == NULL) - device_error(me, "no address_detach method\n"); - me->callback->address.detach(me, name, attach, space, - addr, nr_bytes, access, who); + device_error(me, "no address.detach method"); + me->callback->address.detach(me, attach, space, + addr, nr_bytes, access, client); } @@ -1397,7 +1697,7 @@ device_interrupt_event(device *me, edge = edge->next) { if (edge->my_port == my_port) { if (edge->dest->callback->interrupt.event == NULL) - device_error(me, "no interrupt method\n"); + device_error(me, "no interrupt method"); edge->dest->callback->interrupt.event(edge->dest, edge->dest_port, me, @@ -1408,7 +1708,7 @@ device_interrupt_event(device *me, } } if (!found_an_edge) { - device_error(me, "No interrupt edge for port %d\n", my_port); + device_error(me, "No interrupt edge for port %d", my_port); } } @@ -1441,10 +1741,27 @@ device_interrupt_detach(device *me, dest_port); } +INLINE_DEVICE\ +(void) +device_interrupt_traverse(device *me, + device_interrupt_traverse_function *handler, + void *data) +{ + device_interrupt_edge *interrupt_edge; + for (interrupt_edge = me->interrupt_destinations; + interrupt_edge != NULL; + interrupt_edge = interrupt_edge->next) { + handler(me, interrupt_edge->my_port, + interrupt_edge->dest, interrupt_edge->dest_port, + data); + } +} + INLINE_DEVICE\ (int) device_interrupt_decode(device *me, - const char *port_name) + const char *port_name, + port_direction direction) { if (port_name == NULL || port_name[0] == '\0') return 0; @@ -1456,27 +1773,30 @@ device_interrupt_decode(device *me, me->callback->interrupt.ports; if (ports != NULL) { while (ports->name != NULL) { - if (ports->bound > ports->number) { - int len = strlen(ports->name); - if (strncmp(port_name, ports->name, len) == 0) { - if (port_name[len] == '\0') - return ports->number; - else if(isdigit(port_name[len])) { - int port = ports->number + strtoul(&port_name[len], NULL, 0); - if (port >= ports->bound) - device_error(me, "Interrupt port %s out of range\n", - port_name); - return port; + if (ports->direction == bidirect_port + || ports->direction == direction) { + if (ports->nr_ports > 0) { + int len = strlen(ports->name); + if (strncmp(port_name, ports->name, len) == 0) { + if (port_name[len] == '\0') + return ports->number; + else if(isdigit(port_name[len])) { + int port = ports->number + strtoul(&port_name[len], NULL, 0); + if (port >= ports->number + ports->nr_ports) + device_error(me, "Interrupt port %s out of range", + port_name); + return port; + } } } + else if (strcmp(port_name, ports->name) == 0) + return ports->number; } - else if (strcmp(port_name, ports->name) == 0) - return ports->number; ports++; } } } - device_error(me, "Unreconized interrupt port %s\n", port_name); + device_error(me, "Unreconized interrupt port %s", port_name); return 0; } @@ -1485,28 +1805,32 @@ INLINE_DEVICE\ device_interrupt_encode(device *me, int port_number, char *buf, - int sizeof_buf) + int sizeof_buf, + port_direction direction) { const device_interrupt_port_descriptor *ports = NULL; ports = me->callback->interrupt.ports; if (ports != NULL) { while (ports->name != NULL) { - if (ports->bound > ports->number) { - if (port_number >= ports->number - && port_number < ports->bound) { - strcpy(buf, ports->name); - sprintf(buf + strlen(buf), "%d", port_number - ports->number); - if (strlen(buf) >= sizeof_buf) - error("device_interrupt_encode:buffer overflow\n"); - return strlen(buf); + if (ports->direction == bidirect_port + || ports->direction == direction) { + if (ports->nr_ports > 0) { + if (port_number >= ports->number + && port_number < ports->number + ports->nr_ports) { + strcpy(buf, ports->name); + sprintf(buf + strlen(buf), "%d", port_number - ports->number); + if (strlen(buf) >= sizeof_buf) + error("device_interrupt_encode: buffer overflow"); + return strlen(buf); + } } - } - else { - if (ports->number == port_number) { - if (strlen(ports->name) >= sizeof_buf) - error("device_interrupt_encode: buffer overflow\n"); - strcpy(buf, ports->name); - return strlen(buf); + else { + if (ports->number == port_number) { + if (strlen(ports->name) >= sizeof_buf) + error("device_interrupt_encode: buffer overflow"); + strcpy(buf, ports->name); + return strlen(buf); + } } } ports++; @@ -1514,7 +1838,7 @@ device_interrupt_encode(device *me, } sprintf(buf, "%d", port_number); if (strlen(buf) >= sizeof_buf) - error("device_interrupt_encode: buffer overflow\n"); + error("device_interrupt_encode: buffer overflow"); return strlen(buf); } @@ -1527,14 +1851,15 @@ EXTERN_DEVICE\ device_ioctl(device *me, cpu *processor, unsigned_word cia, + device_ioctl_request request, ...) { int status; va_list ap; - va_start(ap, cia); + va_start(ap, request); if (me->callback->ioctl == NULL) - device_error(me, "no ioctl method\n"); - status = me->callback->ioctl(me, processor, cia, ap); + device_error(me, "no ioctl method"); + status = me->callback->ioctl(me, processor, cia, request, ap); va_end(ap); return status; } @@ -1557,413 +1882,170 @@ device_error(device *me, va_end(ap); /* sanity check */ if (strlen(message) >= sizeof(message)) - error("device_error: buffer overflow\n"); + error("device_error: buffer overflow"); if (me == NULL) - error("device: %s\n", message); + error("device: %s", message); + else if (me->path != NULL && me->path[0] != '\0') + error("%s: %s", me->path, message); + else if (me->name != NULL && me->name[0] != '\0') + error("%s: %s", me->name, message); else - error("%s: %s\n", me->path, message); + error("device: %s", message); while(1); } +INLINE_DEVICE\ +(int) +device_trace(device *me) +{ + return me->trace; +} + -/* Tree utilities: */ +/* External representation */ -EXTERN_DEVICE\ +INLINE_DEVICE\ (device *) -device_tree_add_parsed(device *current, - const char *fmt, - ...) -{ - char device_specifier[1024]; - name_specifier spec; - - /* format the path */ - { - va_list ap; - va_start(ap, fmt); - vsprintf(device_specifier, fmt, ap); - va_end(ap); - if (strlen(device_specifier) >= sizeof(device_specifier)) - error("device_tree_add_parsed: buffer overflow\n"); - } - - /* break it up */ - if (!split_device_specifier(device_specifier, &spec)) - device_error(current, "error parsing %s\n", device_specifier); - - /* fill our tree with its contents */ - current = split_find_device(current, &spec); - - /* add any additional devices as needed */ - if (spec.name != NULL) { - do { - current = - device_template_create_device(current, spec.name, spec.unit, spec.args); - } while (split_device_name(&spec)); - } - - /* is there an interrupt spec */ - if (spec.property == NULL - && spec.value != NULL) { - char *op = split_value(&spec); - switch (op[0]) { - case '>': - { - char *my_port_name = split_value(&spec); - char *dest_port_name = split_value(&spec); - device *dest = device_tree_find_device(current, split_value(&spec)); - int my_port = device_interrupt_decode(current, my_port_name); - int dest_port = device_interrupt_decode(dest, dest_port_name); - device_interrupt_attach(current, - my_port, - dest, - dest_port, - permenant_object); - } - break; - default: - device_error(current, "unreconised interrupt spec %s\n", spec.value); - break; - } - } - - /* is there a property */ - if (spec.property != NULL) { - if (strcmp(spec.value, "true") == 0) - device_add_boolean_property(current, spec.property, 1); - else if (strcmp(spec.value, "false") == 0) - device_add_boolean_property(current, spec.property, 0); - else { - const device_property *property; - switch (spec.value[0]) { - case '*': - { - spec.value++; - device_add_ihandle_property(current, spec.property, spec.value); - } - break; - case '-': case '+': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - unsigned long ul = strtoul(spec.value, &spec.value, 0); - device_add_integer_property(current, spec.property, ul); - } - break; - case '[': - { - unsigned8 words[1024]; - char *curr = spec.value + 1; - int nr_words = 0; - while (1) { - char *next; - words[nr_words] = H2BE_1(strtoul(curr, &next, 0)); - if (curr == next) - break; - curr = next; - nr_words += 1; - } - device_add_array_property(current, spec.property, - words, sizeof(words[0]) * nr_words); - } - break; - case '{': - { - unsigned32 words[1024]; - char *curr = spec.value + 1; - int nr_words = 0; - while (1) { - char *next; - words[nr_words] = H2BE_4(strtoul(curr, &next, 0)); - if (curr == next) - break; - curr = next; - nr_words += 1; - } - device_add_array_property(current, spec.property, - words, sizeof(words[0]) * nr_words); - } - break; - case '"': - spec.value++; - default: - device_add_string_property(current, spec.property, spec.value); - break; - case '!': - spec.value++; - property = device_find_property(current, spec.value); - if (property == NULL) - device_error(current, "property %s not found\n", spec.value); - device_add_duplicate_property(current, - spec.property, - property); - break; - } - } - } - return current; +external_to_device(device *tree_member, + unsigned_cell phandle) +{ + device *me = cap_internal(tree_member->phandles, phandle); + return me; } INLINE_DEVICE\ -(void) -device_tree_traverse(device *root, - device_tree_traverse_function *prefix, - device_tree_traverse_function *postfix, - void *data) -{ - device *child; - if (prefix != NULL) - prefix(root, data); - for (child = root->children; child != NULL; child = child->sibling) { - device_tree_traverse(child, prefix, postfix, data); - } - if (postfix != NULL) - postfix(root, data); +(unsigned_cell) +device_to_external(device *me) +{ + unsigned_cell phandle = cap_external(me->phandles, me); + return phandle; } INLINE_DEVICE\ -(void) -device_tree_print_device(device *me, - void *ignore_or_null) +(device_instance *) +external_to_device_instance(device *tree_member, + unsigned_cell ihandle) { - const device_property *property; - device_interrupt_edge *interrupt_edge; - /* output my name */ - printf_filtered("%s\n", me->path); - /* properties */ - for (property = device_find_property(me, NULL); - property != NULL; - property = device_next_property(property)) { - printf_filtered("%s/%s", me->path, property->name); - if (property->original != NULL) { - printf_filtered(" !"); - printf_filtered("%s/%s\n", property->original->owner->path, - property->original->name); - } - else { - switch (property->type) { - case array_property: - { - if ((property->sizeof_array % sizeof(unsigned32)) == 0) { - unsigned32 *w = (unsigned32*)property->array; - printf_filtered(" {"); - while ((char*)w - (char*)property->array < property->sizeof_array) { - printf_filtered(" 0x%lx", BE2H_4(*w)); - w++; - } - } - else { - unsigned8 *w = (unsigned8*)property->array; - printf_filtered(" ["); - while ((char*)w - (char*)property->array < property->sizeof_array) { - printf_filtered(" 0x%2x", BE2H_1(*w)); - w++; - } - } - printf_filtered("\n"); - } - break; - case boolean_property: - { - int b = device_find_boolean_property(me, property->name); - printf_filtered(" %s\n", b ? "true" : "false"); - } - break; - case ihandle_property: - { - if (property->array != NULL) { - device_instance *i = device_find_ihandle_property(me, property->name); - printf_filtered(" *%s\n", i->path); - } - else { - /* drats, the instance hasn't yet been created. Grub - around and find the path that will be used to create - the ihandle */ - device_property_entry *entry = me->properties; - while (entry->value != property) { - entry = entry->next; - ASSERT(entry != NULL); - } - ASSERT(entry->init_array != NULL); - printf_filtered(" *%s\n", (char*)entry->init_array); - } - } - break; - case integer_property: - { - unsigned_word w = device_find_integer_property(me, property->name); - printf_filtered(" 0x%lx\n", (unsigned long)w); - } - break; - case string_property: - { - const char *s = device_find_string_property(me, property->name); - printf_filtered(" \"%s\n", s); - } - break; - } - } - } - /* interrupts */ - for (interrupt_edge = me->interrupt_destinations; - interrupt_edge != NULL; - interrupt_edge = interrupt_edge->next) { - char src[32]; - char dst[32]; - device_interrupt_encode(me, interrupt_edge->my_port, src, sizeof(src)); - device_interrupt_encode(interrupt_edge->dest, - interrupt_edge->dest_port, dst, sizeof(dst)); - printf_filtered("%s > %s %s %s\n", - me->path, - src, dst, - interrupt_edge->dest->path); - } + device_instance *instance = cap_internal(tree_member->ihandles, ihandle); + return instance; } INLINE_DEVICE\ -(device *) -device_tree_find_device(device *root, - const char *path) -{ - device *node; - name_specifier spec; - TRACE(trace_device_tree, - ("device_tree_find_device_tree(root=0x%lx, path=%s)\n", - (long)root, path)); - /* parse the path */ - split_device_specifier(path, &spec); - if (spec.value != NULL) - return NULL; /* something wierd */ - - /* now find it */ - node = split_find_device(root, &spec); - if (spec.name != NULL) - return NULL; /* not a leaf */ +(unsigned_cell) +device_instance_to_external(device_instance *instance) +{ + unsigned_cell ihandle = cap_external(instance->owner->ihandles, instance); + return ihandle; +} - return node; + +/* Map onto the event functions */ + +INLINE_DEVICE\ +(event_entry_tag) +device_event_queue_schedule(device *me, + signed64 delta_time, + device_event_handler *handler, + void *data) +{ + return event_queue_schedule(psim_event_queue(me->system), + delta_time, + handler, + data); } INLINE_DEVICE\ (void) -device_usage(int verbose) +device_event_queue_deschedule(device *me, + event_entry_tag event_to_remove) { - if (verbose == 1) { - const device_descriptor *const *table; - int pos; - printf_filtered("\n"); - printf_filtered("A device/property specifier has the form:\n"); - printf_filtered("\n"); - printf_filtered(" /path/to/a/device [ property-value ]\n"); - printf_filtered("\n"); - printf_filtered("and a possible device is\n"); - printf_filtered("\n"); - pos = 0; - for (table = device_table; *table != NULL; table++) { - const device_descriptor *descr; - for (descr = *table; descr->name != NULL; descr++) { - pos += strlen(descr->name) + 2; - if (pos > 75) { - pos = strlen(descr->name) + 2; - printf_filtered("\n"); - } - printf_filtered(" %s", descr->name); - } - printf_filtered("\n"); - } - } - if (verbose > 1) { - const device_descriptor *const *table; - printf_filtered("\n"); - printf_filtered("A device/property specifier () has the format:\n"); - printf_filtered("\n"); - printf_filtered(" ::= [ ] ;\n"); - printf_filtered(" ::= { } { \"/\" } ;\n"); - printf_filtered(" ::= ( | \"/\" | \"../\" | \"./\" ) ;\n"); - printf_filtered(" ::= [ \"@\" ] [ \":\" ] ;\n"); - printf_filtered(" ::= { \",\" } ;\n"); - printf_filtered("\n"); - printf_filtered("Where:\n"); - printf_filtered("\n"); - printf_filtered(" is the name of a device (list below)\n"); - printf_filtered(" is the unit-address relative to the parent bus\n"); - printf_filtered(" additional arguments used when creating the device\n"); - printf_filtered(" ::= ( # integer property\n"); - printf_filtered(" | \"[\" { } # array property (byte)\n"); - printf_filtered(" | \"{\" { } # array property (cell)\n"); - printf_filtered(" | [ \"true\" | \"false\" ] # boolean property\n"); - printf_filtered(" | \"*\" # ihandle property\n"); - printf_filtered(" | \"!\" # copy property\n"); - printf_filtered(" | \">\" [ ] # attach interrupt\n"); - printf_filtered(" | \"<\" # attach child interrupt\n"); - printf_filtered(" | \"\\\"\" # string property\n"); - printf_filtered(" | # string property\n"); - printf_filtered(" ) ;\n"); - printf_filtered("\n"); - printf_filtered("And the following are valid device names:\n"); - printf_filtered("\n"); - for (table = device_table; *table != NULL; table++) { - const device_descriptor *descr; - for (descr = *table; descr->name != NULL; descr++) { - printf_filtered(" %s:\n", descr->name); - /* interrupt ports */ - if (descr->callbacks->interrupt.ports != NULL) { - const device_interrupt_port_descriptor *ports = - descr->callbacks->interrupt.ports; - printf_filtered(" interrupt ports:"); - while (ports->name != NULL) { - printf_filtered(" %s", ports->name); - ports++; - } - printf_filtered("\n"); - } - /* general info */ - if (descr->callbacks->usage != NULL) - descr->callbacks->usage(verbose); - } - } - } + event_queue_deschedule(psim_event_queue(me->system), + event_to_remove); } - - -/* External representation */ - INLINE_DEVICE\ -(device *) -external_to_device(device *tree_member, - unsigned32 phandle) +(signed64) +device_event_queue_time(device *me) { - device *root = device_tree_find_device(tree_member, "/"); - device *me = cap_internal(root->phandles, phandle); - return me; + return event_queue_time(psim_event_queue(me->system)); } + +/* Initialization: */ + + INLINE_DEVICE\ -(unsigned32) -device_to_external(device *me) +(void) +device_clean(device *me, + void *data) { - device *root = device_tree_find_device(me, "/"); - unsigned32 phandle = cap_external(root->phandles, me); - return phandle; + psim *system; + system = (psim*)data; + TRACE(trace_device_init, ("device_clean - initializing %s", me->path)); + clean_device_interrupt_edges(&me->interrupt_destinations); + clean_device_instances(me); + clean_device_properties(me); } +/* Device initialization: */ + INLINE_DEVICE\ -(device_instance *) -external_to_device_instance(device *tree_member, - unsigned32 ihandle) +(void) +device_init_address(device *me, + void *data) { - device *root = device_tree_find_device(tree_member, "/"); - device_instance *instance = cap_internal(root->ihandles, ihandle); - return instance; + psim *system = (psim*)data; + int nr_address_cells; + int nr_size_cells; + TRACE(trace_device_init, ("device_init_address - initializing %s", me->path)); + + /* ensure the cap database is valid */ + if (me->parent == NULL) { + cap_init(me->ihandles); + cap_init(me->phandles); + } + + /* some basics */ + me->system = system; /* misc things not known until now */ + me->trace = (device_find_property(me, "trace") + ? device_find_integer_property(me, "trace") + : 0); + + /* Ensure that the first address found in the reg property matches + anything that was specified as part of the devices name */ + if (device_find_property(me, "reg") != NULL) { + reg_property_spec unit; + device_find_reg_array_property(me, "reg", 0, &unit); + if (memcmp(device_unit_address(me), &unit.address, sizeof(unit.address)) + != 0) + device_error(me, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path"); + } + + /* ensure that the devices #address/size-cells is consistent */ + nr_address_cells = device_nr_address_cells(me); + if (device_find_property(me, "#address-cells") != NULL + && (nr_address_cells + != device_find_integer_property(me, "#address-cells"))) + device_error(me, "#address-cells property used before defined"); + nr_size_cells = device_nr_size_cells(me); + if (device_find_property(me, "#size-cells") != NULL + && (nr_size_cells + != device_find_integer_property(me, "#size-cells"))) + device_error(me, "#size-cells property used before defined"); + + /* now init it */ + if (me->callback->init.address != NULL) + me->callback->init.address(me); } INLINE_DEVICE\ -(unsigned32) -device_instance_to_external(device_instance *instance) +(void) +device_init_data(device *me, + void *data) { - device *root = device_tree_find_device(instance->owner, "/"); - unsigned32 ihandle = cap_external(root->ihandles, instance); - return ihandle; + TRACE(trace_device_init, ("device_init_data - initializing %s", me->path)); + if (me->callback->init.data != NULL) + me->callback->init.data(me); } #endif /* _DEVICE_C_ */ diff --git a/sim/ppc/device.h b/sim/ppc/device.h index 4fa5a9d2057..cb2e8c8521e 100644 --- a/sim/ppc/device.h +++ b/sim/ppc/device.h @@ -42,40 +42,47 @@ */ -/* Constructing the device tree: +/* Device creation: */ - The initial device tree populated with devices and basic properties - is created using the function <>. This - function parses a PSIM device specification and uses it to populate - the tree accordingly. +INLINE_DEVICE\ +(device *) device_create +(device *parent, + const char *base, + const char *name, + const char *unit_address, + const char *args); - This function accepts a printf style formatted string as the - argument that describes the entry. Any properties or interrupt - connections added to a device tree using this function are marked - as having a permenant disposition. When the tree is (re) - initialized they will be restored to their initial value. +INLINE_DEVICE\ +(void) device_usage +(int verbose); - */ -EXTERN_DEVICE\ -(device *) device_tree_add_parsed -(device *current, - const char *fmt, - ...) __attribute__ ((format (printf, 2, 3))); +/* Device initialization: */ +INLINE_DEVICE\ +(void) device_clean +(device *root, + void *data); -/* Initializing the created tree: +INLINE_DEVICE\ +(void) device_init_static_properties +(device *me, + void *data); - Once a device tree has been created the <> - function is used to initialize it. The exact sequence of events - that occure during initialization are described separatly. +INLINE_DEVICE\ +(void) device_init_address +(device *me, + void *data); - */ +INLINE_DEVICE\ +(void) device_init_runtime_properties +(device *me, + void *data); INLINE_DEVICE\ -(void) device_tree_init -(device *root, - psim *system); +(void) device_init_data +(device *me, + void *data); /* Relationships: @@ -90,6 +97,10 @@ INLINE_DEVICE\ (device *) device_parent (device *me); +INLINE_DEVICE\ +(device *) device_root +(device *me); + INLINE_DEVICE\ (device *) device_sibling (device *me); @@ -102,6 +113,10 @@ INLINE_DEVICE\ (const char *) device_name (device *me); +INLINE_DEVICE\ +(const char *) device_base +(device *me); + INLINE_DEVICE\ (const char *) device_path (device *me); @@ -116,13 +131,63 @@ INLINE_DEVICE\ typedef struct _device_unit { int nr_cells; - unsigned32 cells[4]; /* unused cells are zero */ + unsigned_cell cells[4]; /* unused cells are zero */ } device_unit; INLINE_DEVICE\ (const device_unit *) device_unit_address (device *me); +INLINE_DEVICE\ +(int) device_decode_unit +(device *bus, + const char *unit, + device_unit *address); + +INLINE_DEVICE\ +(int) device_encode_unit +(device *bus, + const device_unit *unit_address, + char *buf, + int sizeof_buf); + + +/* Convert an Open Firmware size into a form suitable for attach + address calls. + + Return a zero result if the address should be ignored when looking + for attach addresses */ + +INLINE_DEVICE\ +(int) device_address_to_attach_address +(device *me, + const device_unit *address, + int *attach_space, + unsigned_word *attach_address, + device *client); + + +/* Convert an Open Firmware size into a form suitable for attach + address calls + + Return a zero result if the address should be ignored */ + +INLINE_DEVICE\ +(int) device_size_to_attach_size +(device *me, + const device_unit *size, + unsigned *nr_bytes, + device *client); + + +INLINE_DEVICE\ +(unsigned) device_nr_address_cells +(device *me); + +INLINE_DEVICE\ +(unsigned) device_nr_size_cells +(device *me); + /* Properties: @@ -132,15 +197,18 @@ INLINE_DEVICE\ */ -/* The following are valid property types. The property `array' is a +/* The following are valid property types. The property `array' is for generic untyped data. */ typedef enum { array_property, boolean_property, - ihandle_property, + ihandle_property, /*runtime*/ integer_property, + range_array_property, + reg_array_property, string_property, + string_array_property, } device_property_type; typedef struct _device_property device_property; @@ -176,9 +244,25 @@ INLINE_DEVICE\ FIND returns the specified properties value, aborting the simulation if the property is missing. Code locating a property should first check its type (using device_find_property above) and - then obtain its value using the below. */ + then obtain its value using the below. + + void device_add__property(device *, const char *, ) + void device_add_*_array_property(device *, const char *, const *, int) + void device_set_*_property(device *, const char *, ) + void device_set_*_array_property(device *, const char *, const *, int) + device_find_*_property(device *, const char *) + int device_find_*_array_property(device *, const char *, int, *) + + */ +INLINE_DEVICE\ +(void) device_add_array_property +(device *me, + const char *property, + const void *array, + int sizeof_array); + INLINE_DEVICE\ (void) device_set_array_property (device *me, @@ -192,13 +276,12 @@ INLINE_DEVICE\ const char *property); -#if 0 + INLINE_DEVICE\ -(void) device_set_boolean_property +(void) device_add_boolean_property (device *me, const char *property, int bool); -#endif INLINE_DEVICE\ (int) device_find_boolean_property @@ -206,13 +289,30 @@ INLINE_DEVICE\ const char *property); -#if 0 + +typedef struct _ihandle_runtime_property_spec { + device *phandle; + const char *full_path; + const char *args; +} ihandle_runtime_property_spec; + +INLINE_DEVICE\ +(void) device_add_ihandle_runtime_property +(device *me, + const char *property, + const ihandle_runtime_property_spec *ihandle); + +INLINE_DEVICE\ +(void) device_find_ihandle_runtime_property +(device *me, + const char *property, + ihandle_runtime_property_spec *ihandle); + INLINE_DEVICE\ (void) device_set_ihandle_property (device *me, const char *property, device_instance *ihandle); -#endif INLINE_DEVICE\ (device_instance *) device_find_ihandle_property @@ -220,27 +320,75 @@ INLINE_DEVICE\ const char *property); -#if 0 + INLINE_DEVICE\ -(void) device_set_integer_property +(void) device_add_integer_property (device *me, const char *property, - signed_word integer); -#endif + signed_cell integer); INLINE_DEVICE\ -(signed_word) device_find_integer_property +(signed_cell) device_find_integer_property (device *me, const char *property); +INLINE_DEVICE\ +(int) device_find_integer_array_property +(device *me, + const char *property, + unsigned index, + signed_word *integer); + + + +typedef struct _range_property_spec { + device_unit child_address; + device_unit parent_address; + device_unit size; +} range_property_spec; -#if 0 INLINE_DEVICE\ -(void) device_set_string_property +(void) device_add_range_array_property +(device *me, + const char *property, + const range_property_spec *ranges, + unsigned nr_ranges); + +INLINE_DEVICE\ +(int) device_find_range_array_property +(device *me, + const char *property, + unsigned index, + range_property_spec *range); + + + +typedef struct _reg_property_spec { + device_unit address; + device_unit size; +} reg_property_spec; + +INLINE_DEVICE\ +(void) device_add_reg_array_property +(device *me, + const char *property, + const reg_property_spec *reg, + unsigned nr_regs); + +INLINE_DEVICE\ +(int) device_find_reg_array_property +(device *me, + const char *property, + unsigned index, + reg_property_spec *reg); + + + +INLINE_DEVICE\ +(void) device_add_string_property (device *me, const char *property, const char *string); -#endif INLINE_DEVICE\ (const char *) device_find_string_property @@ -248,6 +396,33 @@ INLINE_DEVICE\ const char *property); + +typedef const char *string_property_spec; + +INLINE_DEVICE\ +(void) device_add_string_array_property +(device *me, + const char *property, + const string_property_spec *strings, + unsigned nr_strings); + +INLINE_DEVICE\ +(int) device_find_string_array_property +(device *me, + const char *property, + unsigned index, + string_property_spec *string); + + + +INLINE_DEVICE\ +(void) device_add_duplicate_property +(device *me, + const char *property, + const device_property *original); + + + /* Instances: As with IEEE1275, a device can be opened, creating an instance. @@ -277,7 +452,8 @@ INLINE_DEVICE\ INLINE_DEVICE\ (device_instance *) device_create_instance (device *me, - const char *device_specifier); + const char *full_path, + const char *args); INLINE_DEVICE\ (void) device_instance_delete @@ -302,17 +478,13 @@ INLINE_DEVICE\ unsigned_word pos_lo); INLINE_DEVICE\ -(unsigned_word) device_instance_claim +(int) device_instance_call_method (device_instance *instance, - unsigned_word address, - unsigned_word length, - unsigned_word alignment); - -INLINE_DEVICE\ -(void) device_instance_release -(device_instance *instance, - unsigned_word address, - unsigned_word length); + const char *method, + int n_stack_args, + unsigned_cell stack_args[/*n_stack_args*/], + int n_stack_returns, + unsigned_cell stack_returns[/*n_stack_returns*/]); INLINE_DEVICE\ (device *) device_instance_device @@ -378,6 +550,20 @@ INLINE_DEVICE\ device *dest, int dest_port); +typedef void (device_interrupt_traverse_function) + (device *me, + int my_port, + device *dest, + int my_dest, + void *data); + +INLINE_DEVICE\ +(void) device_interrupt_traverse +(device *me, + device_interrupt_traverse_function *handler, + void *data); + + /* DESTINATION is attached (detached) to LINE of the device ME @@ -393,14 +579,16 @@ INLINE_DEVICE\ INLINE_DEVICE\ (int) device_interrupt_decode (device *me, - const char *symbolic_name); + const char *symbolic_name, + port_direction direction); INLINE_DEVICE\ (int) device_interrupt_encode (device *me, int port_number, char *buf, - int sizeof_buf); + int sizeof_buf, + port_direction direction); /* Hardware operations: @@ -480,24 +668,22 @@ typedef enum _attach_type { INLINE_DEVICE\ (void) device_attach_address (device *me, - const char *name, attach_type attach, int space, unsigned_word addr, unsigned nr_bytes, access_type access, - device *who); /*callback/default*/ + device *client); /*callback/default*/ INLINE_DEVICE\ (void) device_detach_address (device *me, - const char *name, attach_type attach, int space, unsigned_word addr, unsigned nr_bytes, access_type access, - device *who); /*callback/default*/ + device *client); /*callback/default*/ /* Utilities: @@ -513,11 +699,20 @@ INLINE_DEVICE\ */ +typedef enum { + device_ioctl_break, /* unsigned_word requested_break */ + device_ioctl_set_trace, /* void */ + device_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */ + device_ioctl_change_media, /* const char *new_image (possibly NULL) */ + nr_device_ioctl_requests, +} device_ioctl_request; + EXTERN_DEVICE\ (int) device_ioctl (device *me, cpu *processor, unsigned_word cia, + device_ioctl_request request, ...); @@ -539,60 +734,10 @@ EXTERN_DEVICE\ const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -/* Tree traversal:: - - The entire device tree can be traversed using the - <> function. The traversal can be in - either pre- or postfix order. - - */ - -typedef void (device_tree_traverse_function) - (device *device, - void *data); - -INLINE_DEVICE\ -(void) device_tree_traverse -(device *root, - device_tree_traverse_function *prefix, - device_tree_traverse_function *postfix, - void *data); - -/* Device description:: - - */ - -INLINE_DEVICE\ -(void) device_tree_print_device -(device *device, - void *ignore_data_argument); - - -/* Tree lookup:: - - The function <> will attempt to locate - the specified device within the tree. If the device is not found a - NULL device is returned. - - */ - INLINE_DEVICE\ -(device *) device_tree_find_device -(device *root, - const char *path); - - -/* Device list or usage:: - - The <> function outputs a list of all the devices - compiled into PSIM. The verbose option will result in additional - information being printed (for instance, the interrupt ports). - - */ +(int) device_trace +(device *me); -INLINE_DEVICE\ -(void) device_usage -(int verbose); /* External representation: @@ -612,19 +757,43 @@ INLINE_DEVICE\ INLINE_DEVICE\ (device *) external_to_device (device *tree_member, - unsigned32 phandle); + unsigned_cell phandle); INLINE_DEVICE\ -(unsigned32) device_to_external +(unsigned_cell) device_to_external (device *me); INLINE_DEVICE\ (device_instance *) external_to_device_instance (device *tree_member, - unsigned32 ihandle); + unsigned_cell ihandle); INLINE_DEVICE\ -(unsigned32) device_instance_to_external +(unsigned_cell) device_instance_to_external (device_instance *me); + +/* Event queue: + + The device inherets certain event queue operations from the main + simulation. */ + +typedef void device_event_handler(void *data); + +INLINE_DEVICE\ +(event_entry_tag) device_event_queue_schedule +(device *me, + signed64 delta_time, + device_event_handler *handler, + void *data); + +INLINE_EVENTS\ +(void) device_event_queue_deschedule +(device *me, + event_entry_tag event_to_remove); + +INLINE_EVENTS\ +(signed64) device_event_queue_time +(device *me); + #endif /* _DEVICE_H_ */ diff --git a/sim/ppc/emul_chirp.c b/sim/ppc/emul_chirp.c index 9eb3a4e15aa..e569dd7962c 100644 --- a/sim/ppc/emul_chirp.c +++ b/sim/ppc/emul_chirp.c @@ -1,6 +1,6 @@ /* This file is part of the program psim. - Copyright (C) 1994-1995, Andrew Cagney + Copyright (C) 1994-1996, Andrew Cagney This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -11,11 +11,11 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + */ @@ -28,8 +28,6 @@ #include "emul_generic.h" #include "emul_chirp.h" -#include "cap.h" - #ifdef HAVE_STRING_H #include #else @@ -45,12 +43,35 @@ #endif +/* EMULATION + + + OpenFirmware - IEEE Standard for Boot (Initialization + Configuration) Firmware. + + + DESCRIPTION + + + BUGS + + + This code assumes that the memory node has #address-cells and + #size-cells set to one. For future implementations, this may not + be the case. + + */ + + + + /* Descriptor of the open boot services being emulated */ typedef int (chirp_handler) (os_emul_data *data, cpu *processor, unsigned_word cia); + typedef struct _chirp_services { const char *name; chirp_handler *handler; @@ -61,53 +82,127 @@ typedef struct _chirp_services { request or waiting on a client callback */ typedef enum { serving, + emulating, faulting, - catching, } chirp_emul_state; struct _os_emul_data { chirp_emul_state state; unsigned_word return_address; unsigned_word arguments; + unsigned_word n_args; + unsigned_word n_returns; chirp_services *service; - unsigned_word serving_instruction_ea; - unsigned_word catching_instruction_ea; - cap *phandles; device *root; chirp_services *services; + /* configuration */ + unsigned_word memory_size; + unsigned_word real_base; + unsigned_word real_size; + unsigned_word virt_base; + unsigned_word virt_size; + int real_mode; + int little_endian; + int floating_point_available; + int interrupt_prefix; + unsigned_word load_base; + /* hash table */ + unsigned_word nr_page_table_entry_groups; + unsigned_word htab_offset; + unsigned_word htab_ra; + unsigned_word htab_va; + unsigned_word sizeof_htab; + /* virtual address of htab */ + unsigned_word stack_offset; + unsigned_word stack_ra; + unsigned_word stack_va; + unsigned_word sizeof_stack; + /* addresses of emulation instructions virtual/real */ + unsigned_word code_offset; + unsigned_word code_va; + unsigned_word code_ra; + unsigned_word sizeof_code; + unsigned_word code_client_va; + unsigned_word code_client_ra; + unsigned_word code_callback_va; + unsigned_word code_callback_ra; + unsigned_word code_loop_va; + unsigned_word code_loop_ra; }; -/* Read in the argument list and make the most basic check that number - of argumnets are consistent with what was expected */ +/* returns the name of the corresponding Ihandle */ +static const char * +ihandle_name(device_instance *ihandle) +{ + if (ihandle == NULL) + return ""; + else + return device_name(device_instance_device(ihandle)); +} + + + +/* Read/write the argument list making certain that all values are + converted to/from host byte order. + + In the below only n_args+n_returns is read/written */ static int -chirp_read_args(void *args, - int sizeof_args, - int n_args, - int n_returns, - os_emul_data *data, - cpu *processor, - unsigned_word cia) +chirp_read_t2h_args(void *args, + int sizeof_args, + int n_args, + int n_returns, + os_emul_data *data, + cpu *processor, + unsigned_word cia) { - struct base_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; - } *base; - emul_read_buffer(args, data->arguments, - sizeof_args, - processor, cia); - base = (struct base_args*)args; - if (T2H_4(base->n_args) != n_args || T2H_4(base->n_returns) != n_returns) { - TRACE(trace_os_emul, ("invalid nr of args - n_args=%ld, n_returns=%ld\n", - (long)T2H_4(base->n_args), - (long)T2H_4(base->n_returns))); + unsigned_cell *words; + int i; + /* check against the number of arguments specified by the client + program */ + if ((n_args >= 0 && data->n_args != n_args) + || (n_returns >= 0 && data->n_returns != n_returns)) { + TRACE(trace_os_emul, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n", + data->service->name, + (long)data->n_args, + (long)data->n_returns)); return -1; } + /* check that there is enough space */ + if (sizeof(unsigned_cell) * (data->n_args + data->n_returns) > sizeof_args) + return -1; + /* bring in the data */ + memset(args, 0, sizeof_args); + emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned_cell), + sizeof(unsigned_cell) * (data->n_args + data->n_returns), + processor, cia); + /* convert all words to host format */ + words = args; + for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++) + words[i] = T2H_cell(words[i]); return 0; } +static void +chirp_write_h2t_args(void *args, + int sizeof_args, + os_emul_data *data, + cpu *processor, + unsigned_word cia) +{ + int i; + unsigned_cell *words; + /* convert to target everything */ + words = args; + for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++) + words[i] = H2T_cell(words[i]); + /* bring in the data */ + emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned_cell), + sizeof(unsigned_cell) * (data->n_args + data->n_returns), + processor, cia); +} + /* OpenBoot emulation functions */ @@ -119,23 +214,21 @@ chirp_emul_test(os_emul_data *data, unsigned_word cia) { struct test_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 name; /*string*/ + unsigned_cell name; /*string*/ /*out*/ - unsigned32 missing; + unsigned_cell missing; } args; char name[32]; - chirp_services *service = data->services; + chirp_services *service = NULL; /* read in the arguments */ - if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; - emul_read_string(name, T2H_4(args.name), sizeof(name), + emul_read_string(name, args.name, sizeof(name), processor, cia); TRACE(trace_os_emul, ("test - in - name=`%s'\n", name)); /* see if we know about the service */ + service = data->services; while (service->name != NULL && strcmp(service->name, name) != 0) { service++; } @@ -146,9 +239,10 @@ chirp_emul_test(os_emul_data *data, /* write the arguments back out */ TRACE(trace_os_emul, ("test - out - missing=%ld\n", (long)args.missing)); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -161,45 +255,46 @@ chirp_emul_peer(os_emul_data *data, unsigned_word cia) { struct peer_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 phandle; + unsigned_cell phandle; /*out*/ - unsigned32 sibling_phandle; + unsigned_cell sibling_phandle; } args; - device *dev; - device *sibling_dev = NULL; + device *phandle; + device *sibling_phandle = NULL; /* read in the arguments */ - if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; - dev = cap_internal(data->phandles, args.phandle); + phandle = external_to_device(data->root, args.phandle); TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n", - (unsigned long)T2H_4(args.phandle), - (unsigned long)dev, - (dev == NULL ? "" : device_name(dev)))); + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)))); /* find the peer */ - if (dev == NULL && args.phandle != 0) - return -1; - if (args.phandle == 0) - sibling_dev = data->root; - else - sibling_dev = device_sibling(dev); - if (sibling_dev == NULL) - args.sibling_phandle = 0; - else - args.sibling_phandle = cap_external(data->phandles, sibling_dev); + if (args.phandle == 0) { + sibling_phandle = data->root; + args.sibling_phandle = device_to_external(sibling_phandle); + } + else if (phandle == NULL) { + sibling_phandle = NULL; + args.sibling_phandle = -1; + } + else { + sibling_phandle = device_sibling(phandle); + if (sibling_phandle == NULL) + args.sibling_phandle = 0; + else + args.sibling_phandle = device_to_external(sibling_phandle); + } /* write the arguments back out */ TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n", - (unsigned long)T2H_4(args.sibling_phandle), - (unsigned long)sibling_dev, - (sibling_dev == NULL - ? "" - : device_name(sibling_dev)))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (unsigned long)args.sibling_phandle, + (unsigned long)sibling_phandle, + (sibling_phandle == NULL ? "" : device_name(sibling_phandle)))); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -209,40 +304,43 @@ chirp_emul_child(os_emul_data *data, unsigned_word cia) { struct child_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 phandle; + unsigned_cell phandle; /*out*/ - unsigned32 child_phandle; + unsigned_cell child_phandle; } args; - device *dev; - device *child_dev; + device *phandle; + device *child_phandle; /* read the arguments in */ - if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; - dev = cap_internal(data->phandles, args.phandle); + phandle = external_to_device(data->root, args.phandle); TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n", - (unsigned long)T2H_4(args.phandle), - (unsigned long)dev, - (dev == NULL ? "" : device_name(dev)))); + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)))); /* find a child */ - if (dev == (device*)0) - return -1; - child_dev = device_child(dev); - if (child_dev == NULL) - args.child_phandle = 0; - else - args.child_phandle = cap_external(data->phandles, child_dev); + if (args.phandle == 0 + || phandle == NULL) { + child_phandle = NULL; + args.child_phandle = -1; + } + else { + child_phandle = device_child(phandle); + if (child_phandle == NULL) + args.child_phandle = 0; + else + args.child_phandle = device_to_external(child_phandle); + } /* write the result out */ TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n", - (unsigned long)T2H_4(args.child_phandle), - (unsigned long)child_dev, - (child_dev == NULL ? "" : device_name(child_dev)))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (unsigned long)args.child_phandle, + (unsigned long)child_phandle, + (child_phandle == NULL ? "" : device_name(child_phandle)))); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -252,40 +350,43 @@ chirp_emul_parent(os_emul_data *data, unsigned_word cia) { struct parent_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 phandle; + unsigned_cell phandle; /*out*/ - unsigned32 parent_phandle; + unsigned_cell parent_phandle; } args; - device *dev; - device *parent_dev; + device *phandle; + device *parent_phandle; /* read the args in */ - if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; - dev = cap_internal(data->phandles, args.phandle); + phandle = external_to_device(data->root, args.phandle); TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n", - (unsigned long)T2H_4(args.phandle), - (unsigned long)dev, - (dev == NULL ? "" : device_name(dev)))); + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)))); /* find a parent */ - if (dev == (device*)0) - return -1; - parent_dev = device_parent(dev); - if (parent_dev == NULL) - args.parent_phandle = 0; - else - args.parent_phandle = cap_external(data->phandles, parent_dev); + if (args.phandle == 0 + || phandle == NULL) { + parent_phandle = NULL; + args.parent_phandle = -1; + } + else { + parent_phandle = device_parent(phandle); + if (parent_phandle == NULL) + args.parent_phandle = 0; + else + args.parent_phandle = device_to_external(parent_phandle); + } /* return the result */ TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n", - (unsigned long)T2H_4(args.parent_phandle), - (unsigned long)parent_dev, - (parent_dev == NULL ? "" : device_name(parent_dev)))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (unsigned long)args.parent_phandle, + (unsigned long)parent_phandle, + (parent_phandle == NULL ? "" : device_name(parent_phandle)))); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -294,7 +395,40 @@ chirp_emul_instance_to_package(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: instance-to-package unimplemented\n"); + struct instance_to_package_args { + /*in*/ + unsigned_cell ihandle; + /*out*/ + unsigned_cell phandle; + } args; + device_instance *ihandle; + device *phandle = NULL; + /* read the args in */ + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) + return -1; + ihandle = external_to_device_instance(data->root, args.ihandle); + TRACE(trace_os_emul, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n", + (unsigned long)args.ihandle, + (unsigned long)ihandle, + ihandle_name(ihandle))); + /* find the corresponding phandle */ + if (ihandle == NULL) { + phandle = NULL; + args.phandle = -1; + } + else { + phandle = device_instance_device(ihandle); + args.phandle = device_to_external(phandle); + } + /* return the result */ + TRACE(trace_os_emul, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n", + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)))); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -304,47 +438,48 @@ chirp_emul_getproplen(os_emul_data *data, unsigned_word cia) { struct getproplen_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 phandle; - unsigned32 name; + unsigned_cell phandle; + unsigned_cell name; /*out*/ - unsigned32 proplen; + unsigned_cell proplen; } args; char name[32]; - device *dev; - const device_property *prop; + device *phandle; /* read the args in */ - if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia)) - return -1; - dev = cap_internal(data->phandles, args.phandle); - /* find our prop and get its length */ - if (dev == (device*)0) + if (chirp_read_t2h_args(&args, sizeof(args), 2, 1, data, processor, cia)) return -1; + phandle = external_to_device(data->root, args.phandle); emul_read_string(name, - T2H_4(args.name), + args.name, sizeof(name), processor, cia); TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n", - (unsigned long)T2H_4(args.phandle), - (unsigned long)dev, - (dev == NULL ? "" : device_name(dev)), + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)), name)); - prop = device_find_property(dev, name); - if (prop == (device_property*)0) { + /* find our prop and get its length */ + if (args.phandle == 0 + || phandle == NULL) { args.proplen = -1; } else { - args.proplen = H2T_4(prop->sizeof_array); + const device_property *prop = device_find_property(phandle, name); + if (prop == (device_property*)0) { + args.proplen = -1; + } + else { + args.proplen = prop->sizeof_array; + } } /* return the result */ TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n", - (unsigned long)T2H_4(args.proplen))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (unsigned long)args.proplen)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -354,65 +489,77 @@ chirp_emul_getprop(os_emul_data *data, unsigned_word cia) { struct getprop_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 phandle; - unsigned32 name; - unsigned32 buf; - unsigned32 buflen; + unsigned_cell phandle; + unsigned_cell name; + unsigned_cell buf; + unsigned_cell buflen; /*out*/ - unsigned32 size; + unsigned_cell size; } args; char name[32]; - device *dev; - const device_property *prop; - /* read in the args */ - if (chirp_read_args(&args, sizeof(args), 4, 1, data, processor, cia)) + device *phandle; + /* read in the args, the return is optional */ + if (chirp_read_t2h_args(&args, sizeof(args), 4, -1, data, processor, cia)) return -1; - dev = cap_internal(data->phandles, args.phandle); + phandle = external_to_device(data->root, args.phandle); emul_read_string(name, - T2H_4(args.name), + args.name, sizeof(name), processor, cia); TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n", - (unsigned long)T2H_4(args.phandle), - (unsigned long)dev, - (dev == NULL ? "" : device_name(dev)), + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)), name, - (unsigned long)T2H_4(args.buf), - (unsigned long)T2H_4(args.buflen))); + (unsigned long)args.buf, + (unsigned long)args.buflen)); /* get the property */ - if (dev == (device*)0) - return -1; - prop = device_find_property(dev, name); - if (prop == (device_property*)0) { + if (args.phandle == 0 + || phandle == NULL) { args.size = -1; } else { - int size = T2H_4(args.buflen); - if (size > prop->sizeof_array) - size = prop->sizeof_array; - emul_write_buffer(prop->array, T2H_4(args.buf), - size, - processor, cia); - args.size = H2T_4(size); - } - switch (prop->type) { - case string_property: - TRACE(trace_os_emul, ("getprop - value=`%s' (string)\n", - (char*)prop->array)); - break; - default: - break; + const device_property *prop = device_find_property(phandle, name); + if (prop == NULL) { + args.size = -1; + } + else { + int size = args.buflen; + if (size > prop->sizeof_array) + size = prop->sizeof_array; + emul_write_buffer(prop->array, args.buf, + size, + processor, cia); + args.size = size; + switch (prop->type) { + case string_property: + TRACE(trace_os_emul, ("getprop - string `%s'\n", + device_find_string_property(phandle, name))); + break; + case ihandle_property: + TRACE(trace_os_emul, ("getprop - ihandle=0x%lx(0x%lx`%s')\n", + BE2H_cell(*(unsigned_cell*)prop->array), + (unsigned long)device_find_ihandle_property(phandle, name), + ihandle_name(device_find_ihandle_property(phandle, name)))); + break; + default: + break; + } + } } /* write back the result */ - TRACE(trace_os_emul, ("getprop - out - size=%ld\n", - (unsigned long)T2H_4(args.size))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + if (data->n_returns == 0) + TRACE(trace_os_emul, ("getprop - out - size=%ld (not returned)\n", + (unsigned long)args.size)); + else { + TRACE(trace_os_emul, ("getprop - out - size=%ld\n", + (unsigned long)args.size)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); + } return 0; } @@ -421,25 +568,127 @@ chirp_emul_nextprop(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: nextprop not implemented\n"); + struct nextprop_args { + /*in*/ + unsigned_cell phandle; + unsigned_cell previous; + unsigned_cell buf; + /*out*/ + unsigned_cell flag; + } args; + char previous[32]; + device *phandle; + /* read in the args */ + if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) + return -1; + phandle = external_to_device(data->root, args.phandle); + emul_read_string(previous, + args.previous, + sizeof(previous), + processor, cia); + TRACE(trace_os_emul, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n", + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)), + previous, + (unsigned long)args.buf)); + /* find the next property */ + if (args.phandle == 0 + || phandle == NULL) { + args.flag = -1; + } + else { + const device_property *prev_prop = device_find_property(phandle, previous); + if (prev_prop == NULL) { + args.flag = -1; /* name invalid */ + } + else { + const device_property *next_prop; + next_prop = device_next_property(prev_prop); + if (next_prop == NULL) { + args.flag = 0; /* last property */ + } + else { + emul_write_buffer(next_prop->name, args.buf, strlen(next_prop->name), + processor, cia); + TRACE(trace_os_emul, ("nextprop - name=`%s'\n", next_prop->name)); + args.flag = 1; /* worked ok */ + } + } + } + /* write back the result */ + TRACE(trace_os_emul, ("nextprop - out - flag=%ld\n", + (unsigned long)args.flag)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } +#if 0 static int chirp_emul_setprop(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: setprop not implemented\n"); + error("chirp: setprop method not implemented\n"); return 0; } +#endif static int chirp_emul_canon(os_emul_data *data, - cpu *processor, - unsigned_word cia) + cpu *processor, + unsigned_word cia) { - error("chirp: canon not implemented\n"); + struct canon_args { + /*in*/ + unsigned_cell device_specifier; + unsigned_cell buf; + unsigned_cell buflen; + /*out*/ + unsigned_cell length; + } args; + char device_specifier[1024]; + device *phandle; + const char *path; + int length; + /* read in the args */ + if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) + return -1; + emul_read_string(device_specifier, + args.device_specifier, + sizeof(device_specifier), + processor, cia); + TRACE(trace_os_emul, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n", + device_specifier, + (unsigned long)args.buf, + (unsigned long)args.buflen)); + /* canon the name */ + phandle = tree_find_device(data->root, device_specifier); + if (phandle == NULL) { + length = -1; + path = ""; + args.length = -1; + } + else { + path = device_path(phandle); + length = strlen(path); + if (length >= args.buflen) + length = args.buflen - 1; + emul_write_buffer(path, args.buf, length, + processor, cia); + args.length = length; + } + /* write back the result */ + TRACE(trace_os_emul, ("canon - out - length=%ld buf=`%s'\n", + (unsigned long)args.length, + path)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -449,40 +698,37 @@ chirp_emul_finddevice(os_emul_data *data, unsigned_word cia) { struct finddevice_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 device_specifier; + unsigned_cell device_specifier; /*out*/ - unsigned32 phandle; + unsigned_cell phandle; } args; char device_specifier[1024]; - device *dev; + device *phandle; /* get the args */ - if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; emul_read_string(device_specifier, - T2H_4(args.device_specifier), + args.device_specifier, sizeof(device_specifier), processor, cia); TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n", device_specifier)); /* find the device */ - dev = device_tree_find_device(data->root, - device_specifier); - if (dev == (device*)0) + phandle = tree_find_device(data->root, device_specifier); + if (phandle == NULL) args.phandle = -1; else - args.phandle = cap_external(data->phandles, dev); + args.phandle = device_to_external(phandle); /* return its phandle */ TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n", - (unsigned long)T2H_4(args.phandle), - (unsigned long)dev, - (dev == NULL ? "" : device_name(dev)))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)))); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -491,25 +737,162 @@ chirp_emul_instance_to_path(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: instance_to_path not implemented\n"); + struct instance_to_path_args { + /*in*/ + unsigned_cell ihandle; + unsigned_cell buf; + unsigned_cell buflen; + /*out*/ + unsigned_cell length; + } args; + device_instance *ihandle; + const char *path; + int length; + /* get the args */ + if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) + return -1; + ihandle = external_to_device_instance(data->root, args.ihandle); + TRACE(trace_os_emul, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n", + (unsigned long)args.ihandle, + (unsigned long)ihandle, + ihandle_name(ihandle), + (unsigned long)args.buf, + (unsigned long)args.buflen)); + /* get the devices name */ + if (ihandle == NULL) { + args.length = -1; + path = "(null)"; + } + else { + path = device_instance_path(ihandle); + length = strlen(path); + if (length >= args.buflen) + length = args.buflen - 1; + emul_write_buffer(path, args.buf, length, + processor, cia); + args.length = length; + } + /* return its phandle */ + TRACE(trace_os_emul, ("instance-to-path - out - length=%ld buf=`%s')\n", + (unsigned long)args.length, + path)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } static int chirp_emul_package_to_path(os_emul_data *data, - cpu *processor, - unsigned_word cia) + cpu *processor, + unsigned_word cia) { - error("chirp: package_to_path not implemented\n"); + struct package_to_path_args { + /*in*/ + unsigned_cell phandle; + unsigned_cell buf; + unsigned_cell buflen; + /*out*/ + unsigned_cell length; + } args; + device *phandle; + const char *path; + /* get the args */ + if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) + return -1; + phandle = external_to_device(data->root, args.phandle); + TRACE(trace_os_emul, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n", + (unsigned long)args.phandle, + (unsigned long)phandle, + (phandle == NULL ? "" : device_name(phandle)), + (unsigned long)args.buf, + (unsigned long)args.buflen)); + /* get the devices name */ + if (phandle == NULL) { + args.length = -1; + path = "(null)"; + } + else { + int length; + path = device_path(phandle); + length = strlen(path); + if (length >= args.buflen) + length = args.buflen - 1; + emul_write_buffer(path, args.buf, length, + processor, cia); + args.length = length; + } + /* return its phandle */ + TRACE(trace_os_emul, ("package-to-path - out - length=%ld buf=`%s')\n", + (unsigned long)args.length, + path)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } static int chirp_emul_call_method(os_emul_data *data, - cpu *processor, - unsigned_word cia) + cpu *processor, + unsigned_word cia) { - error("chirp: call-method implemented\n"); + struct call_method_args { + /*in*/ + unsigned_cell method; + unsigned_cell ihandle; + /*in/out*/ + unsigned_cell stack[13]; /*6in + 6out + catch */ + } args; + char method[32]; + device_instance *ihandle; + /* some useful info about our mini stack */ + int n_stack_args; + int n_stack_returns; + int stack_catch_result; + int stack_returns; + /* read the args */ + if (chirp_read_t2h_args(&args, sizeof(args), -1, -1, data, processor, cia)) + return -1; + emul_read_string(method, + args.method, + sizeof(method), + processor, cia); + ihandle = external_to_device_instance(data->root, args.ihandle); + n_stack_args = data->n_args - 2; + n_stack_returns = data->n_returns - 1; + stack_catch_result = n_stack_args; + stack_returns = stack_catch_result + 1; + TRACE(trace_os_emul, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n", + (unsigned long)data->n_args, + (unsigned long)data->n_returns, + method, + (unsigned long)args.ihandle, + (unsigned long)ihandle, + ihandle_name(ihandle))); + /* see if we can emulate this method */ + if (ihandle == NULL) { + /* OpenFirmware doesn't define this error */ + error("chirp: invalid ihandle passed to call-method method"); + } + else { + args.stack[stack_catch_result] = + device_instance_call_method(ihandle, + method, + n_stack_args, + &args.stack[0], + n_stack_returns, + &args.stack[stack_returns]); + } + /* finished */ + TRACE(trace_os_emul, ("call-method - out - catch-result=%ld\n", + (unsigned long)args.stack[stack_catch_result])); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -522,33 +905,37 @@ chirp_emul_open(os_emul_data *data, unsigned_word cia) { struct open_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 device_specifier; + unsigned_cell device_specifier; /*out*/ - unsigned32 ihandle; + unsigned_cell ihandle; } args; - char name[1024]; + char device_specifier[1024]; + device_instance *ihandle; /* read the args */ - if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; - emul_read_string(name, - T2H_4(args.device_specifier), - sizeof(name), + emul_read_string(device_specifier, + args.device_specifier, + sizeof(device_specifier), processor, cia); TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n", - name)); + device_specifier)); /* open the device */ - printf_filtered("OpenBoot - open unimplemented for %s\n", name); - args.ihandle = -1; + ihandle = tree_instance(data->root, device_specifier); + if (ihandle == NULL) + args.ihandle = -1; + else + args.ihandle = device_instance_to_external(ihandle); /* return the ihandle result */ - TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n", - (unsigned long)T2H_4(args.ihandle))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + TRACE(trace_os_emul, ("open - out - ihandle=0x%lx(0x%lx`%s')\n", + (unsigned long)args.ihandle, + (unsigned long)ihandle, + ihandle_name(ihandle))); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -557,7 +944,34 @@ chirp_emul_close(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: close not implemented\n"); + struct close_args { + /*in*/ + unsigned_cell ihandle; + /*out*/ + } args; + device_instance *ihandle; + /* read the args */ + if (chirp_read_t2h_args(&args, sizeof(args), 1, 0, data, processor, cia)) + return -1; + ihandle = external_to_device_instance(data->root, args.ihandle); + TRACE(trace_os_emul, ("close - in - ihandle=0x%lx(0x%lx`%s')\n", + (unsigned long)args.ihandle, + (unsigned long)ihandle, + ihandle_name(ihandle))); + /* close the device */ + if (ihandle == NULL) { + /* OpenFirmware doesn't define this error */ + error("chirp: invalid ihandle passed to close method"); + } + else { + device_instance_delete(ihandle); + } + /* return the ihandle result */ + TRACE(trace_os_emul, ("close - out\n")); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -567,94 +981,135 @@ chirp_emul_read(os_emul_data *data, unsigned_word cia) { struct read_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 ihandle; - unsigned32 addr; - unsigned32 len; + unsigned_cell ihandle; + unsigned_cell addr; + unsigned_cell len; /*out*/ - unsigned32 actual; + unsigned_cell actual; } args; char buf[1024]; - int actual; + device_instance *ihandle; /* read the args */ - if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) return -1; - TRACE(trace_os_emul, ("read - in - ihandle=0x%lx addr=0x%lx len=%ld\n", + ihandle = external_to_device_instance(data->root, args.ihandle); + TRACE(trace_os_emul, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n", (unsigned long)args.ihandle, - (unsigned long)T2H_4(args.addr), - (unsigned long)T2H_4(args.len))); - /* do the read */ - actual = T2H_4(args.len); - if (actual >= sizeof(buf)) - actual = sizeof(buf) - 1; - actual = read(BE2H_4(args.ihandle), buf, actual); - if (actual >= 0) { - emul_write_buffer(buf, - T2H_4(args.addr), - actual, - processor, cia); - args.actual = H2T_4(actual); - buf[actual] = '\0'; + (unsigned long)ihandle, + ihandle_name(ihandle), + (unsigned long)args.addr, + (unsigned long)args.len)); + if (ihandle == NULL) { + /* OpenFirmware doesn't define this error */ + error("chirp: invalid ihandle passed to read method"); } else { - args.actual = 0; + /* do the reads */ + int actual = 0; + while (actual < args.len) { + int remaining = args.len - actual; + int to_read = (remaining <= sizeof(buf) ? remaining : sizeof(buf)); + int nr_read = device_instance_read(ihandle, buf, to_read); + if (nr_read < 0) { + actual = nr_read; /* the error */ + break; + } + else if (nr_read == 0) { + break; + } + emul_write_buffer(buf, + args.addr + actual, + nr_read, + processor, cia); + actual += nr_read; + } + if (actual >= 0) { + args.actual = actual; + if (actual < sizeof(buf)) + buf[actual] = '\0'; + else + buf[sizeof(buf) - 1] = '\0'; + } + else { + switch (actual) { + case sim_io_eof: + args.actual = 0; + break; + case sim_io_not_ready: + ASSERT(sim_io_not_ready == -2); + args.actual = sim_io_not_ready; + break; + default: + error("Bad error value %ld", (long)actual); + break; + } + } } /* return the result */ TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n", - (long)T2H_4(args.actual), - (actual >= 0 ? buf : ""))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (long)args.actual, + ((args.actual > 0 && args.actual < sizeof(buf)) ? buf : "") + )); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } static int chirp_emul_write(os_emul_data *data, - cpu *processor, - unsigned_word cia) + cpu *processor, + unsigned_word cia) { struct write_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ - unsigned32 ihandle; - unsigned32 addr; - unsigned32 len; + unsigned_cell ihandle; + unsigned_cell addr; + unsigned_cell len; /*out*/ - unsigned32 actual; + unsigned_cell actual; } args; char buf[1024]; + device_instance *ihandle; int actual; /* get the args */ - if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) return -1; - actual = T2H_4(args.len); + actual = args.len; if (actual >= sizeof(buf)) actual = sizeof(buf) - 1; emul_read_buffer(buf, - T2H_4(args.addr), + args.addr, actual, processor, cia); buf[actual] = '\0'; - TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n", - (unsigned long)args.ihandle, buf, (long)actual)); - /* write it out */ - actual = write(BE2H_4(args.ihandle), buf, actual); - if (actual < 0) - args.actual = 0; - else - args.actual = H2T_4(actual); + ihandle = external_to_device_instance(data->root, args.ihandle); + TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n", + (unsigned long)args.ihandle, + (unsigned long)ihandle, + ihandle_name(ihandle), + buf, (long)actual)); + if (ihandle == NULL) { + /* OpenFirmware doesn't define this error */ + error("chirp: invalid ihandle passed to write method"); + } + else { + /* write it out */ + actual = device_instance_write(ihandle, buf, actual); + if (actual < 0) + args.actual = 0; + else + args.actual = actual; + } /* return the result */ TRACE(trace_os_emul, ("write - out - actual=%ld\n", - (long)T2H_4(args.actual))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (long)args.actual)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -663,7 +1118,41 @@ chirp_emul_seek(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: seek not implemented\n"); + struct seek_args { + /*in*/ + unsigned_cell ihandle; + unsigned_cell pos_hi; + unsigned_cell pos_lo; + /*out*/ + unsigned_cell status; + } args; + int status; + device_instance *ihandle; + /* get the args */ + if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia)) + return -1; + ihandle = external_to_device_instance(data->root, args.ihandle); + TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n", + (unsigned long)args.ihandle, + (unsigned long)ihandle, + ihandle_name(ihandle), + args.pos_hi, args.pos_lo)); + if (ihandle == NULL) { + /* OpenFirmware doesn't define this error */ + error("chirp: invalid ihandle passed to seek method"); + } + else { + /* seek it out */ + status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo); + args.status = status; + } + /* return the result */ + TRACE(trace_os_emul, ("seek - out - status=%ld\n", + (long)args.status)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -675,7 +1164,55 @@ chirp_emul_claim(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: claim not implemented\n"); + /* NOTE: the client interface claim routine is *very* different to + the "claim" method described in IEEE-1275 appendix A. The latter + uses real addresses while this uses virtual (effective) + addresses. */ + struct claim_args { + /* in */ + unsigned_cell virt; + unsigned_cell size; + unsigned_cell align; + /* out */ + unsigned_cell baseaddr; + } args; + /* read the args */ + if (chirp_read_t2h_args(&args, sizeof(args), + 3 /*n_args*/, 1 /*n_returns*/, + data, processor, cia)) + return -1; + TRACE(trace_os_emul, ("claim - in - virt=0x%lx size=%ld align=%d\n", + (unsigned long)args.virt, + (long int)args.size, + (int)args.align)); + /* use the memory device to allocate (real) memory at the requested + address */ + { + device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory"); + unsigned_cell mem_in[3]; + unsigned_cell mem_out[1]; + mem_in[0] = args.align; /*top-of-stack*/ + mem_in[1] = args.size; + mem_in[2] = args.virt; + if (device_instance_call_method(memory, "claim", + 3, mem_in, 1, mem_out) < 0) + error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d", + (unsigned long)args.virt, + (long int)args.size, + (int)args.align); + args.baseaddr = mem_out[0]; + } + /* if using virtual addresses, create a 1-1 map of this address space */ + if (!data->real_mode) { + error("chirp: claim method does not support virtual mode"); + } + /* return the base address */ + TRACE(trace_os_emul, ("claim - out - baseaddr=0x%lx\n", + (unsigned long)args.baseaddr)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -684,7 +1221,47 @@ chirp_emul_release(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: release not implemented\n"); + /* NOTE: the client interface release routine is *very* different to + the "claim" method described in IEEE-1275 appendix A. The latter + uses real addresses while this uses virtual (effective) + addresses. */ + struct claim_args { + /* in */ + unsigned_cell virt; + unsigned_cell size; + /* out */ + } args; + /* read the args */ + if (chirp_read_t2h_args(&args, sizeof(args), + 2 /*n_args*/, 0 /*n_returns*/, + data, processor, cia)) + return -1; + TRACE(trace_os_emul, ("release - in - virt=0x%lx size=%ld\n", + (unsigned long)args.virt, + (long int)args.size)); + /* use the memory device to release (real) memory at the requested + address */ + { + device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory"); + unsigned_cell mem_in[2]; + mem_in[0] = args.size; + mem_in[1] = args.virt; + if (device_instance_call_method(memory, "release", + 2, mem_in, 0, NULL) < 0) + error("chirp: claim failed to release memory virt=0x%lx size=%ld", + (unsigned long)args.virt, + (long int)args.size); + } + /* if using virtual addresses, remove the 1-1 map of this address space */ + if (!data->real_mode) { + error("chirp: release method does not support virtual mode"); + } + /* return the base address */ + TRACE(trace_os_emul, ("release - out\n")); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -696,7 +1273,25 @@ chirp_emul_boot(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: boot not implemented\n"); + /* unlike OpenFirmware this one can take an argument */ + struct boot_args { + /*in*/ + unsigned_cell bootspec; + /*out*/ + } args; + char bootspec[1024]; + /* read in the arguments */ + if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia)) + cpu_halt(processor, cia, was_exited, -1); + if (args.bootspec != 0) + emul_read_string(bootspec, args.bootspec, sizeof(bootspec), + processor, cia); + else + strcpy(bootspec, "(null)"); + TRACE(trace_os_emul, ("boot - in bootspec=`%s'\n", bootspec)); + /* just report this and exit */ + printf_filtered("chrp: boot %s called, exiting.\n", bootspec); + cpu_halt(processor, cia, was_exited, 0); return 0; } @@ -705,7 +1300,7 @@ chirp_emul_enter(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: enter not implemented\n"); + error("chirp: enter method not implemented\n"); return 0; } @@ -714,7 +1309,15 @@ chirp_emul_exit(os_emul_data *data, cpu *processor, unsigned_word cia) { - cpu_halt(processor, cia, was_exited, 0); /* always succeeds */ + /* unlike OpenBoot this one can take an argument */ + struct exit_args { + /*in*/ + signed_cell status; + /*out*/ + } args; + if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia)) + cpu_halt(processor, cia, was_exited, -1); + cpu_halt(processor, cia, was_exited, args.status); return 0; } @@ -723,7 +1326,7 @@ chirp_emul_chain(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: chain not implemented\n"); + error("chirp: chain method not implemented\n"); return 0; } @@ -735,7 +1338,7 @@ chirp_emul_interpret(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: interpret not implemented\n"); + error("chirp: interpret method not implemented\n"); return 0; } @@ -744,7 +1347,7 @@ chirp_emul_set_callback(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: set_callback not implemented\n"); + error("chirp: set_callback method not implemented\n"); return 0; } @@ -753,7 +1356,7 @@ chirp_emul_set_symbol_lookup(os_emul_data *data, cpu *processor, unsigned_word cia) { - error("chirp: set_symbol_lookup not implemented\n"); + error("chirp: set_symbol_lookup method not implemented\n"); return 0; } @@ -766,26 +1369,24 @@ chirp_emul_milliseconds(os_emul_data *data, unsigned_word cia) { struct test_args { - unsigned32 service; - unsigned32 n_args; - unsigned32 n_returns; /*in*/ /*out*/ - unsigned32 ms; + unsigned_cell ms; } args; unsigned64 time; /* read in the arguments */ - if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia)) + if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia)) return -1; /* make up a number */ - time = event_queue_time(cpu_event_queue(processor)) / 1000000; - args.ms = H2T_4(time); + time = event_queue_time(psim_event_queue(cpu_system(processor))) / 1000000; + args.ms = time; /* write the arguments back out */ TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n", - (unsigned long)T2H_4(args.ms))); - emul_write_buffer(&args, data->arguments, - sizeof(args), - processor, cia); + (unsigned long)args.ms)); + chirp_write_h2t_args(&args, + sizeof(args), + data, + processor, cia); return 0; } @@ -805,7 +1406,7 @@ static chirp_services services[] = { { "getproplen", chirp_emul_getproplen }, { "getprop", chirp_emul_getprop }, { "nextprop", chirp_emul_nextprop }, - { "setprop", chirp_emul_setprop }, + /* { "setprop", chirp_emul_setprop }, */ { "canon", chirp_emul_canon }, { "finddevice", chirp_emul_finddevice }, { "instance-to-path", chirp_emul_instance_to_path }, @@ -850,6 +1451,10 @@ static chirp_services services[] = { #ifndef CHIRP_START_ADDRESS #define CHIRP_START_ADDRESS 0x80000000 #endif +#ifndef CHIRP_LOAD_BASE +#define CHIRP_LOAD_BASE -1 +#endif + typedef struct _chirp_note_desc { signed32 real_mode; @@ -857,11 +1462,17 @@ typedef struct _chirp_note_desc { signed32 real_size; signed32 virt_base; signed32 virt_size; + signed32 load_base; } chirp_note_desc; +typedef enum { + note_missing, + note_found, + note_correct, +} note_found_status; typedef struct _chirp_note { chirp_note_desc desc; - int found; + note_found_status found; } chirp_note; typedef struct _chirp_note_head { @@ -888,41 +1499,43 @@ map_over_chirp_note(bfd *image, head.type = bfd_get_32(image, (void*)&head.type); if (head.type != 0x1275) return; - note->found = 1; /* check the name field */ if (head.namesz > sizeof(name)) { - printf_filtered("open-boot warning: note name too long (%ld)\n", - (long)head.namesz); - return; + error("chirp: note name too long (%d > %d)\n", (int)head.namesz, sizeof(name)); } if (!bfd_get_section_contents(image, sect, name, sizeof(head), head.namesz)) { - printf_filtered("open-boot warning: note name unreadable\n"); - return; + error("chirp: note name unreadable\n"); } if (strcmp(name, "PowerPC") != 0) { - printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n", - name); - return; + printf_filtered("chirp: note name (%s) not `PowerPC'\n", name); } - /* get the contents */ - if (head.descsz != sizeof(note->desc)) { - printf_filtered("open-boot warning: note descriptor of wrong size\n"); + /* check the size */ + if (head.descsz == sizeof(note->desc) - sizeof(signed32)) { + sim_io_printf_filtered("chirp: note descriptor missing load-base\n"); + } + else if (head.descsz != sizeof(note->desc)) { + sim_io_printf_filtered("chirp: note descriptor of wrong size\n"); + note->found = note_found; return; } + note->found = note_correct; + /* get the contents */ if (!bfd_get_section_contents(image, sect, ¬e->desc, /* page align start */ ((sizeof(head) + head.namesz) + 3) & ~3, head.descsz)) { - printf_filtered("open-boot warning: note descriptor unreadable\n"); - return; + error("chirp: note descriptor unreadable\n"); } note->desc.real_mode = bfd_get_32(image, (void*)¬e->desc.real_mode); note->desc.real_base = bfd_get_32(image, (void*)¬e->desc.real_base); note->desc.real_size = bfd_get_32(image, (void*)¬e->desc.real_size); note->desc.virt_base = bfd_get_32(image, (void*)¬e->desc.virt_base); note->desc.virt_size = bfd_get_32(image, (void*)¬e->desc.virt_size); - note->found = 2; + if (head.descsz == sizeof(note->desc)) + note->desc.load_base = bfd_get_32(image, (void*)¬e->desc.load_base); + else + note->desc.load_base = CHIRP_LOAD_BASE; } } @@ -932,9 +1545,10 @@ emul_chirp_create(device *root, bfd *image, const char *name) { - os_emul_data *data; + os_emul_data *chirp; + device *node; chirp_note note; - int big_endian; + int i; /* Sanity check that this really is the chosen emulation */ if (name == NULL && image == NULL) @@ -947,204 +1561,347 @@ emul_chirp_create(device *root, && strcmp(name, "openboot") != 0) return NULL; - /* look for an elf note section */ + /* look for an elf note section, enter its values into the device tree */ memset(¬e, 0, sizeof(note)); if (image != NULL) bfd_map_over_sections(image, map_over_chirp_note, ¬e); - if (name == NULL && image != NULL && !note.found) + if (name == NULL && image != NULL && note.found == note_missing) return NULL; + /* Assume that it is a chirp emulation */ + + chirp = ZALLOC(os_emul_data); + chirp->root = root; + chirp->services = services; + /* the root node */ - device_add_string_property(root, - "name", - "gpl,clayton"); + tree_parse(root, "/name \"gpl,clayton"); - { - const unsigned_word memory_size = 0x200000; - - /* the hash table */ - const unsigned nr_page_table_entry_groups = (memory_size < 0x800000 - ? 1024 /* min allowed */ - : (memory_size / 4096 / 2)); - const unsigned sizeof_htab = nr_page_table_entry_groups * 64; - const unsigned_word htab_ra = memory_size - sizeof_htab; - - /* a page for firmware calls */ - const unsigned_word sizeof_code = 4096; - const unsigned_word code_ra = htab_ra - sizeof_code; - - /* the stack */ - const unsigned sizeof_stack = 32 * 1024; - const unsigned_word stack_ra = code_ra - sizeof_stack; - - /* the firmware's home */ - const int real_mode = 0; - /* const unsigned_word real_base = stack_ra; */ - /* const unsigned real_size = memory_size - real_base; */ - const unsigned_word virt_base = CHIRP_START_ADDRESS; - /* const unsigned virt_size = real_size;*/ - - /* the virtual addresses */ - const unsigned_word stack_va = virt_base; - const unsigned_word code_va = stack_va + sizeof_stack; - const unsigned_word code_client_va = code_va; - const unsigned_word code_callback_va = code_client_va + 16; - const unsigned_word code_loop_va = code_callback_va + 16; - const unsigned_word htab_va = code_va + sizeof_code; - -#ifdef bfd_big_endian /* new bfd */ - big_endian = bfd_big_endian(image); -#else - big_endian = image->xvec->byteorder_big_p; -#endif + /* default options */ + emul_add_tree_options(root, image, "chirp", "oea", + 0 /*oea-interrupt-prefix*/); - /* options */ - { - device *options = device_tree_add_found(root, "/", "options"); - device_add_integer_property(options, - "smp", - MAX_NR_PROCESSORS); - device_add_boolean_property(options, - "little-endian?", - !big_endian); - device_add_string_property(options, - "env", - "operating"); - device_add_boolean_property(options, - "strict-alignment?", - (WITH_ALIGNMENT == STRICT_ALIGNMENT - || !big_endian)); - device_add_boolean_property(options, - "floating-point?", - WITH_FLOATING_POINT); - device_add_string_property(options, - "os-emul", - "chirp"); - } - - /* hardware */ - device_tree_add_found_uw_u_u(root, "/", "memory", - 0, memory_size, access_read_write_exec); - - /* initialization */ - { - device *init = device_tree_add_found(root, "/", "init"); - { - device *init_register = device_tree_add_found(init, "", "register"); - device_add_integer_property(init_register, - "pc", - code_loop_va); - device_add_integer_property(init_register, - "0.pc", - bfd_get_start_address(image)); - device_add_integer_property(init_register, - "sp", - stack_va + sizeof_stack - 16); - - /* init the code callback along with a loop for the unused cpu's */ - device_add_integer_property(init_register, - "r5", - code_client_va); - /* client interface */ - device_tree_add_found_uw_u_u(init, "", - "data", - code_ra + (code_client_va - code_va), - 4, emul_call_instruction); - device_tree_add_found_uw_u_u(init, "", - "data", - code_ra + (code_client_va - code_va) + 4, - 4, emul_blr_instruction); - /* callback return address */ - device_tree_add_found_uw_u_u(init, "", - "data", - code_ra + (code_callback_va - code_va), - 4, emul_call_instruction); - /* loop to keep other processors busy */ - device_tree_add_found_uw_u_u(init, "", - "data", - code_ra + (code_loop_va - code_va), - 4, emul_loop_instruction); - device_add_integer_property(init_register, - "msr", - (msr_machine_check_enable - | (real_mode - ? 0 - : (msr_instruction_relocate - | msr_data_relocate)) - | (big_endian - ? 0 - : (msr_little_endian_mode - | msr_interrupt_little_endian_mode - )))); - device_add_integer_property(init_register, - "sdr1", - (htab_ra - | MASK32(16, 22) - | ((sizeof_htab - 1) >> 16))); - /* FIXME */ - device_add_integer_property(init_register, - "sr8", - 0x00fffff8); - device_add_integer_property(init_register, - "sr9", - 0x00fffff9); - - { /* hash table and vm */ - device *htab_root = device_tree_add_found_uw_u(init, "", "htab", - htab_ra, sizeof_htab); - device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte", - stack_ra, stack_va, sizeof_stack, - 0x7/*wimg*/, 0x2/*pp*/); - device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte", - code_ra, code_va, sizeof_code, - 0x7/*wimg*/, 0x2/*pp*/); - device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte", - htab_ra, htab_va, sizeof_htab, - 0x7/*wimg*/, 0x2/*pp*/); - device_tree_add_found_uw_u_u_c(htab_root, "", "pte", - 0x4000, /*magic*/ - 0x7/*wimg*/, 0x2/*pp*/, - bfd_get_filename (image)); - } - } - } - - { /* chosen options */ - device *chosen = device_tree_add_found(root, "/", "chosen"); - device_add_string_property(chosen, - "name", - "chosen"); - device_add_integer_property(chosen, - "stdin", - 0); /* FIXME: ihandle of stdin */ - device_add_integer_property(chosen, - "stdout", - 1); /* FIXME: ihandle of stdout */ - device_add_string_property(chosen, - "bootpath", - "/disk@0:\\boot"); - device_add_string_property(chosen, - "bootargs", - ""); -#if 0 - device_add_integer_property(chosen, - "memory", - 0); /* FIXME: ihandle of memory */ - device_add_integer_property(chosen, - "mmu", - 0); -#endif - } - - /* FIXME - should come from the device tree */ - data = ZALLOC(os_emul_data); - data->serving_instruction_ea = code_client_va; - data->catching_instruction_ea = code_callback_va; - data->phandles = cap_create("chirp"); - data->root = root; - data->services = services; - return data; + /* hardware */ + emul_add_tree_hardware(root); + + /* basic information */ + chirp->memory_size + = tree_find_integer_property(root, "/openprom/options/oea-memory-size"); + chirp->little_endian + = tree_find_boolean_property(root, "/options/little-endian?"); + chirp->floating_point_available + = tree_find_boolean_property(root, "/openprom/options/floating-point?"); + chirp->interrupt_prefix = + tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix"); + + + /* Perform an interum layout of the openboot firmware in memory */ + + + /* a page for firmware calls */ + chirp->sizeof_code = 4096; + chirp->code_offset = 0x4000; /* possible space for interrupt table */ + + /* the stack */ + chirp->sizeof_stack = 32 * 1024; + chirp->stack_offset = chirp->code_offset + chirp->sizeof_code; + + /* the hash table */ + if (!note.desc.real_mode) { + chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000 + ? 1024 /* min allowed */ + : (chirp->memory_size / 4096 / 2)); + chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64; + } + chirp->htab_offset = chirp->stack_offset + chirp->sizeof_stack; + + /* the actual amount of space needed */ + chirp->real_size = chirp->htab_offset + chirp->sizeof_htab; + + + /* now go through and see if it fits in what is available */ + + + /* resolve real-mode? */ + if (note.found == note_correct) + chirp->real_mode = note.desc.real_mode; + else if (tree_find_property(root, "/options/real-mode?") != NULL) + chirp->real_mode = tree_find_boolean_property(root, "/options/real-mode?"); + else + chirp->real_mode = 0; + if (tree_find_property(root, "/options/real-mode?") != NULL) { + if (!chirp->real_mode + != !tree_find_boolean_property(root, "/options/real-mode?")) + error("chirp: /options/real-mode? conflicts with note section\n"); + } + else + tree_parse(root, "/options/real-mode? %s", + chirp->real_mode ? "true" : "false"); + + /* resolve real-base */ + if (note.found == note_correct + && note.desc.real_base != (signed32)-1) + chirp->real_base = note.desc.real_base; + else if (tree_find_property(root, "/options/real-base") != NULL) + chirp->real_base = tree_find_integer_property(root, "/options/real-base"); + else + chirp->real_base = chirp->memory_size - chirp->real_size; + if (tree_find_property(root, "/options/real-base") != NULL) { + if (chirp->real_base != tree_find_integer_property(root, "/options/real-base")) + error("chirp: /options/real-base conflicts with note section\n"); + } + else + tree_parse(root, "/options/real-base 0x%lx", + (unsigned long)chirp->real_base); + + /* resolve real-size */ + if (note.found == note_correct + && note.desc.real_size != (signed32)-1 + && note.desc.real_size != 0 + && chirp->real_size > note.desc.real_size) + error("chirp: insufficient physical memory for firmware\n"); + if (tree_find_property(root, "/options/real-size") != NULL) { + if (chirp->real_size > tree_find_integer_property(root, "/options/real-size")) + error("chirp: /options/real-size conflicts with note section\n"); + } + else + tree_parse(root, "/options/real-size 0x%lx", + (unsigned long)chirp->real_size); + + /* resolve virt-base */ + if (chirp->real_mode) + chirp->virt_base = chirp->real_base; + else if (note.found == note_correct && note.desc.virt_base != (signed32)-1) + chirp->virt_base = note.desc.virt_base; + else if (tree_find_property(root, "/options/virt-base") != NULL) + chirp->virt_base = tree_find_integer_property(root, "/options/virt-base"); + else + chirp->virt_base = CHIRP_START_ADDRESS; + if (tree_find_property(root, "/options/virt-base") != NULL) { + if (chirp->virt_base != tree_find_integer_property(root, "/options/virt-base")) + error("chirp: /options/virt-base conflicts with note section\n"); + } + else + tree_parse(root, "/options/virt-base 0x%lx", + chirp->real_mode ? -1 : (unsigned long)chirp->virt_base); + + /* resolve virt-size */ + chirp->virt_size = chirp->real_size; + if (note.found == note_correct + && note.desc.virt_size != (signed32)-1 + && note.desc.virt_size != 0 + && !chirp->real_mode + && chirp->virt_size > note.desc.virt_size) + error("chirp: insufficent virtual memory for firmware\n"); + if (tree_find_property(root, "/options/virt-size") != NULL) { + if (chirp->virt_size > tree_find_integer_property(root, "/options/virt-size")) + error("chirp: /options/virt-size conflicts with note section\n"); + } + else + tree_parse(root, "/options/virt-size 0x%lx", + chirp->real_mode ? -1 : (unsigned long)chirp->virt_size); + + /* resolve load-base */ + if (note.found == note_correct + && note.desc.load_base != (signed32)-1) + chirp->load_base = note.desc.load_base; + else if (tree_find_property(root, "/options/load-base") != NULL) + chirp->load_base = tree_find_integer_property(root, "/options/load-base"); + else + chirp->load_base = CHIRP_LOAD_BASE; + if (tree_find_property(root, "/options/load-base") != NULL) { + if (chirp->load_base != tree_find_integer_property(root, "/options/load-base")) + error("chirp: /options/load-base conflicts with note section\n"); + } + else + tree_parse(root, "/options/load-base 0x%lx", + (unsigned long)chirp->load_base); + + /* now adjust the preliminary firmware addresses to final values */ + chirp->code_ra = chirp->code_offset + chirp->real_base; + chirp->stack_ra = chirp->stack_offset + chirp->real_base; + chirp->htab_ra = chirp->htab_offset + chirp->real_base; + + /* the virtual addresses. In real mode these are real addresses. */ + + chirp->code_va = chirp->code_offset + chirp->virt_base; + chirp->stack_va = chirp->stack_offset + chirp->virt_base; + chirp->htab_va = chirp->htab_offset + chirp->virt_base; + + chirp->code_client_va = chirp->code_va; + chirp->code_client_ra = chirp->code_ra; + + chirp->code_callback_va = chirp->code_client_va + 16; + chirp->code_callback_ra = chirp->code_client_ra + 16; + + chirp->code_loop_va = chirp->code_callback_va + 16; + chirp->code_loop_ra = chirp->code_callback_ra + 16; + + /* initialization */ + + tree_parse(root, "/openprom/init"); + tree_parse(root, "/openprom/init/register"); + tree_parse(root, "/openprom/init/register/0.pc 0x%lx", + (unsigned long)bfd_get_start_address(image)); + tree_parse(root, "/openprom/init/register/pc 0x%lx", + (unsigned long)chirp->code_loop_va); + tree_parse(root, "/openprom/init/register/msr 0x%x", + (msr_machine_check_enable + | (chirp->real_mode + ? 0 + : (msr_instruction_relocate + | msr_data_relocate)) + | (chirp->little_endian + ? (msr_little_endian_mode + | msr_interrupt_little_endian_mode) + : 0) + | (chirp->floating_point_available + ? msr_floating_point_available + : 0) + | (chirp->interrupt_prefix + ? msr_interrupt_prefix + : 0) + )); + tree_parse(root, "/openprom/init/register/sdr1 0x%lx", + (unsigned long)(chirp->htab_ra + | MASK32(16, 22) + | ((chirp->sizeof_htab - 1) >> 16))); + /* make certain that the segment registers map straight through */ + for (i = 0; i < 16; i++) { + tree_parse(root, "/openprom/init/register/sr%d 0x%lx", + i, (unsigned long)i); + } + + /* establish an initial state for all processors */ + + + /* the client interface address */ + tree_parse(root, "/openprom/init/register/r5 0x%lx", + (unsigned long)chirp->code_client_va); + /* a stack */ + tree_parse(root, "/openprom/init/register/sp 0x%lx", + (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16)); + /* in chrp mode any arguments end up being concatinated */ + tree_parse(root, "/openprom/init/stack/stack-type chirp"); + + + /* client interface - emul-call followed by return instruction */ + + + node = tree_parse(root, "/openprom/init/data@0x%lx", + (unsigned long)chirp->code_client_ra); + tree_parse(node, "./psim,description \"client-interface instruction"); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)chirp->code_client_ra); + tree_parse(node, "./data 0x%lx", + (unsigned long)emul_call_instruction); + + node = tree_parse(root, "/openprom/init/data@0x%lx", + (unsigned long)(chirp->code_client_ra + 4)); + tree_parse(node, "./psim,description \"client-interface return instruction"); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)(chirp->code_client_ra + 4)); + tree_parse(node, "./data 0x%lx", + (unsigned long)emul_blr_instruction); + + + /* return address for client callbacks - an emul-call instruction + that is again followed by a return instruction */ + + + node = tree_parse(root, "/openprom/init/data@0x%lx", + (unsigned long)chirp->code_callback_ra); + tree_parse(node, "./psim,description \"client-callback instruction"); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)chirp->code_callback_ra); + tree_parse(node, "./data 0x%lx", + (unsigned long)emul_call_instruction); + + node = tree_parse(root, "/openprom/init/data@0x%lx", + (unsigned long)(chirp->code_callback_ra + 4)); + tree_parse(node, "./psim,description \"client-callback return instruction"); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)(chirp->code_callback_ra + 4)); + tree_parse(node, "./data 0x%lx", + (unsigned long)emul_blr_instruction); + + /* loop to keep other processors busy */ + + node = tree_parse(root, "/openprom/init/data@0x%lx", + (unsigned long)chirp->code_loop_ra); + tree_parse(node, "./psim,description \"processor busy loop"); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)chirp->code_loop_ra); + tree_parse(node, "./data 0x%lx", + (unsigned long)emul_loop_instruction); + + /* hash table */ + + /* create a hash table */ + + if (!chirp->real_mode) { + node = tree_parse(root, "/openprom/init/htab@0x%lx", + (unsigned long)chirp->htab_ra); + tree_parse(node, "./claim 0"); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)chirp->htab_ra); + tree_parse(node, "./nr-bytes 0x%lx", + (unsigned long)chirp->sizeof_htab); + } + + /* map in the stack */ + + if (!chirp->real_mode) { + node = tree_parse(root, "/openprom/init/htab/pte@0x%lx", + (unsigned long)chirp->stack_ra); + tree_parse(node, "./psim,description \"map in the stack"); + tree_parse(node, "./claim 1"); + tree_parse(node, "./virtual-address 0x%lx", + (unsigned long)chirp->stack_va); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)chirp->stack_ra); + tree_parse(node, "./nr-bytes 0x%lx", + (unsigned long)chirp->sizeof_stack); + tree_parse(node, "./wimg %d", 0x7); + tree_parse(node, "./pp %d", 0x2); + } + + /* map in the chrp openboot callback code */ + + if (!chirp->real_mode) { + node = tree_parse(root, "/openprom/init/htab/pte@0x%lx", + (unsigned long)chirp->code_ra); + tree_parse(node, "./psim,description \"map in chrp openboot callback code"); + tree_parse(node, "./claim 1"); + tree_parse(node, "./virtual-address 0x%lx", + (unsigned long)chirp->code_va); + tree_parse(node, "./real-address 0x%lx", + (unsigned long)chirp->code_ra); + tree_parse(node, "./nr-bytes 0x%lx", + (unsigned long)chirp->sizeof_code); + tree_parse(node, "./wimg %d", 0x7); + tree_parse(node, "./pp %d", 0x2); } + + /* map in the program to run */ + + if (chirp->real_mode) { + node = tree_parse(node, "/openprom/init/load-binary"); + tree_parse(node, "./psim,description \"load the binary"); + tree_parse(node, "./file-name %s", bfd_get_filename(image)); + tree_parse(node, "./claim 1"); + } + else { + node = tree_parse(root, "/openprom/init/htab/pte@0x%lx", + (unsigned long)chirp->load_base); + tree_parse(node, "./psim,description \"load & map the binary"); + tree_parse(node, "./claim 1"); + tree_parse(node, "./file-name \"%s", bfd_get_filename(image)); + tree_parse(node, "./wimg %d", 0x7); + tree_parse(node, "./pp %d", 0x2); + } + + return chirp; } static void @@ -1152,7 +1909,6 @@ emul_chirp_init(os_emul_data *emul_data, int nr_cpus) { emul_data->state = serving; - cap_init(emul_data->phandles); } static int @@ -1172,7 +1928,7 @@ emul_chirp_instruction_call(cpu *processor, case serving: /* we are waiting on an OpenBoot request from the client program via the client interface */ - if (cia != emul_data->serving_instruction_ea) + if (cia != emul_data->code_client_va) return 0; emul_data->return_address = LR; emul_data->arguments = cpu_registers(processor)->gpr[3]; @@ -1181,39 +1937,51 @@ emul_chirp_instruction_call(cpu *processor, processor, cia); service_name = emul_read_string(service_buf, service_name_addr, sizeof(service_buf), processor, cia); + emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned_cell), + processor, cia); + emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned_cell), + processor, cia); + /* verify what was passed */ + if (service_name_addr == 0 + || service_name == NULL) { + error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n", + (unsigned long)emul_data->return_address, + (unsigned long)emul_data->arguments); + } + if (emul_data->n_args > 6) { /* See iee1275 requirements on nr returns */ + error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n", + (unsigned long)emul_data->return_address, + (unsigned long)emul_data->arguments, + emul_data->n_returns); + } + if (emul_data->n_returns > 6) { + error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n", + (unsigned long)emul_data->return_address, + (unsigned long)emul_data->arguments, + emul_data->n_args); + } + /* look it up */ TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n", service_name, (unsigned long)emul_data->return_address, (unsigned long)emul_data->arguments)); - /* look it up */ service = services; while (service->name != NULL && strcmp(service->name, service_name) != 0) service++; + /* found or not? */ if (service->name == NULL) { error("OpenBoot service `%s' not found\n", service_name); TRACE(trace_os_emul, ("%s not found\n", service_name)); - cpu_registers(processor)->gpr[3] = 0; - cpu_restart(processor, emul_data->return_address); + cpu_registers(processor)->gpr[3] = -1; + } + else { + emul_data->service = service; + /* call upon it */ + result = service->handler(emul_data, processor, cia); + if (result != 0) + TRACE(trace_os_emul, ("%s aborted with %ld\n", service_name, (long)result)); + cpu_registers(processor)->gpr[3] = result; } - emul_data->service = service; - /* call upon it */ - result = service->handler(emul_data, processor, cia); - break; - - case faulting: - /* We were handling a client request but encountered a page fault - (or other exception). The fault needs to be passed back to the - client using the the client suplied call back interface */ - error("emul_chirp_instruction_call() faulting unimplemented\n"); - result = -1; - break; - - case catching: - /* Have called the client (via the callback interface) because - some fault (hash table miss) occured. The client has finished - handling this and is now returning */ - error("emul_chirp_instruction_call() catching unimplemented\n"); - result = -1; break; default: diff --git a/sim/ppc/gen-icache.c b/sim/ppc/gen-icache.c index 7f5e5e182ae..bd585a6ca44 100644 --- a/sim/ppc/gen-icache.c +++ b/sim/ppc/gen-icache.c @@ -83,45 +83,51 @@ print_icache_declaration(insn_table *entry, static void print_icache_extraction(lf *file, insn *instruction, - char *field_name, - char *field_type, - char *field_expression, + const char *entry_name, + const char *entry_type, + const char *entry_expression, + const char *original_name, const char *file_name, int line_nr, insn_field *cur_field, insn_bits *bits, - int use_defines, - int get_value_from_cache, - int put_value_in_cache) + icache_decl_type what_to_declare, + icache_body_type what_to_do) { - ASSERT(field_name != NULL); - if (use_defines && put_value_in_cache) { + ASSERT(entry_name != NULL); + + /* Define a storage area for the cache element */ + if (what_to_declare == undef_variables) { /* We've finished with the value - destory it */ lf_indent_suppress(file); - lf_printf(file, "#undef %s\n", field_name); + lf_printf(file, "#undef %s\n", entry_name); return; } - else if (use_defines && get_value_from_cache) { - lf_indent_suppress(file); - lf_printf(file, "#define %s ", field_name); + else if (what_to_declare == define_variables) { + lf_indent_suppress(file); + lf_printf(file, "#define %s ", entry_name); } else { - lf_print__external_reference(file, line_nr, file_name); - lf_printf(file, "%s const %s __attribute__((__unused__)) = ", - field_type == NULL ? "unsigned" : field_type, - field_name); + if (file_name != NULL) + lf_print__external_reference(file, line_nr, file_name); + lf_printf(file, "%s const %s UNUSED = ", + entry_type == NULL ? "unsigned" : entry_type, + entry_name); } + /* define a value for that storage area as determined by what is in + the cache */ if (bits != NULL - && ((bits->opcode->is_boolean - && bits->value == 0) - || !bits->opcode->is_boolean) - && strcmp(field_name, cur_field->val_string) == 0) { + && strcmp(entry_name, cur_field->val_string) == 0 + && ((bits->opcode->is_boolean && bits->value == 0) + || (!bits->opcode->is_boolean))) { /* The field has been made constant (as a result of expanding - instructions or similar) - define a constant variable with the - corresponding value. */ + instructions or similar). Remember that for a boolean field, + value is either 0 (implying the required boolean_constant) or + nonzero (implying some other value) - Define the variable + accordingly */ ASSERT(bits->field == cur_field); - ASSERT(field_type == NULL); + ASSERT(entry_type == NULL); if (bits->opcode->is_boolean) lf_printf(file, "%d", bits->opcode->boolean_constant); else if (bits->opcode->last < bits->field->last) @@ -130,30 +136,48 @@ print_icache_extraction(lf *file, else lf_printf(file, "%d", bits->value); } + else if (bits != NULL + && bits->opcode->is_boolean + && original_name != NULL + && strncmp(entry_name, + original_name, strlen(original_name)) == 0 + && strncmp(entry_name + strlen(original_name), + "_is_", strlen("_is_")) == 0 + && (atol(entry_name + strlen(original_name) + strlen("_is_")) + == bits->opcode->boolean_constant)) { + /* An entry, derived from ORIGINAL_NAME, is testing to see of the + ORIGINAL_NAME has a specific constant value. That value + matching a boolean bit field */ + lf_printf(file, "%d /* %s == %d */", + bits->value == 0, original_name, bits->opcode->boolean_constant); + } else { /* put the field in the local variable, possibly also enter it into the cache */ - /* getting it from the cache */ - if (get_value_from_cache || put_value_in_cache) { + /* handle the cache */ + if ((what_to_do & get_values_from_icache) + || (what_to_do & put_values_in_icache)) { lf_printf(file, "cache_entry->crack.%s.%s", instruction->file_entry->fields[insn_form], - field_name); - if (put_value_in_cache) /* also put it in the cache? */ + entry_name); + if (what_to_do & put_values_in_icache) /* also put it in the cache? */ lf_printf(file, " = "); } - if (!get_value_from_cache) { - if (strcmp(field_name, cur_field->val_string) == 0) + if ((what_to_do & put_values_in_icache) + || what_to_do == do_not_use_icache) { + if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0) lf_printf(file, "EXTRACTED32(instruction, %d, %d)", i2target(hi_bit_nr, cur_field->first), i2target(hi_bit_nr, cur_field->last)); - else if (field_expression != NULL) - lf_printf(file, "%s", field_expression); + else if (entry_expression != NULL) + lf_printf(file, "%s", entry_expression); else - lf_printf(file, "eval_%s", field_name); + lf_printf(file, "eval_%s", entry_name); } } - if (use_defines && get_value_from_cache) + if ((what_to_declare == define_variables) + || (what_to_declare == undef_variables)) lf_printf(file, "\n"); else lf_printf(file, ";\n"); @@ -165,16 +189,41 @@ print_icache_body(lf *file, insn *instruction, insn_bits *expanded_bits, cache_table *cache_rules, - int use_defines, - int get_value_from_cache, - int put_value_in_cache) + icache_decl_type what_to_declare, + icache_body_type what_to_do) { insn_field *cur_field; /* extract instruction fields */ - lf_printf(file, "/* extraction: %s defines=%d get-value=%d put-value=%d */\n", - instruction->file_entry->fields[insn_format], - use_defines, get_value_from_cache, put_value_in_cache); + lf_printf(file, "/* extraction: %s ", + instruction->file_entry->fields[insn_format]); + switch (what_to_declare) { + case define_variables: + lf_printf(file, "#define"); + break; + case declare_variables: + lf_printf(file, "declare"); + break; + case undef_variables: + lf_printf(file, "#undef"); + break; + } + lf_printf(file, " "); + switch (what_to_do) { + case get_values_from_icache: + lf_printf(file, "get-values-from-icache"); + break; + case put_values_in_icache: + lf_printf(file, "put-values-in-icache"); + break; + case both_values_and_icache: + lf_printf(file, "get-values-from-icache|put-values-in-icache"); + break; + case do_not_use_icache: + lf_printf(file, "do-not-use-icache"); + break; + } + lf_printf(file, " */\n"); for (cur_field = instruction->fields->first; cur_field->first < insn_bit_size; @@ -190,100 +239,98 @@ print_icache_body(lf *file, break; } /* try the cache rule table for what to do */ - if (get_value_from_cache || put_value_in_cache) { + { cache_table *cache_rule; for (cache_rule = cache_rules; cache_rule != NULL; cache_rule = cache_rule->next) { - if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) { + if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) { found_rule = 1; - if (cache_rule->type == compute_value - && put_value_in_cache - && !use_defines) + if (cache_rule->type == scratch_value + && ((what_to_do & put_values_in_icache) + || what_to_do == do_not_use_icache)) + print_icache_extraction(file, + instruction, + cache_rule->derived_name, + cache_rule->type_def, + cache_rule->expression, + cache_rule->field_name, + cache_rule->file_entry->file_name, + cache_rule->file_entry->line_nr, + cur_field, + bits, + what_to_declare, + do_not_use_icache); + else if (cache_rule->type == compute_value + && ((what_to_do & get_values_from_icache) + || what_to_do == do_not_use_icache)) print_icache_extraction(file, instruction, - cache_rule->new_name, + cache_rule->derived_name, cache_rule->type_def, cache_rule->expression, + cache_rule->field_name, cache_rule->file_entry->file_name, cache_rule->file_entry->line_nr, cur_field, bits, - 0 /*use_defines*/, - 0 /*get-value-from-cache*/, - 0 /*put-value-in-cache*/); - else if (cache_rule->type == cache_value) + what_to_declare, + do_not_use_icache); + else if (cache_rule->type == cache_value + && ((what_to_declare != undef_variables) + || !(what_to_do & put_values_in_icache))) print_icache_extraction(file, instruction, - cache_rule->new_name, + cache_rule->derived_name, cache_rule->type_def, cache_rule->expression, + cache_rule->field_name, cache_rule->file_entry->file_name, cache_rule->file_entry->line_nr, cur_field, bits, - use_defines, - get_value_from_cache, - put_value_in_cache); + ((what_to_do & put_values_in_icache) + ? declare_variables + : what_to_declare), + what_to_do); } } } - if (found_rule == 0) + /* No rule at all, assume that it should go into the cache */ + if (found_rule == 0 + && ((what_to_declare != undef_variables) + || !(what_to_do & put_values_in_icache))) print_icache_extraction(file, instruction, cur_field->val_string, - 0, - 0, + NULL, NULL, NULL, /* type, exp, orig */ instruction->file_entry->file_name, instruction->file_entry->line_nr, cur_field, bits, - use_defines, - get_value_from_cache, - put_value_in_cache); - /* if any (XXX == 0), output a corresponding test */ - if (instruction->file_entry->annex != NULL) { - char *field_name = cur_field->val_string; - char *is_0_ptr = instruction->file_entry->annex; - int field_len = strlen(field_name); - if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) { - is_0_ptr += field_len; - while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) { - if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0 - && !isalpha(is_0_ptr[ - field_len - 1])) { - if (!use_defines || (use_defines && get_value_from_cache)) { - if (use_defines) { - lf_indent_suppress(file); - lf_printf(file, "#define %s_is_0 ", field_name); - } - else { - table_entry_print_cpp_line_nr(file, instruction->file_entry); - lf_printf(file, "const unsigned %s_is_0 __attribute__((__unused__)) = ", - field_name); - } - if (bits != NULL) - lf_printf(file, "(%d == 0)", bits->value); - else - lf_printf(file, "(%s == 0)", field_name); - if (use_defines) - lf_printf(file, "\n"); - else - lf_printf(file, ";\n"); - } - else if (use_defines && put_value_in_cache) { - lf_indent_suppress(file); - lf_printf(file, "#undef %s_is_0\n", field_name); - } - break; - } - is_0_ptr += strlen("_is_0"); - } - } - } + ((what_to_do & put_values_in_icache) + ? declare_variables + : what_to_declare), + what_to_do); /* any thing else ... */ } } + lf_print__internal_reference(file); + + if ((code & generate_with_insn_in_icache)) { + lf_printf(file, "\n"); + print_icache_extraction(file, + instruction, + "insn", + "instruction_word", + "instruction", + NULL, /* origin */ + NULL, 0, /* file_name & line_nr */ + NULL, NULL, + what_to_declare, + what_to_do); + } } @@ -356,6 +403,7 @@ print_icache_struct(insn_table *instructions, { icache_tree *tree = insn_table_cache_fields(instructions); + lf_printf(file, "\n"); lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n", (code & generate_with_icache) ? icache_size : 0); lf_printf(file, "\n"); @@ -372,6 +420,8 @@ print_icache_struct(insn_table *instructions, form = form->next) { icache_tree *field; lf_printf(file, " struct {\n"); + if (code & generate_with_insn_in_icache) + lf_printf(file, " instruction_word insn;\n"); for (field = form->children; field != NULL; field = field->next) { @@ -380,15 +430,15 @@ print_icache_struct(insn_table *instructions, for (cache_rule = cache_rules; cache_rule != NULL; cache_rule = cache_rule->next) { - if (strcmp(field->name, cache_rule->old_name) == 0) { + if (strcmp(field->name, cache_rule->field_name) == 0) { found_rule = 1; - if (cache_rule->new_name != NULL) + if (cache_rule->derived_name != NULL) lf_printf(file, " %s %s; /* %s */\n", (cache_rule->type_def == NULL ? "unsigned" : cache_rule->type_def), - cache_rule->new_name, - cache_rule->old_name); + cache_rule->derived_name, + cache_rule->field_name); } } if (!found_rule) @@ -400,23 +450,11 @@ print_icache_struct(insn_table *instructions, lf_printf(file, "} idecode_cache;\n"); } else { - /* alernativly, since no cache, #define the fields to be - extractions from the instruction variable. Emit a dummy - definition for idecode_cache to allow model_issue to not - be #ifdefed at the call level */ - cache_table *cache_rule; - lf_printf(file, "\n"); + /* alernativly, since no cache, emit a dummy definition for + idecode_cache so that code refering to the type can still compile */ lf_printf(file, "typedef void idecode_cache;\n"); - lf_printf(file, "\n"); - for (cache_rule = cache_rules; - cache_rule != NULL; - cache_rule = cache_rule->next) { - if (cache_rule->expression != NULL - && strlen(cache_rule->expression) > 0) - lf_printf(file, "#define %s %s\n", - cache_rule->new_name, cache_rule->expression); - } } + lf_printf(file, "\n"); } @@ -445,7 +483,7 @@ print_icache_function(lf *file, lf_printf(file, "{\n"); lf_indent(file, +2); - print_define_my_index(file, instruction->file_entry); + print_my_defines(file, expanded_bits, instruction->file_entry); print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/); print_idecode_validate(file, instruction, opcodes); @@ -453,47 +491,60 @@ print_icache_function(lf *file, lf_printf(file, "\n"); lf_printf(file, "{\n"); lf_indent(file, +2); + if ((code & generate_with_semantic_icache)) + lf_printf(file, "unsigned_word nia;\n"); print_icache_body(file, instruction, expanded_bits, cache_rules, - 0/*use_defines*/, - 0/*get_value_from_cache*/, - 1/*put_value_in_cache*/); + ((code & generate_with_direct_access) + ? define_variables + : declare_variables), + ((code & generate_with_semantic_icache) + ? both_values_and_icache + : put_values_in_icache)); + lf_printf(file, "\n"); + lf_printf(file, "cache_entry->address = cia;\n"); + lf_printf(file, "cache_entry->semantic = "); + print_function_name(file, + instruction->file_entry->fields[insn_name], + expanded_bits, + function_name_prefix_semantics); + lf_printf(file, ";\n"); + lf_printf(file, "\n"); + if ((code & generate_with_semantic_icache)) { - lf_printf(file, "unsigned_word nia;\n"); - lf_printf(file, "cache_entry->address = cia;\n"); - lf_printf(file, "cache_entry->semantic = "); - print_function_name(file, - instruction->file_entry->fields[insn_name], - expanded_bits, - function_name_prefix_semantics); - lf_printf(file, ";\n"); + lf_printf(file, "/* semantic routine */\n"); print_semantic_body(file, instruction, expanded_bits, opcodes); - lf_printf(file, "\n"); lf_printf(file, "return nia;\n"); } - lf_indent(file, -2); - lf_printf(file, "}\n"); if (!(code & generate_with_semantic_icache)) { - /* return the function propper (main sorts this one out) */ - lf_printf(file, "\n"); - lf_printf(file, "/* semantic routine */\n"); - table_entry_print_cpp_line_nr(file, instruction->file_entry); + lf_printf(file, "/* return the function proper */\n"); lf_printf(file, "return "); print_function_name(file, instruction->file_entry->fields[insn_name], expanded_bits, function_name_prefix_semantics); lf_printf(file, ";\n"); - lf_print__internal_reference(file); } + if ((code & generate_with_direct_access)) + print_icache_body(file, + instruction, + expanded_bits, + cache_rules, + undef_variables, + ((code & generate_with_semantic_icache) + ? both_values_and_icache + : put_values_in_icache)); + + lf_indent(file, -2); + lf_printf(file, "}\n"); lf_indent(file, -2); lf_printf(file, "}\n"); } diff --git a/sim/ppc/gen-idecode.c b/sim/ppc/gen-idecode.c index 1c4c6bf58a5..d5a805c54df 100644 --- a/sim/ppc/gen-idecode.c +++ b/sim/ppc/gen-idecode.c @@ -42,6 +42,7 @@ lf_print_opcodes(lf *file, { if (table != NULL) { while (1) { + ASSERT(table->opcode != NULL); lf_printf(file, "_%d_%d", table->opcode->first, table->opcode->last); @@ -70,9 +71,10 @@ print_idecode_table(lf *file, insn_table *entry, const char *result) { - /* int can_assume_leaf; */ +#if 0 + /* FIXME: I don't think the second part of this is correct! */ + int can_assume_leaf; decode_table *opcode_rule; - /* have a look at the rule table, if all table rules follow all switch rules, I can assume that all end points are leaves */ opcode_rule = entry->opcode_rule; @@ -80,9 +82,6 @@ print_idecode_table(lf *file, && (opcode_rule->gen == switch_gen || opcode_rule->gen == padded_switch_gen)) opcode_rule = opcode_rule->next; - -#if 0 - /* FIXME: I don't get this bit! */ while (opcode_rule != NULL && (opcode_rule->gen == switch_gen || opcode_rule->gen == padded_switch_gen) @@ -189,6 +188,7 @@ print_idecode_table_leaf(insn_table *entry, lf_printf(file, " },\n"); } else if (entry->opcode_rule->gen == switch_gen + || entry->opcode_rule->gen == goto_switch_gen || entry->opcode_rule->gen == padded_switch_gen) { /* table calling switch statement */ lf_printf(file, " /*%d*/ { table_function_entry, 0, 0, 0, ", @@ -250,12 +250,89 @@ print_idecode_table_padding(insn_table *table, /****************************************************************/ +static void +print_goto_switch_name(lf *file, + insn_table *entry) +{ + lf_printf(file, "case_"); + if (entry->opcode == NULL) + print_function_name(file, + entry->insns->file_entry->fields[insn_name], + entry->expanded_bits, + ((code & generate_with_icache) + ? function_name_prefix_icache + : function_name_prefix_semantics)); + else + lf_print_table_name(file, entry); +} + +static void +print_goto_switch_table_leaf(insn_table *entry, + lf *file, + void *data, + insn *instruction, + int depth) +{ + ASSERT(entry->parent != NULL); + ASSERT(depth == 0); + ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen); + ASSERT(entry->parent->opcode); + + lf_printf(file, "&&"); + print_goto_switch_name(file, entry); + lf_printf(file, ",\n"); +} + +static void +print_goto_switch_table_padding(insn_table *table, + lf *file, + void *data, + int depth, + int opcode_nr) +{ + ASSERT(depth == 0); + ASSERT(table->opcode_rule->gen == goto_switch_gen); + + lf_printf(file, "&&illegal_"); + lf_print_table_name(file, table); + lf_printf(file, ",\n"); +} + +static void +print_goto_switch_break(lf *file, + insn_table *entry) +{ + lf_printf(file, "goto break_"); + lf_print_table_name(file, entry->parent); + lf_printf(file, ";\n"); +} + + +static void +print_goto_switch_table(lf *file, + insn_table *table) +{ + lf_printf(file, "const static void *"); + lf_print_table_name(file, table); + lf_printf(file, "[] = {\n"); + lf_indent(file, +2); + insn_table_traverse_tree(table, + file, NULL/*data*/, + 0, + NULL/*start*/, + print_goto_switch_table_leaf, + NULL/*end*/, + print_goto_switch_table_padding); + lf_indent(file, -2); + lf_printf(file, "};\n"); +} + + void print_idecode_switch (lf *file, insn_table *table, const char *result); - static void idecode_switch_start(insn_table *table, lf *file, @@ -265,15 +342,39 @@ idecode_switch_start(insn_table *table, /* const char *result = data; */ ASSERT(depth == 0); ASSERT(table->opcode_rule->gen == switch_gen - || table->opcode_rule->gen == padded_switch_gen - || table->opcode_rule->gen == goto_gen); + || table->opcode_rule->gen == goto_switch_gen + || table->opcode_rule->gen == padded_switch_gen); - switch (table->opcode_rule->gen) { - default: + if (table->opcode->is_boolean + || table->opcode_rule->gen == switch_gen + || table->opcode_rule->gen == padded_switch_gen) { lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n", i2target(hi_bit_nr, table->opcode->first), i2target(hi_bit_nr, table->opcode->last)); - break; + } + else if (table->opcode_rule->gen == goto_switch_gen) { + if (table->parent != NULL + && (table->parent->opcode_rule->gen == switch_gen + || table->parent->opcode_rule->gen == goto_switch_gen + || table->parent->opcode_rule->gen == padded_switch_gen)) { + lf_printf(file, "{\n"); + lf_indent(file, +2); + } + print_goto_switch_table(file, table); + lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n", + i2target(hi_bit_nr, table->opcode->first), + i2target(hi_bit_nr, table->opcode->last)); + lf_printf(file, " < (sizeof("); + lf_print_table_name(file, table); + lf_printf(file, ") / sizeof(void*)));\n"); + lf_printf(file, "goto *"); + lf_print_table_name(file, table); + lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n", + i2target(hi_bit_nr, table->opcode->first), + i2target(hi_bit_nr, table->opcode->last)); + } + else { + ASSERT("bad switch" == NULL); } } @@ -289,16 +390,34 @@ idecode_switch_leaf(insn_table *entry, ASSERT(entry->parent != NULL); ASSERT(depth == 0); ASSERT(entry->parent->opcode_rule->gen == switch_gen + || entry->parent->opcode_rule->gen == goto_switch_gen || entry->parent->opcode_rule->gen == padded_switch_gen); ASSERT(entry->parent->opcode); if (entry->parent->opcode->is_boolean - && entry->opcode_nr == 0) + && entry->opcode_nr == 0) { + /* boolean false target */ lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant); - else if (!entry->parent->opcode->is_boolean) - lf_printf(file, "case %d:\n", entry->opcode_nr); - else + } + else if (entry->parent->opcode->is_boolean + && entry->opcode_nr != 0) { + /* boolean true case */ lf_printf(file, "default:\n"); + } + else if (entry->parent->opcode_rule->gen == switch_gen + || entry->parent->opcode_rule->gen == padded_switch_gen) { + /* normal goto */ + lf_printf(file, "case %d:\n", entry->opcode_nr); + } + else if (entry->parent->opcode_rule->gen == goto_switch_gen) { + /* lf_indent(file, -1); */ + print_goto_switch_name(file, entry); + lf_printf(file, ":\n"); + /* lf_indent(file, +1); */ + } + else { + ASSERT("bad switch" == NULL); + } lf_indent(file, +2); { if (entry->opcode == NULL) { @@ -318,6 +437,7 @@ idecode_switch_leaf(insn_table *entry, lf_printf(file, ";\n"); } else if (entry->opcode_rule->gen == switch_gen + || entry->opcode_rule->gen == goto_switch_gen || entry->opcode_rule->gen == padded_switch_gen) { /* switch calling switch */ print_idecode_switch(file, entry, result); @@ -330,7 +450,17 @@ idecode_switch_leaf(insn_table *entry, lf_indent(file, -2); lf_printf(file, "}\n"); } - lf_printf(file, "break;\n"); + if (entry->parent->opcode->is_boolean + || entry->parent->opcode_rule->gen == switch_gen + || entry->parent->opcode_rule->gen == padded_switch_gen) { + lf_printf(file, "break;\n"); + } + else if (entry->parent->opcode_rule->gen == goto_switch_gen) { + print_goto_switch_break(file, entry); + } + else { + ASSERT("bad switch" == NULL); + } } lf_indent(file, -2); } @@ -342,7 +472,7 @@ print_idecode_switch_illegal(lf *file, { lf_indent(file, +2); print_idecode_illegal(file, result); - /*lf_printf(file, "break;\n");*/ + lf_printf(file, "break;\n"); lf_indent(file, -2); } @@ -355,11 +485,15 @@ idecode_switch_end(insn_table *table, const char *result = data; ASSERT(depth == 0); ASSERT(table->opcode_rule->gen == switch_gen - || table->opcode_rule->gen == padded_switch_gen - || table->opcode_rule->gen == goto_gen); + || table->opcode_rule->gen == goto_switch_gen + || table->opcode_rule->gen == padded_switch_gen); ASSERT(table->opcode); - if (!table->opcode->is_boolean) { + if (table->opcode->is_boolean) { + lf_printf(file, "}\n"); + } + else if (table->opcode_rule->gen == switch_gen + || table->opcode_rule->gen == padded_switch_gen) { lf_printf(file, "default:\n"); switch (table->opcode_rule->gen) { case switch_gen: @@ -370,10 +504,29 @@ idecode_switch_end(insn_table *table, lf_printf(file, " break;\n"); break; default: - error("idecode_switch_end - unknown switch type\n"); + ASSERT("bad switch" == NULL); } + lf_printf(file, "}\n"); + } + else if (table->opcode_rule->gen == goto_switch_gen) { + lf_printf(file, "illegal_"); + lf_print_table_name(file, table); + lf_printf(file, ":\n"); + print_idecode_illegal(file, result); + lf_printf(file, "break_"); + lf_print_table_name(file, table); + lf_printf(file, ":;\n"); + if (table->parent != NULL + && (table->parent->opcode_rule->gen == switch_gen + || table->parent->opcode_rule->gen == goto_switch_gen + || table->parent->opcode_rule->gen == padded_switch_gen)) { + lf_indent(file, -2); + lf_printf(file, "}\n"); + } + } + else { + ASSERT("bad switch" == NULL); } - lf_printf(file, "}\n"); } static void @@ -386,15 +539,21 @@ idecode_switch_padding(insn_table *table, const char *result = data; ASSERT(depth == 0); ASSERT(table->opcode_rule->gen == switch_gen + || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen); - if (table->opcode_rule->gen == padded_switch_gen) { + switch (table->opcode_rule->gen) { + case switch_gen: + break; + case padded_switch_gen: lf_printf(file, "case %d:\n", opcode_nr); print_idecode_switch_illegal(file, result); - } - else if (table->opcode_rule->gen == goto_gen) { - lf_printf(file, "goto_%d:\n", opcode_nr); - print_idecode_switch_illegal(file, result); + break; + case goto_switch_gen: + /* no padding needed */ + break; + default: + ASSERT("bad switch" != NULL); } } @@ -452,12 +611,13 @@ idecode_declare_if_switch(insn_table *table, int depth) { if ((table->opcode_rule->gen == switch_gen + || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) && table->parent != NULL /* don't declare the top one yet */ && table->parent->opcode_rule->gen == array_gen) { print_idecode_switch_function_header(file, - table, - 0/*isnt function definition*/); + table, + 0/*isnt function definition*/); } } @@ -469,6 +629,7 @@ idecode_expand_if_switch(insn_table *table, int depth) { if ((table->opcode_rule->gen == switch_gen + || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) && table->parent != NULL /* don't expand the top one yet */ && table->parent->opcode_rule->gen == array_gen) { @@ -537,6 +698,7 @@ print_idecode_body(lf *file, lf_putstr(file, "{\n"); lf_indent(file, +2); if (table->opcode_rule->gen == switch_gen + || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) print_idecode_switch(file, table, result); else @@ -565,8 +727,6 @@ print_run_until_stop_body(lf *file, lf_putstr(file, "{\n"); lf_indent(file, +2); - if (!can_stop) - lf_putstr(file, "int *keep_running = NULL;\n"); lf_putstr(file, "jmp_buf halt;\n"); lf_putstr(file, "jmp_buf restart;\n"); lf_putstr(file, "cpu *processor = NULL;\n"); @@ -630,6 +790,11 @@ print_run_until_stop_body(lf *file, if (!(code & generate_with_icache)) { lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n"); print_idecode_body(file, table, "cia =", ""); + /* tail */ + if (can_stop) { + lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); + lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); + } } if ((code & generate_with_icache)) { @@ -638,6 +803,12 @@ print_run_until_stop_body(lf *file, lf_putstr(file, " /* cache hit */\n"); lf_putstr(file, " idecode_semantic *const semantic = cache_entry->semantic;\n"); lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n"); + /* tail */ + if (can_stop) { + lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); + lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); + } + lf_putstr(file, " continue;\n"); lf_putstr(file, "}\n"); lf_putstr(file, "else {\n"); lf_putstr(file, " /* cache miss */\n"); @@ -656,11 +827,15 @@ print_run_until_stop_body(lf *file, print_idecode_body(file, table, "semantic =", " "); lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n"); } + /* tail */ + if (can_stop) { + lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); + lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); + } + lf_putstr(file, " continue;\n"); lf_putstr(file, "}\n"); } - lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); - lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); lf_indent(file, -2); lf_putstr(file, "}\n"); } @@ -698,41 +873,63 @@ print_run_until_stop_body(lf *file, if (!(code & generate_with_icache)) { lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n"); print_idecode_body(file, table, "cia =", ""); + if (can_stop) { + lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); + lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); + } + lf_putstr(file, "cpu_set_program_counter(processor, cia);\n"); + lf_putstr(file, "continue;\n"); } if ((code & generate_with_icache)) { lf_putstr(file, "cache_entry = cpu_icache_entry(processor, cia);\n"); lf_putstr(file, "if (cache_entry->address == cia) {\n"); - lf_putstr(file, " /* cache hit */\n"); - lf_putstr(file, " idecode_semantic *semantic = cache_entry->semantic;\n"); - lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n"); - lf_putstr(file, "}\n"); - lf_putstr(file, "else {\n"); - lf_putstr(file, " /* cache miss */\n"); - if (!(code & generate_with_semantic_icache)) { + { lf_indent(file, +2); - lf_putstr(file, " idecode_semantic *semantic;\n"); + lf_putstr(file, "/* cache hit */\n"); + lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n"); + lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n"); + /* tail */ + if (can_stop) { + lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); + lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); + } + lf_putstr(file, "cpu_set_program_counter(processor, cia);\n"); + lf_putstr(file, "continue;\n"); lf_indent(file, -2); } - lf_putstr(file, " instruction =\n"); - lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n"); - lf_putstr(file, " if (WITH_MON != 0)\n"); - lf_putstr(file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n"); - if ((code & generate_with_semantic_icache)) { - print_idecode_body(file, table, "cia =", " "); - } - else { - print_idecode_body(file, table, "semantic = ", " "); + lf_putstr(file, "}\n"); + lf_putstr(file, "else {\n"); + { lf_indent(file, +2); - lf_putstr(file, "cia = semantic(processor, cache_entry, cia));\n"); + lf_putstr(file, "/* cache miss */\n"); + if (!(code & generate_with_semantic_icache)) { + lf_putstr(file, "idecode_semantic *semantic;\n"); + } + lf_putstr(file, "instruction =\n"); + lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n"); + lf_putstr(file, "if (WITH_MON != 0)\n"); + lf_putstr(file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n"); + if ((code & generate_with_semantic_icache)) { + print_idecode_body(file, table, "cia =", ""); + } + else { + print_idecode_body(file, table, "semantic = ", " "); + lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n"); + } + /* tail */ + if (can_stop) { + lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); + lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); + } + lf_putstr(file, "cpu_set_program_counter(processor, cia);\n"); + lf_putstr(file, "continue;\n"); lf_indent(file, -2); } lf_putstr(file, "}\n"); } - lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n"); - lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n"); - lf_putstr(file, "cpu_set_program_counter(processor, cia);\n"); + /* tail */ lf_indent(file, -2); lf_putstr(file, "}\n"); } @@ -765,10 +962,11 @@ print_jump(lf *file, } if (generate_smp) { - lf_putstr(file, "cpu_set_program_counter(processor, nia);\n"); + if (is_tail) + lf_putstr(file, "cpu_set_program_counter(processor, nia);\n"); lf_putstr(file, "if (WITH_EVENTS) {\n"); lf_putstr(file, " current_cpu += 1;\n"); - lf_putstr(file, " if (current_cpu == nr_cpus) {\n"); + lf_putstr(file, " if (current_cpu >= nr_cpus) {\n"); lf_putstr(file, " if (event_queue_tick(events)) {\n"); lf_putstr(file, " event_queue_process(events);\n"); lf_putstr(file, " }\n"); @@ -793,7 +991,7 @@ print_jump(lf *file, } } - if (!(code & generate_with_icache)) { + if (!(code & generate_with_icache) && is_tail) { lf_printf(file, "goto idecode;\n"); } @@ -813,7 +1011,7 @@ print_jump_insn(lf *file, /* what we are for the moment */ lf_printf(file, "\n"); - print_define_my_index(file, instruction->file_entry); + print_my_defines(file, expanded_bits, instruction->file_entry); /* output the icache entry */ if ((code & generate_with_icache)) { @@ -837,9 +1035,8 @@ print_jump_insn(lf *file, instruction, expanded_bits, cache_rules, - 0, - 0/*get_value_from_cache*/, - 1/*put_value_in_cache*/); + 0, /*use_defines*/ + put_values_in_icache); lf_printf(file, "cache_entry->address = nia;\n"); lf_printf(file, "cache_entry->semantic = &&"); print_function_name(file, @@ -884,13 +1081,25 @@ print_jump_insn(lf *file, instruction, expanded_bits, cache_rules, - (code & generate_with_direct_access_icache), - (code & generate_with_icache)/*get_value_from_cache*/, - 0/*put_value_in_cache*/); + ((code & generate_with_direct_access) + ? define_variables + : declare_variables), + ((code & generate_with_icache) + ? get_values_from_icache + : do_not_use_icache)); print_semantic_body(file, instruction, expanded_bits, opcodes); + if (code & generate_with_direct_access) + print_icache_body(file, + instruction, + expanded_bits, + cache_rules, + undef_variables, + ((code & generate_with_icache) + ? get_values_from_icache + : do_not_use_icache)); print_jump(file, 1/*is tail*/); lf_indent(file, -2); lf_printf(file, "}\n"); diff --git a/sim/ppc/igen.c b/sim/ppc/igen.c index 471c97bc1a5..4b9ae36f0f2 100644 --- a/sim/ppc/igen.c +++ b/sim/ppc/igen.c @@ -48,7 +48,7 @@ int insn_bit_size = max_insn_bit_size; igen_code code = generate_calls; int generate_expanded_instructions; -int icache_size; +int icache_size = 1024; int generate_smp; /****************************************************************/ @@ -127,9 +127,11 @@ print_function_name(lf *file, void -print_define_my_index(lf *file, - table_entry *file_entry) +print_my_defines(lf *file, + insn_bits *expanded_bits, + table_entry *file_entry) { + /* #define MY_INDEX xxxxx */ lf_indent_suppress(file); lf_printf(file, "#undef MY_INDEX\n"); lf_indent_suppress(file); @@ -139,6 +141,16 @@ print_define_my_index(lf *file, NULL, function_name_prefix_itable); lf_printf(file, "\n"); + /* #define MY_PREFIX xxxxxx */ + lf_indent_suppress(file); + lf_printf(file, "#undef MY_PREFIX\n"); + lf_indent_suppress(file); + lf_printf(file, "#define MY_PREFIX "); + print_function_name(file, + file_entry->fields[insn_name], + expanded_bits, + function_name_prefix_none); + lf_printf(file, "\n"); } @@ -321,9 +333,10 @@ main(int argc, printf(" igen ... ... ...\n"); printf("Config options:\n"); printf(" -F eg -F 64 to skip 64bit instructions\n"); - printf(" -C Include semantics in cache functions\n"); printf(" -E Expand (duplicate) semantic functions\n"); printf(" -I Generate cracking cache version\n"); + printf(" -C Include semantics in cache functions\n"); + printf(" -S Include insn (instruction) in icache\n"); printf(" -R Use defines to reference cache vars\n"); printf(" -L Supress line numbering in output files\n"); printf(" -B Set the number of bits in an instruction\n"); @@ -348,15 +361,17 @@ main(int argc, } while ((ch = getopt(argc, argv, - "F:EI:RLJCB:H:N:o:k:i:n:hc:d:m:s:t:f:")) + "F:EI:RSLJCB:H:N:o:k:i:n:hc:d:m:s:t:f:")) != -1) { fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : "")); switch(ch) { case 'C': code |= generate_with_icache; code |= generate_with_semantic_icache; - if (icache_size == 0) - icache_size = 1024; + break; + case 'S': + code |= generate_with_icache; + code |= generate_with_insn_in_icache; break; case 'L': file_references = lf_omit_references; @@ -372,10 +387,7 @@ main(int argc, generate_smp = a2i(optarg); break; case 'R': - code |= generate_with_icache; - code |= generate_with_direct_access_icache; - if (icache_size == 0) - icache_size = 1024; + code |= generate_with_direct_access; break; case 'B': insn_bit_size = a2i(optarg); diff --git a/sim/ppc/main.c b/sim/ppc/main.c index 99201dbd43b..454efed0a20 100644 --- a/sim/ppc/main.c +++ b/sim/ppc/main.c @@ -43,6 +43,8 @@ #endif #endif +#include + #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL) #undef WITH_STDIO #define WITH_STDIO DO_USE_STDIO @@ -69,6 +71,7 @@ error (char *msg, ...) va_list ap; va_start(ap, msg); vprintf(msg, ap); + printf("\n"); va_end(ap); /* any final clean up */ @@ -98,6 +101,7 @@ sim_io_write_stdout(const char *buf, default: error("sim_io_write_stdout: invalid switch\n"); } + return 0; } int @@ -120,6 +124,7 @@ sim_io_write_stderr(const char *buf, default: error("sim_io_write_stdout: invalid switch\n"); } + return 0; } int @@ -128,10 +133,20 @@ sim_io_read_stdin(char *buf, { switch (CURRENT_STDIO) { case DO_USE_STDIO: - if (fgets(buf, sizeof_buf, stdin) == NULL) - return sim_io_eof; - else - return strlen(buf); + if (sizeof_buf > 1) { + if (fgets(buf, sizeof_buf, stdin) != NULL) + return strlen(buf); + } + else if (sizeof_buf == 1) { + char b[2]; + if (fgets(b, sizeof(b), stdin) != NULL) { + memcpy(buf, b, strlen(b)); + return strlen(b); + } + } + else if (sizeof_buf == 0) + return 0; + return sim_io_eof; break; case DONT_USE_STDIO: { @@ -139,6 +154,7 @@ sim_io_read_stdin(char *buf, int flags; int status; int nr_read; + int result; /* get the old status */ flags = fcntl(0, F_GETFL, 0); if (flags == -1) { @@ -152,25 +168,32 @@ sim_io_read_stdin(char *buf, return sim_io_eof; } /* try for input */ - nr_read = read(0, &buf, sizeof_buf); + nr_read = read(0, buf, sizeof_buf); + if (nr_read > 0 + || (nr_read == 0 && sizeof_buf == 0)) + result = nr_read; + else if (nr_read == 0) + result = sim_io_eof; + else { /* nr_read < 0 */ + if (errno == EAGAIN) + result = sim_io_not_ready; + else + result = sim_io_eof; + } /* return to regular vewing */ status = fcntl(0, F_SETFL, flags); if (status == -1) { perror("sim_io_read_stdin"); return sim_io_eof; } - if (status > 0) - return 1; - else if (status < 0) - return sim_io_eof; - else - return sim_io_not_ready; + return result; } break; default: error("sim_io_read_stdin: invalid switch\n"); break; } + return 0; } void @@ -215,8 +238,14 @@ main(int argc, char **argv) /* parse the arguments */ argv = psim_options(root, argv + 1); - if (argv[0] == NULL) - psim_usage(0); + if (argv[0] == NULL) { + if (ppc_trace[trace_opts]) { + print_options (); + return 0; + } else { + psim_usage(0); + } + } name_of_file = argv[0]; if (ppc_trace[trace_opts]) diff --git a/sim/ppc/ppc-cache-rules b/sim/ppc/ppc-cache-rules index 270fb4a6097..2b5f4722175 100644 --- a/sim/ppc/ppc-cache-rules +++ b/sim/ppc/ppc-cache-rules @@ -20,6 +20,7 @@ cache:RA:RA:: cache:RA:rA:signed_word *:(cpu_registers(processor)->gpr + RA) cache:RA:RA_BITMASK:unsigned32:(1 << RA) +compute:RA:RA_is_0:int:(RA == 0) cache:RT:RT:: cache:RT:rT:signed_word *:(cpu_registers(processor)->gpr + RT) cache:RT:RT_BITMASK:unsigned32:(1 << RT) @@ -29,30 +30,30 @@ cache:RS:RS_BITMASK:unsigned32:(1 << RS) cache:RB:RB:: cache:RB:rB:signed_word *:(cpu_registers(processor)->gpr + RB) cache:RB:RB_BITMASK:unsigned32:(1 << RB) -compute:FRA:FRA:: +scratch:FRA:FRA:: cache:FRA:frA:unsigned64 *:(cpu_registers(processor)->fpr + FRA) cache:FRA:FRA_BITMASK:unsigned32:(1 << FRA) -compute:FRB:FRB:: +scratch:FRB:FRB:: cache:FRB:frB:unsigned64 *:(cpu_registers(processor)->fpr + FRB) cache:FRB:FRB_BITMASK:unsigned32:(1 << FRB) -compute:FRC:FRC:: +scratch:FRC:FRC:: cache:FRC:frC:unsigned64 *:(cpu_registers(processor)->fpr + FRC) cache:FRC:FRC_BITMASK:unsigned32:(1 << FRC) -compute:FRS:FRS:: +scratch:FRS:FRS:: cache:FRS:frS:unsigned64 *:(cpu_registers(processor)->fpr + FRS) cache:FRS:FRS_BITMASK:unsigned32:(1 << FRS) -compute:FRT:FRT:: +scratch:FRT:FRT:: cache:FRT:frT:unsigned64 *:(cpu_registers(processor)->fpr + FRT) cache:FRT:FRT_BITMASK:unsigned32:(1 << FRT) cache:SI:EXTS_SI:unsigned_word:((signed_word)(signed16)instruction) -compute:BI:BI:: +scratch:BI:BI:: cache:BI:BIT32_BI::BIT32(BI) cache:BF:BF:: cache:BF:BF_BITMASK:unsigned32:(1 << BF) -compute:BA:BA:: +scratch:BA:BA:: cache:BA:BIT32_BA::BIT32(BA) cache:BA:BA_BITMASK:unsigned32:(1 << BA) -compute:BB:BB:: +scratch:BB:BB:: cache:BB:BIT32_BB::BIT32(BB) cache:BB:BB_BITMASK:unsigned32:(1 << BB) cache:BT:BT:: @@ -61,3 +62,4 @@ cache:BD:EXTS_BD_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~3) cache:LI:EXTS_LI_0b00:unsigned_word:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3) cache:D:EXTS_D:unsigned_word:((signed_word)(signed16)(instruction)) cache:DS:EXTS_DS_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~0x3) +#compute:SPR:SPR_is_256:int:(SPR == 256) diff --git a/sim/ppc/ppc-instructions b/sim/ppc/ppc-instructions index be626555670..54df704472f 100644 --- a/sim/ppc/ppc-instructions +++ b/sim/ppc/ppc-instructions @@ -1109,18 +1109,14 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 int rbit = 0; int xbit = 0; int sign = EXTRACTED64(frb, 0, 0); - enum { start, finish, Infinity_Operand, SNaN_Operand, QNaN_Operand, Large_Operand, Done } label = start; - while (label != finish) switch (label) { - case finish: - error("Unhandled switch\n"); - case start: + /***/ if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0) - { label = Infinity_Operand; break; } + GOTO(Infinity_Operand); if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0) - { label = SNaN_Operand; break; } + GOTO(SNaN_Operand); if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1) - { label = QNaN_Operand; break; } - if (EXTRACTED64(frb, 1, 11) > 1086) { label = Large_Operand; break; } + GOTO(QNaN_Operand); + if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand); if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023; if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022; if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */ @@ -1148,25 +1144,25 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 } if (tgt_precision == 32 /* can ignore frac64 in compare */ && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/) - { label = Large_Operand; break; } + GOTO(Large_Operand); if (tgt_precision == 64 /* can ignore frac64 in compare */ && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/) - { label = Large_Operand; break; } + GOTO(Large_Operand); if (tgt_precision == 32 /* can ignore frac64 in compare */ && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/) - { label = Large_Operand; break; } + GOTO(Large_Operand); if (tgt_precision == 64 /* can ignore frac64 in compare */ && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/) - { label = Large_Operand; break; } + GOTO(Large_Operand); FPSCR_SET_XX(FPSCR & fpscr_fi); if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64; if (tgt_precision == 64) *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64; /*FPSCR[fprf] = undefined */ - { label = Done; break; } + GOTO(Done); /**/ - case Infinity_Operand: + LABEL(Infinity_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); @@ -1181,9 +1177,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 } /* FPSCR[FPRF] = undefined */ } - { label = Done; break; } + GOTO(Done); /**/ - case SNaN_Operand: + LABEL(SNaN_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi); @@ -1192,9 +1188,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/ /* FPSCR[fprf] = undefined */ } - { label = Done; break; } + GOTO(Done); /**/ - case QNaN_Operand: + LABEL(QNaN_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); @@ -1203,9 +1199,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/ /* FPSCR[fprf] = undefined */ } - { label = Done; break; } + GOTO(Done); /**/ - case Large_Operand: + LABEL(Large_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_OR_VX(fpscr_vxcvi); @@ -1221,9 +1217,7 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 /* FPSCR[fprf] = undefined */ } /**/ - case Done: - { label = finish; break; } - } + LABEL(Done): # extract out raw fields of a FP number @@ -2126,8 +2120,40 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, # 0.46,6.RT,11.RA,16.D:D:::Load Multiple Word + unsigned_word EA; + unsigned_word b; + int r; + if (RA == 0) b = 0; + else b = *rA; + EA = b + EXTS(D); + r = RT; + if (RA >= r) + program_interrupt(processor, cia, + illegal_instruction_program_interrupt); + if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0)) + alignment_interrupt(processor, cia, EA); + while (r <= 31) { + GPR(r) = MEM(unsigned, EA, 4); + r = r + 1; + EA = EA + 4; + } 0.47,6.RS,11.RA,16.D:D:::Store Multiple Word + unsigned_word EA; + unsigned_word b; + int r; + if (RA == 0) b = 0; + else b = *rA; + EA = b + EXTS(D); + if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT + || (EA % 4 != 0)) + alignment_interrupt(processor, cia, EA); + r = RS; + while (r <= 31) { + STORE(EA, 4, GPR(r)); + r = r + 1; + EA = EA + 4; + } # @@ -2135,12 +2161,116 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, # 0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate +# unsigned_word EA; +# int n; +# int r; +# int i; +# int nr; +# if (RA == 0) EA = 0; +# else EA = *rA; +# if (NB == 0) n = 32; +# else n = NB; +# r = RT - 1; +# i = 32; +# nr = (n + 3) / 4; +# if ((RT + nr >= 32) +# ? (RA >= RT && RA < RT + nr) +# : (RA >= RT || RA < (RT + nr) % 32)) +# program_interrupt(processor, cia, +# illegal_instruction_program_interrupt); +# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT) +# alignment_interrupt(processor, cia, EA); +# while (n > 0) { +# if (i == 32) { +# r = (r + 1) % 32; +# GPR(r) = 0; +# } +# GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7); +# if (i == 64) i = 32; +# EA = EA + 1; +# n = n - 1; +# } 0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed +# unsigned_word EA; +# unsigned_word b; +# int n; +# int r; +# int i; +# int nr; +# if (RA == 0) b = 0; +# else b = *rA; +# EA = b + *rB; +# n = EXTRACTED32(XER, 25, 31); +# r = RT - 1; +# i = 32; +# nr = (n + 3) / 4; +# if (((RT + n >= 32) +# ? ((RA >= RT && RA < RT + n) +# || (RB >= RT && RB < RT + n)) +# : ((RA >= RT || RA < (RT + n) % 32) +# || (RB >= RT || RB < (RT + n) % 32))) +# || (RT == RA || RT == RB)) +# program_interrupt(processor, cia, +# illegal_instruction_program_interrupt); +# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT) +# alignment_interrupt(processor, cia, EA); +# while (n > 0) { +# if (i == 32) { +# r = (r + 1) % 32; +# GPR(i) = 0; +# } +# GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7); +# i = i + 8; +# if (i == 64) i = 32; +# EA = EA + 1; +# n = n - 1; +# } 0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate +# unsigned_word EA; +# int n; +# int r; +# int i; +# if (RA == 0) EA = 0; +# else EA = *rA; +# if (NB == 0) n = 32; +# else n = NB; +# r = RS - 1; +# i = 32; +# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT) +# alignment_interrupt(processor, cia, EA); +# while (n > 0) { +# if (i == 32) r = (r + 1) % 32; +# STORE(EA, 1, EXTRACTED(GPR(r), i, i+7)); +# i = i + 8; +# if (i == 64) i = 32; +# EA = EA + 1; +# n = n - 1; +# } 0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed +# unsigned_word EA; +# unsigned_word b; +# int n; +# int r; +# int i; +# if (RA == 0) b = 0; +# else b = *rA; +# EA = b + *rB; +# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT) +# alignment_interrupt(processor, cia, EA); +# n = EXTRACTED32(XER, 25, 31); +# r = RS - 1; +# i = 32; +# while (n > 0) { +# if (i == 32) r = (r + 1) % 32; +# STORE(EA, 1, EXTRACTED(GPR(r), i, i+7)); +# i = i + 8; +# if (i == 64) i = 32; +# EA = EA + 1; +# n = n - 1; +# } # @@ -2944,12 +3074,12 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, # CR0_COMPARE(result, 0, Rc); 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask -# long n = MASKED(*rB, 59, 63); -# unsigned32 r = ROTL32(*rS, n); -# unsigned32 m = MASK(MB+32, ME+32); -# signed_word result = r & m; -# *rA = result; -# CR0_COMPARE(result, 0, Rc); + long n = MASKED(*rB, 59, 63); + unsigned32 r = ROTL32(*rS, n); + unsigned32 m = MASK(MB+32, ME+32); + signed_word result = r & m; + *rA = result; + CR0_COMPARE(result, 0, Rc); 0.30,6.RS,11.RA,16.sh_0_4,21.mb,27.3,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Mask Insert # long n = (sh_5 << 4) | sh_0_4; @@ -3124,8 +3254,23 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, program_interrupt(processor, cia, illegal_instruction_program_interrupt); else { - /* HACK - some SPR's need to get their value extracted specially */ - *rT = SPREG(n); + /* HACK - time base registers need to be calculated */ + if (WITH_TIME_BASE) { + switch (n) { + case spr_dec: + *rT = cpu_get_decrementer(processor); + break; + case spr_tbu: + case spr_tbl: + /* NOTE - these SPR's are not readable. Use mftb[ul] */ + default: + *rT = SPREG(n); + break; + } + } + else { + *rT = SPREG(n); + } } PPC_INSN_FROM_SPR(RT_BITMASK, n); @@ -3149,6 +3294,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, PPC_INSN_MTCR(RS_BITMASK, FXM); 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER +# CR_SET(BF, EXTRACTED32(XER, 0, 3)); +# MBLIT32(XER, 0, 3, 0); 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -4010,32 +4157,29 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, int sign; int exp; unsigned64 frac_grx; - enum { start, finish, Disabled_Exponent_Underflow, Enabled_Exponent_Underflow, Disabled_Exponent_Overflow, Enabled_Exponent_Overflow, Normal_Operand, Zero_Operand, Infinity_Operand, QNaN_Operand, SNaN_Operand, Enabled_Overflow, Done } label = start; - while (label != finish) switch (label) { - case finish: - error("Unhandled switch\n"); - case start: + /***/ /* split off cases for what to do */ if (EXTRACTED64(*frB, 1, 11) < 897 && EXTRACTED64(*frB, 1, 63) > 0) { - if ((FPSCR & fpscr_ue) == 0) { label = Disabled_Exponent_Underflow; break; } - if ((FPSCR & fpscr_ue) != 0) { label = Enabled_Exponent_Underflow; break; } + if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow); + if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow); } if (EXTRACTED64(*frB, 1, 11) > 1150 && EXTRACTED64(*frB, 1, 11) < 2047) { - if ((FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; } - if ((FPSCR & fpscr_oe) != 0) { label = Enabled_Exponent_Overflow; break; } + if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow); + if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow); } if (EXTRACTED64(*frB, 1, 11) > 896 - && EXTRACTED64(*frB, 1, 11) < 1151) { label = Normal_Operand; break; } - if (EXTRACTED64(*frB, 1, 63) == 0) { label = Zero_Operand; break; } + && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand); + if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand); if (EXTRACTED64(*frB, 1, 11) == 2047) { - if (EXTRACTED64(*frB, 12, 63) == 0) { label = Infinity_Operand; break; } - if (EXTRACTED64(*frB, 12, 12) == 1) { label = QNaN_Operand; break; } + if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand); + if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand); if (EXTRACTED64(*frB, 12, 12) == 0 - && EXTRACTED64(*frB, 13, 63) > 0) { label = SNaN_Operand; break; } + && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand); } - case Disabled_Exponent_Underflow: + /**/ + LABEL(Disabled_Exponent_Underflow): sign = EXTRACTED64(*frB, 0, 0); if (EXTRACTED64(*frB, 1, 11) == 0) { exp = -1022; @@ -4077,8 +4221,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); } - { label = Done; break; } - case Enabled_Exponent_Underflow: + GOTO(Done); + /**/ + LABEL(Enabled_Exponent_Underflow): FPSCR_SET_UX(1); sign = EXTRACTED64(*frB, 0, 0); if (EXTRACTED64(*frB, 1, 11) == 0) { @@ -4103,8 +4248,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); - { label = Done; break; } - case Disabled_Exponent_Overflow: + GOTO(Done); + /**/ + LABEL(Disabled_Exponent_Overflow): FPSCR_SET_OX(1); if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) { if (EXTRACTED64(*frB, 0, 0) == 0) { @@ -4149,14 +4295,16 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, /* FPSCR[FR] <- undefined */ FPSCR_SET_FI(1); FPSCR_SET_XX(1); - { label = Done; break; } - case Enabled_Exponent_Overflow: + GOTO(Done); + /**/ + LABEL(Enabled_Exponent_Overflow): sign = EXTRACTED64(*frB, 0, 0); exp = EXTRACTED64(*frB, 1, 11) - 1023; frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52); Round_Single(processor, sign, &exp, &frac_grx); FPSCR_SET_XX(FPSCR & fpscr_fi); - case Enabled_Overflow: + /**/ + LABEL(Enabled_Overflow): FPSCR_SET_OX(1); exp = exp - 192; *frT = (INSERTED64(sign, 0, 0) @@ -4164,28 +4312,32 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); - { label = Done; break; } - case Zero_Operand: + GOTO(Done); + /**/ + LABEL(Zero_Operand): *frT = *frB; if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero); if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero); FPSCR_SET_FR(0); FPSCR_SET_FI(0); - { label = Done; break; } - case Infinity_Operand: + GOTO(Done); + /**/ + LABEL(Infinity_Operand): *frT = *frB; if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity); if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity); FPSCR_SET_FR(0); FPSCR_SET_FI(0); - { label = Done; break; } - case QNaN_Operand: + GOTO(Done); + /**/ + LABEL(QNaN_Operand): *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34); FPSCR_SET_FPRF(fpscr_rf_quiet_nan); FPSCR_SET_FR(0); FPSCR_SET_FI(0); - { label = Done; break; } - case SNaN_Operand: + GOTO(Done); + /**/ + LABEL(SNaN_Operand): FPSCR_OR_VX(fpscr_vxsnan); if ((FPSCR & fpscr_ve) == 0) { *frT = (MASKED64(*frB, 0, 11) @@ -4195,31 +4347,35 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, } FPSCR_SET_FR(0); FPSCR_SET_FI(0); - { label = Done; break; } - case Normal_Operand: + GOTO(Done); + /**/ + LABEL(Normal_Operand): sign = EXTRACTED64(*frB, 0, 0); exp = EXTRACTED64(*frB, 1, 11) - 1023; frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52); Round_Single(processor, sign, &exp, &frac_grx); FPSCR_SET_XX(FPSCR & fpscr_fi); - if (exp > 127 && (FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; } - if (exp > 127 && (FPSCR & fpscr_oe) != 0) { label = Enabled_Overflow; break; } + if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow); + if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow); *frT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63)); if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number); if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number); - { label = Done; break; } - case Done: + GOTO(Done); + /**/ + LABEL(Done): PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc); - { label = finish; break; } - } + 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword + floating_point_assist_interrupt(processor, cia); 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero + floating_point_assist_interrupt(processor, cia); 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word + floating_point_assist_interrupt(processor, cia); 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0 @@ -4237,12 +4393,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, int sign = EXTRACTED64(*frB, 0, 0); int exp = 63; unsigned64 frac = *frB; - enum { start, finish, Zero_Operand, Done } label = start; - while (label != finish) switch (label) { - case finish: - error("Unhandled switch\n"); - case start: - if (frac == 0) { label = Zero_Operand; break; } + /***/ + if (frac == 0) GOTO(Zero_Operand); if (sign == 1) frac = ~frac + 1; while (EXTRACTED64(frac, 0, 0) == 0) { /*??? do the loop 0 times if (FRB) = max negative integer */ @@ -4255,19 +4407,18 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *frT = (INSERTED64(sign, 0, 0) | INSERTED64(exp + 1023, 1, 11) | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63)); - { label = Done; break; } + GOTO(Done); /**/ - case Zero_Operand: + LABEL(Zero_Operand): FPSCR_SET_FR(0); FPSCR_SET_FI(0); FPSCR_SET_FPRF(fpscr_rf_pos_zero); *frT = 0; - { label = Done; break; } + GOTO(Done); /**/ - case Done: + LABEL(Done): PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc); - { label = finish; break; } - } + # # I.4.6.7 Floating-Point Compare Instructions @@ -4329,41 +4480,115 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, # 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR + floating_point_assist_interrupt(processor, cia); +# FPSCR_BEGIN; +# *frT = FPSCR; +# FPSCR_END(Rc); 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR + floating_point_assist_interrupt(processor, cia); +# FPSCR_BEGIN; +# unsigned field = FPSCR_FIELD(BFA); +# CR_SET(BF, field); +# switch (BFA) { +# case 0: +# FPSCR &= ~(fpscr_fx | fpscr_ox); +# break; +# case 1: +# FPSCR &= ~(fpscr_ux | fpscr_zx | fpscr_xx | fpscr_vxsnan); +# break; +# case 2: +# FPSCR &= ~(fpscr_vxisi | fpscr_vxidi | fpscr_vxzdz | fpscr_vximz); +# break; +# case 3: +# FPSCR &= ~(fpscr_vxvc); +# break; +# case 5: +# FPSCR &= ~(fpscr_vxsoft | fpscr_vxsqrt | fpscr_vxcvi); +# break; +# } +# FPSCR_END(0); 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate + floating_point_assist_interrupt(processor, cia); +# FPSCR_BEGIN; +# FPSCR_SET(BF, U); +# /* FIXME - what about the effect this has on exception bits */ +# FPSCR_END(Rc); 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields + FPSCR_BEGIN; + int i; + for (i = 0; i < 8; i++) { + if ((FLM & BIT8(i))) { + FPSCR &= ~MASK32(i*4, i*4+3); + FPSCR |= MASKED32(*frB, i*4, i*4+3); + } + } + FPSCR_END(Rc); 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0 + floating_point_assist_interrupt(processor, cia); +# FPSCR_BEGIN; +# unsigned32 mask = ~BIT32(BT) | (fpscr_fex | fpscr_vx); +# FPSCR &= mask; +# /* FIXME - what about the effect this has on exception bits */ +# FPSCR_END(Rc); 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1 + floating_point_assist_interrupt(processor, cia); +# FPSCR_BEGIN; +# unsigned32 bit = BIT32(BT) & ~(fpscr_fex | fpscr_vx); +# FPSCR |= bit; +# /* FIXME - need to take care of when and why FX is set */ +# /* FIXME - if FX (or another exception bit is set) shall +# an exception occure */ +# /* FPSCR |= fpscr_fx; */ +# /* FIXME - what about the effect this has on exception bits */ +# FPSCR_END(Rc); # # I.A.1.1 Floating-Point Store Instruction # -0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed +0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed + program_interrupt(processor, cia, optional_instruction_program_interrupt); # # I.A.1.2 Floating-Point Arithmetic Instructions # -0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root +0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root + program_interrupt(processor, cia, optional_instruction_program_interrupt); -0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single +0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single + program_interrupt(processor, cia, optional_instruction_program_interrupt); -0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single +0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single + program_interrupt(processor, cia, optional_instruction_program_interrupt); -0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate +0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate + program_interrupt(processor, cia, optional_instruction_program_interrupt); # # I.A.1.3 Floating-Point Select Instruction # -0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select - +0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select +*601: PPC_UNIT_BAD, PPC_UNIT_BAD, 0, 0, 0 +*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 +*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 +*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0 + if (CURRENT_MODEL == MODEL_ppc601) { + program_interrupt(processor, cia, optional_instruction_program_interrupt); + } else { + unsigned64 zero = 0; + FPSCR_BEGIN; + if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB; + else *frT = *frC; + FPSCR_END(Rc); + PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc); + } # # II.3.2 Cache Management Instructions @@ -4385,7 +4610,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0 - cpu_synchronize_context(processor); + cpu_synchronize_context(processor, cia); PPC_INSN_INT(0, 0, 0); @@ -4481,7 +4706,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, | MASKED(SRR1, 37, 41) | MASKED(SRR1, 48, 63)); NIA = MASKED(SRR0, 0, 61); - cpu_synchronize_context(processor); + cpu_synchronize_context(processor, cia); check_masked_interrupts(processor); } diff --git a/sim/ppc/ppc-opcode-complex b/sim/ppc/ppc-opcode-complex index 333c6ae8474..78fac6a514b 100644 --- a/sim/ppc/ppc-opcode-complex +++ b/sim/ppc/ppc-opcode-complex @@ -22,6 +22,6 @@ array,normal: 21:31:32:-1:OE,LR,AA,Rc,LK: array,expand-forced: 6: 9: 6: 9:BO: 0xfc000000:0x40000000 array,boolean: 11:15:11:15:0RA: 0xfc000000:0x38000000:0 array,boolean: 11:15:11:15:RA: 0xfc000000:0x3c000000:0 -# BLR instruction - LR=8 is munged into 0x100 -array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:0x100 -array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:0x100 +# BLR instruction - LR=8 is munged into 0x100 == 256 +array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:256 +array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:256 diff --git a/sim/ppc/psim.c b/sim/ppc/psim.c index 0c7024e50cd..c2d3a6067b4 100644 --- a/sim/ppc/psim.c +++ b/sim/ppc/psim.c @@ -26,6 +26,7 @@ #include "idecode.h" #include "options.h" +#include "tree.h" #include #include @@ -78,6 +79,7 @@ int current_environment; int current_alignment; int current_floating_point; int current_model_issue = MODEL_ISSUE_IGNORE; +int current_stdio = DO_USE_STDIO; model_enum current_model = WITH_DEFAULT_MODEL; @@ -87,16 +89,16 @@ INLINE_PSIM\ (device *) psim_tree(void) { - device *root = device_tree_add_parsed(NULL, "core"); - device_tree_add_parsed(root, "/aliases"); - device_tree_add_parsed(root, "/options"); - device_tree_add_parsed(root, "/chosen"); - device_tree_add_parsed(root, "/packages"); - device_tree_add_parsed(root, "/cpus"); - device_tree_add_parsed(root, "/openprom"); - device_tree_add_parsed(root, "/openprom/init"); - device_tree_add_parsed(root, "/openprom/trace"); - device_tree_add_parsed(root, "/openprom/options"); + device *root = tree_parse(NULL, "core"); + tree_parse(root, "/aliases"); + tree_parse(root, "/options"); + tree_parse(root, "/chosen"); + tree_parse(root, "/packages"); + tree_parse(root, "/cpus"); + tree_parse(root, "/openprom"); + tree_parse(root, "/openprom/init"); + tree_parse(root, "/openprom/trace"); + tree_parse(root, "/openprom/options"); return root; } @@ -122,55 +124,74 @@ psim_usage(int verbose) printf_filtered("\n"); printf_filtered("Where\n"); printf_filtered("\n"); - printf_filtered("\t Name of the PowerPC program to run.\n"); + printf_filtered("\t Name of the PowerPC program to run.\n"); if (verbose) { - printf_filtered("\t This can either be a PowerPC binary or\n"); - printf_filtered("\t a text file containing a device tree\n"); - printf_filtered("\t specification.\n"); - printf_filtered("\t PSIM will attempt to determine from the\n"); - printf_filtered("\t specified the intended emulation\n"); - printf_filtered("\t environment.\n"); - printf_filtered("\t If PSIM gets it wrong, the emulation\n"); - printf_filtered("\t environment can be specified using the\n"); - printf_filtered("\t `-e' option (described below).\n"); + printf_filtered("\t This can either be a PowerPC binary or\n"); + printf_filtered("\t a text file containing a device tree\n"); + printf_filtered("\t specification.\n"); + printf_filtered("\t PSIM will attempt to determine from the\n"); + printf_filtered("\t specified the intended emulation\n"); + printf_filtered("\t environment.\n"); + printf_filtered("\t If PSIM gets it wrong, the emulation\n"); + printf_filtered("\t environment can be specified using the\n"); + printf_filtered("\t `-e' option (described below).\n"); printf_filtered("\n"); } - printf_filtered("\t Argument to be passed to \n"); + printf_filtered("\t Argument to be passed to \n"); if (verbose) { - printf_filtered("\t These arguments will be passed to\n"); - printf_filtered("\t (as standard C argv, argc)\n"); - printf_filtered("\t when is started.\n"); + printf_filtered("\t These arguments will be passed to\n"); + printf_filtered("\t (as standard C argv, argc)\n"); + printf_filtered("\t when is started.\n"); printf_filtered("\n"); } - printf_filtered("\t See below\n"); + printf_filtered("\t See below\n"); printf_filtered("\n"); printf_filtered("The following are valid s:\n"); printf_filtered("\n"); - printf_filtered("\t-m Specify the processor to model (604)\n"); - if (verbose) { - printf_filtered("\t Selects the processor to use when\n"); - printf_filtered("\t modeling execution units. Includes:\n"); - printf_filtered("\t 604, 603 and 603e\n"); - printf_filtered("\n"); } - printf_filtered("\t-e specify an OS or platform to model\n"); + + printf_filtered("\t-i Print instruction counting statistics\n"); + if (verbose) { printf_filtered("\n"); } + + printf_filtered("\t-I Print execution unit statistics\n"); + if (verbose) { printf_filtered("\n"); } + + printf_filtered("\t-e specify an OS or platform to model\n"); if (verbose) { - printf_filtered("\t Can be any of the following:\n"); - printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n"); - printf_filtered("\t netbsd - UEA + NetBSD system calls\n"); - printf_filtered("\t solaris - UEA + Solaris system calls\n"); - printf_filtered("\t linux - UEA + Linux system calls\n"); - printf_filtered("\t chirp - OEA + a few OpenBoot calls\n"); + printf_filtered("\t Can be any of the following:\n"); + printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n"); + printf_filtered("\t netbsd - UEA + NetBSD system calls\n"); + printf_filtered("\t solaris - UEA + Solaris system calls\n"); + printf_filtered("\t linux - UEA + Linux system calls\n"); + printf_filtered("\t chirp - OEA + a few OpenBoot calls\n"); printf_filtered("\n"); } - printf_filtered("\t-i Print instruction counting statistics\n"); - if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-I Print execution unit statistics\n"); + + printf_filtered("\t-f Merge into the device tree\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-r Set RAM size in bytes (OEA environments)\n"); + + printf_filtered("\t-h -? -H give more detailed usage\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-t [!] Enable (disable) option\n"); + + printf_filtered("\t-m Specify the processor to model (604)\n"); + if (verbose) { + printf_filtered("\t Selects the processor to use when\n"); + printf_filtered("\t modeling execution units. Includes:\n"); + printf_filtered("\t 604, 603 and 603e\n"); + printf_filtered("\n"); } + + printf_filtered("\t-n Specify the number of processors in SMP simulations\n"); + if (verbose) { + printf_filtered("\t Specifies the number of processors that are\n"); + printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n"); + printf_filtered("\t simulation\n"); + printf_filtered("\n"); } + + printf_filtered("\t-o Add device to the device tree\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-o add device to the device tree\n"); + + printf_filtered("\t-r Set RAM size in bytes (OEA environments)\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-h -? -H give more detailed usage\n"); + + printf_filtered("\t-t [!] Enable (disable) option\n"); if (verbose) { printf_filtered("\n"); } + printf_filtered("\n"); trace_usage(verbose); device_usage(verbose); @@ -202,7 +223,11 @@ psim_options(device *root, break; case 'e': param = find_arg("Missing option for -e\n", &argp, argv); - device_tree_add_parsed(root, "/openprom/options/os-emul %s", param); + tree_parse(root, "/openprom/options/os-emul %s", param); + break; + case 'f': + param = find_arg("Missing option for -f\n", &argp, argv); + psim_merge_device_file(root, param); break; case 'h': case '?': @@ -212,45 +237,81 @@ psim_options(device *root, psim_usage(2); break; case 'i': - device_tree_add_parsed(root, "/openprom/trace/print-info 1"); + tree_parse(root, "/openprom/trace/print-info 1"); break; case 'I': - device_tree_add_parsed(root, "/openprom/trace/print-info 2"); - device_tree_add_parsed(root, "/openprom/options/model-issue %d", - MODEL_ISSUE_PROCESS); + tree_parse(root, "/openprom/trace/print-info 2"); + tree_parse(root, "/openprom/options/model-issue %d", + MODEL_ISSUE_PROCESS); break; case 'm': param = find_arg("Missing option for -m\n", &argp, argv); - device_tree_add_parsed(root, "/openprom/options/model \"%s", param); + tree_parse(root, "/openprom/options/model \"%s", param); + break; + case 'n': + param = find_arg("Missing option for -n\n", &argp, argv); + tree_parse(root, "/openprom/options/smp %s", param); break; case 'o': - param = find_arg("Missing option for -o\n", &argp, argv); - current = device_tree_add_parsed(current, "%s", param); + param = find_arg("Missing option for -o\n", &argp, argv); + current = tree_parse(current, "%s", param); break; case 'r': param = find_arg("Missing option for -r\n", &argp, argv); - device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx", - atol(param)); + tree_parse(root, "/openprom/options/oea-memory-size %s", + param); break; case 't': param = find_arg("Missing option for -t\n", &argp, argv); if (param[0] == '!') - device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1); + tree_parse(root, "/openprom/trace/%s 0", param+1); else - device_tree_add_parsed(root, "/openprom/trace/%s 1", param); + tree_parse(root, "/openprom/trace/%s 1", param); break; } p += 1; } argp += 1; } - /* force the trace node to (re)process its options */ - device_ioctl(device_tree_find_device(root, "/openprom/trace"), NULL, 0); + /* force the trace node to process its options now *before* the tree + initialization occures */ + device_ioctl(tree_find_device(root, "/openprom/trace"), + NULL, 0, + device_ioctl_set_trace); /* return where the options end */ return argv + argp; } +INLINE_PSIM\ +(void) +psim_command(device *root, + char **argv) +{ + int argp = 0; + if (argv[argp] == NULL) { + return; + } + else if (strcmp(argv[argp], "trace") == 0) { + const char *opt = find_arg("Missing option", &argp, argv); + if (opt[0] == '!') + trace_option(opt + 1, 0); + else + trace_option(opt, 1); + } + else if (strcmp(*argv, "change-media") == 0) { + char *device = find_arg("Missing device name", &argp, argv); + char *media = argv[++argp]; + device_ioctl(tree_find_device(root, device), NULL, 0, + device_ioctl_change_media, media); + } + else { + printf_filtered("Unknown PSIM command %s, try\n", argv[argp]); + printf_filtered(" trace \n"); + printf_filtered(" change-media [ ]\n"); + } +} + /* create the simulator proper from the device tree and executable */ @@ -274,13 +335,13 @@ psim_create(const char *file_name, error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name); /* fill in the missing real number of CPU's */ - nr_cpus = device_find_integer_property(root, "/openprom/options/smp"); + nr_cpus = tree_find_integer_property(root, "/openprom/options/smp"); if (MAX_NR_PROCESSORS < nr_cpus) error("target and configured number of cpus conflict\n"); /* fill in the missing TARGET BYTE ORDER information */ current_target_byte_order - = (device_find_boolean_property(root, "/options/little-endian?") + = (tree_find_boolean_property(root, "/options/little-endian?") ? LITTLE_ENDIAN : BIG_ENDIAN); if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order) @@ -295,7 +356,7 @@ psim_create(const char *file_name, error("host and configured byte order conflict\n"); /* fill in the missing OEA/VEA information */ - env = device_find_string_property(root, "/openprom/options/env"); + env = tree_find_string_property(root, "/openprom/options/env"); current_environment = ((strcmp(env, "user") == 0 || strcmp(env, "uea") == 0) ? USER_ENVIRONMENT @@ -313,7 +374,7 @@ psim_create(const char *file_name, /* fill in the missing ALLIGNMENT information */ current_alignment - = (device_find_boolean_property(root, "/openprom/options/strict-alignment?") + = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?") ? STRICT_ALIGNMENT : NONSTRICT_ALIGNMENT); if (CURRENT_ALIGNMENT != current_alignment) @@ -321,15 +382,23 @@ psim_create(const char *file_name, /* fill in the missing FLOATING POINT information */ current_floating_point - = (device_find_boolean_property(root, "/openprom/options/floating-point?") + = (tree_find_boolean_property(root, "/openprom/options/floating-point?") ? HARD_FLOATING_POINT : SOFT_FLOATING_POINT); if (CURRENT_FLOATING_POINT != current_floating_point) error("target and configured floating-point conflict\n"); + /* fill in the missing STDIO information */ + current_stdio + = (tree_find_boolean_property(root, "/openprom/options/use-stdio?") + ? DO_USE_STDIO + : DONT_USE_STDIO); + if (CURRENT_STDIO != current_stdio) + error("target and configured stdio interface conflict\n"); + /* sort out the level of detail for issue modeling */ current_model_issue - = device_find_integer_property(root, "/openprom/options/model-issue"); + = tree_find_integer_property(root, "/openprom/options/model-issue"); if (CURRENT_MODEL_ISSUE != current_model_issue) error("target and configured model-issue conflict\n"); @@ -341,7 +410,7 @@ psim_create(const char *file_name, ihandle into the corresponding cpu's phandle and then querying the "name" property, the cpu type can be determined. Ok? */ - model_set(device_find_string_property(root, "/openprom/options/model")); + model_set(tree_find_string_property(root, "/openprom/options/model")); /* create things */ system = ZALLOC(psim); @@ -364,7 +433,7 @@ psim_create(const char *file_name, /* dump out the contents of the device tree */ if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree]) - device_tree_traverse(root, device_tree_print_device, NULL, NULL); + tree_print(root); if (ppc_trace[trace_dump_device_tree]) error(""); @@ -419,6 +488,7 @@ psim_halt(psim *system, longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1); } + INLINE_PSIM\ (int) psim_last_cpu(psim *system) @@ -458,7 +528,7 @@ INLINE_PSIM\ psim_device(psim *system, const char *path) { - return device_tree_find_device(system->devices, path); + return tree_find_device(system->devices, path); } INLINE_PSIM\ @@ -487,19 +557,20 @@ psim_init(psim *system) cpu_init(system->processors[cpu_nr]); /* init all the devices (which updates the cpus) */ - device_tree_init(system->devices, system); + tree_init(system->devices, system); /* and the emulation (which needs an initialized device tree) */ os_emul_init(system->os_emulation, system->nr_cpus); /* now sync each cpu against the initialized state of its registers */ for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) { - cpu_synchronize_context(system->processors[cpu_nr]); - cpu_page_tlb_invalidate_all(system->processors[cpu_nr]); + cpu *processor = system->processors[cpu_nr]; + cpu_synchronize_context(processor, cpu_get_program_counter(processor)); + cpu_page_tlb_invalidate_all(processor); } - /* force loop to restart */ - system->last_cpu = -1; /* when incremented will become 0 - first CPU */ + /* force loop to start with first cpu (after processing events) */ + system->last_cpu = system->nr_cpus - 1; } INLINE_PSIM\ @@ -510,14 +581,15 @@ psim_stack(psim *system, { /* pass the stack device the argv/envp and let it work out what to do with it */ - device *stack_device = device_tree_find_device(system->devices, - "/openprom/init/stack"); + device *stack_device = tree_find_device(system->devices, + "/openprom/init/stack"); if (stack_device != (device*)0) { unsigned_word stack_pointer; psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer); device_ioctl(stack_device, NULL, /*cpu*/ 0, /*cia*/ + device_ioctl_create_stack, stack_pointer, argv, envp); @@ -778,7 +850,8 @@ psim_read_memory(psim *system, error("psim_read_memory() invalid cpu\n"); processor = system->processors[which_cpu]; return vm_data_map_read_buffer(cpu_data_map(processor), - buffer, vaddr, nr_bytes); + buffer, vaddr, nr_bytes, + NULL, -1); } @@ -798,7 +871,8 @@ psim_write_memory(psim *system, error("psim_read_memory() invalid cpu\n"); processor = system->processors[which_cpu]; return vm_data_map_write_buffer(cpu_data_map(processor), - buffer, vaddr, nr_bytes, 1); + buffer, vaddr, nr_bytes, 1/*violate-read-only*/, + NULL, -1); } @@ -818,20 +892,61 @@ INLINE_PSIM\ psim_merge_device_file(device *root, const char *file_name) { - FILE *description = fopen(file_name, "r"); - int line_nr = 0; + FILE *description; + int line_nr; char device_path[1000]; - device *current = root; + device *current; + + /* try opening the file */ + description = fopen(file_name, "r"); + if (description == NULL) { + perror(file_name); + error("Invalid file %s specified", file_name); + } + + line_nr = 0; + current = root; while (fgets(device_path, sizeof(device_path), description)) { - /* check all of line was read */ + char *device; + /* check that the full line was read */ if (strchr(device_path, '\n') == NULL) { fclose(description); - error("create_filed_device_tree() line %d to long: %s\n", - line_nr, device_path); + error("%s:%d: line to long - %s", + file_name, line_nr, device_path); } + else + *strchr(device_path, '\n') = '\0'; line_nr++; + /* skip comments ("#" or ";") and blank lines lines */ + for (device = device_path; + *device != '\0' && isspace(*device); + device++); + if (device[0] == '#' + || device[0] == ';' + || device[0] == '\0') + continue; + /* merge any appended lines */ + while (device_path[strlen(device_path) - 1] == '\\') { + int curlen = strlen(device_path) - 1; + /* zap \ */ + device_path[curlen] = '\0'; + /* append the next line */ + if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) { + fclose(description); + error("%s:%s: unexpected eof in line continuation - %s", + file_name, line_nr, device_path); + } + if (strchr(device_path, '\n') == NULL) { + fclose(description); + error("%s:%d: line to long - %s", + file_name, line_nr, device_path); + } + else + *strchr(device_path, '\n') = '\0'; + line_nr++; + } /* parse this line */ - current = device_tree_add_parsed(current, "%s", device_path); + current = tree_parse(current, "%s", device); } fclose(description); } diff --git a/sim/ppc/sim_calls.c b/sim/ppc/sim_calls.c index e1889f6e98b..35a9212d5d2 100644 --- a/sim/ppc/sim_calls.c +++ b/sim/ppc/sim_calls.c @@ -40,10 +40,9 @@ #endif #endif -#include "../../gdb/defs.h" - -#include "../../gdb/remote-sim.h" -#include "../../gdb/callback.h" +#include "defs.h" +#include "callback.h" +#include "remote-sim.h" /* Structures used by the simulator, for gdb just have static structures */ @@ -280,9 +279,9 @@ sim_do_command (char *cmd) { TRACE(trace_gdb, ("sim_do_commands(cmd=%s) called\n", cmd ? cmd : "(null)")); - if (cmd) { + if (cmd != NULL) { char **argv = buildargv(cmd); - psim_options(root_device, argv); + psim_command(root_device, argv); freeargv(argv); } } @@ -312,6 +311,7 @@ sim_io_read_stdin(char *buf, error("sim_io_read_stdin: unaccounted switch\n"); break; } + return 0; } int @@ -329,6 +329,7 @@ sim_io_write_stdout(const char *buf, error("sim_io_write_stdout: unaccounted switch\n"); break; } + return 0; } int @@ -347,6 +348,7 @@ sim_io_write_stderr(const char *buf, error("sim_io_write_stderr: unaccounted switch\n"); break; } + return 0; } diff --git a/sim/ppc/tree.c b/sim/ppc/tree.c new file mode 100644 index 00000000000..856e90bf9e2 --- /dev/null +++ b/sim/ppc/tree.c @@ -0,0 +1,1273 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _PARSE_C_ +#define _PARSE_C_ + +#include +#include + +#include "basics.h" + +#include "device.h" +#include "tree.h" + + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#include + + +/* manipulate/lookup device names */ + +typedef struct _name_specifier { + /* components in the full length name */ + char *path; + char *property; + char *value; + /* current device */ + char *name; + char *base; + char *unit; + char *args; + /* previous device */ + char *last_name; + char *last_base; + char *last_unit; + char *last_args; + /* work area */ + char buf[1024]; +} name_specifier; + + + +/* Given a device specifier, break it up into its main components: + path (and if present) property name and property value. */ + +STATIC_INLINE_TREE\ +(int) +split_device_specifier(device *current, + const char *device_specifier, + name_specifier *spec) +{ + char *chp = NULL; + + /* expand any leading alias if present */ + if (current != NULL + && *device_specifier != '\0' + && *device_specifier != '.' + && *device_specifier != '/') { + device *aliases = tree_find_device(current, "/aliases"); + char alias[32]; + int len = 0; + while (device_specifier[len] != '\0' + && device_specifier[len] != '/' + && device_specifier[len] != ':' + && !isspace(device_specifier[len])) { + alias[len] = device_specifier[len]; + len++; + if (len >= sizeof(alias)) + error("split_device_specifier: buffer overflow"); + } + alias[len] = '\0'; + if (aliases != NULL + && device_find_property(aliases, alias)) { + strcpy(spec->buf, device_find_string_property(aliases, alias)); + strcat(spec->buf, device_specifier + len); + } + else { + strcpy(spec->buf, device_specifier); + } + } + else { + strcpy(spec->buf, device_specifier); + } + + /* check no overflow */ + if (strlen(spec->buf) >= sizeof(spec->buf)) + error("split_device_specifier: buffer overflow\n"); + + /* strip leading spaces */ + chp = spec->buf; + while (*chp != '\0' && isspace(*chp)) + chp++; + if (*chp == '\0') + return 0; + + /* find the path and terminate it with null */ + spec->path = chp; + while (*chp != '\0' && !isspace(*chp)) + chp++; + if (*chp != '\0') { + *chp = '\0'; + chp++; + } + + /* and any value */ + while (*chp != '\0' && isspace(*chp)) + chp++; + spec->value = chp; + + /* now go back and chop the property off of the path */ + if (spec->value[0] == '\0') { + spec->property = NULL; /*not a property*/ + spec->value = NULL; + } + else if (spec->value[0] == '>' + || spec->value[0] == '<') { + /* an interrupt spec */ + spec->property = NULL; + } + else { + chp = strrchr(spec->path, '/'); + if (chp == NULL) { + spec->property = spec->path; + spec->path = strchr(spec->property, '\0'); + } + else { + *chp = '\0'; + spec->property = chp+1; + } + } + + /* and mark the rest as invalid */ + spec->name = NULL; + spec->base = NULL; + spec->unit = NULL; + spec->args = NULL; + spec->last_name = NULL; + spec->last_base = NULL; + spec->last_unit = NULL; + spec->last_args = NULL; + + return 1; +} + + +/* given a device specifier break it up into its main components - + path and property name - assuming that the last `device' is a + property name. */ + +STATIC_INLINE_DEVICE\ +(int) +split_property_specifier(device *current, + const char *property_specifier, + name_specifier *spec) +{ + if (split_device_specifier(current, property_specifier, spec)) { + if (spec->property == NULL) { + /* force the last name to be a property name */ + char *chp = strrchr(spec->path, '/'); + if (chp == NULL) { + spec->property = spec->path; + spec->path = strrchr(spec->property, '\0');; + } + else { + *chp = '\0'; + spec->property = chp+1; + } + } + return 1; + } + else + return 0; +} + + +/* device the next device name and split it up, return 0 when no more + names to device */ + +STATIC_INLINE_TREE\ +(int) +split_device_name(name_specifier *spec) +{ + char *chp; + /* remember what came before */ + spec->last_name = spec->name; + spec->last_base = spec->base; + spec->last_unit = spec->unit; + spec->last_args = spec->args; + /* finished? */ + if (spec->path[0] == '\0') { + spec->name = NULL; + spec->base = NULL; + spec->unit = NULL; + spec->args = NULL; + return 0; + } + /* break the current device spec from the path */ + spec->name = spec->path; + chp = strchr(spec->name, '/'); + if (chp == NULL) + spec->path = strchr(spec->name, '\0'); + else { + spec->path = chp+1; + *chp = '\0'; + } + /* break out the base */ + if (spec->name[0] == '(') { + chp = strchr(spec->name, ')'); + if (chp == NULL) { + spec->base = spec->name; + } + else { + *chp = '\0'; + spec->base = spec->name + 1; + spec->name = chp + 1; + } + } + else { + spec->base = spec->name; + } + /* now break out the unit */ + chp = strchr(spec->name, '@'); + if (chp == NULL) { + spec->unit = NULL; + chp = spec->name; + } + else { + *chp = '\0'; + chp += 1; + spec->unit = chp; + } + /* finally any args */ + chp = strchr(chp, ':'); + if (chp == NULL) + spec->args = NULL; + else { + *chp = '\0'; + spec->args = chp+1; + } + return 1; +} + + +/* device the value, returning the next non-space token */ + +STATIC_INLINE_TREE\ +(char *) +split_value(name_specifier *spec) +{ + char *token; + if (spec->value == NULL) + return NULL; + /* skip leading white space */ + while (isspace(spec->value[0])) + spec->value++; + if (spec->value[0] == '\0') { + spec->value = NULL; + return NULL; + } + token = spec->value; + /* find trailing space */ + while (spec->value[0] != '\0' && !isspace(spec->value[0])) + spec->value++; + /* chop this value out */ + if (spec->value[0] != '\0') { + spec->value[0] = '\0'; + spec->value++; + } + return token; +} + + + +/* traverse the path specified by spec starting at current */ + +STATIC_INLINE_TREE\ +(device *) +split_find_device(device *current, + name_specifier *spec) +{ + /* strip off (and process) any leading ., .., ./ and / */ + while (1) { + if (strncmp(spec->path, "/", strlen("/")) == 0) { + /* cd /... */ + while (current != NULL && device_parent(current) != NULL) + current = device_parent(current); + spec->path += strlen("/"); + } + else if (strncmp(spec->path, "./", strlen("./")) == 0) { + /* cd ./... */ + current = current; + spec->path += strlen("./"); + } + else if (strncmp(spec->path, "../", strlen("../")) == 0) { + /* cd ../... */ + if (current != NULL && device_parent(current) != NULL) + current = device_parent(current); + spec->path += strlen("../"); + } + else if (strcmp(spec->path, ".") == 0) { + /* cd . */ + current = current; + spec->path += strlen("."); + } + else if (strcmp(spec->path, "..") == 0) { + /* cd . */ + if (current != NULL && device_parent(current) != NULL) + current = device_parent(current); + spec->path += strlen(".."); + } + else + break; + } + + /* now go through the path proper */ + + if (current == NULL) { + split_device_name(spec); + return NULL; + } + + while (split_device_name(spec)) { + device *child; + for (child = device_child(current); + child != NULL; child = device_sibling(child)) { + if (strcmp(spec->name, device_name(child)) == 0) { + if (spec->unit == NULL) + break; + else { + device_unit phys; + device_decode_unit(current, spec->unit, &phys); + if (memcmp(&phys, device_unit_address(child), + sizeof(device_unit)) == 0) + break; + } + } + } + if (child == NULL) + return current; /* search failed */ + current = child; + } + + return current; +} + + +STATIC_INLINE_TREE\ +(device *) +split_fill_path(device *current, + const char *device_specifier, + name_specifier *spec) +{ + /* break it up */ + if (!split_device_specifier(current, device_specifier, spec)) + device_error(current, "error parsing %s\n", device_specifier); + + /* fill our tree with its contents */ + current = split_find_device(current, spec); + + /* add any additional devices as needed */ + if (spec->name != NULL) { + do { + current = device_create(current, spec->base, spec->name, + spec->unit, spec->args); + } while (split_device_name(spec)); + } + + return current; +} + + +INLINE_TREE\ +(void) +tree_init(device *root, + psim *system) +{ + TRACE(trace_device_tree, ("tree_init(root=0x%lx, system=0x%lx)\n", + (long)root, + (long)system)); + /* remove the old, rebuild the new */ + tree_traverse(root, device_clean, NULL, system); + tree_traverse(root, device_init_static_properties, NULL, system); + tree_traverse(root, device_init_address, NULL, system); + tree_traverse(root, device_init_runtime_properties, NULL, system); + tree_traverse(root, device_init_data, NULL, system); +} + + + +/* */ + +STATIC_INLINE_TREE\ +(const char *) +skip_token(const char *chp) +{ + while (!isspace(*chp) && *chp != '\0') + chp++; + while (isspace(*chp) && *chp != '\0') + chp++; + return chp; +} + + +/* count the number of entries */ + +STATIC_INLINE_TREE\ +(int) +count_entries(device *current, + const char *property_name, + const char *property_value, + int modulo) +{ + const char *chp = property_value; + int nr_entries = 0; + while (*chp != '\0') { + nr_entries += 1; + chp = skip_token(chp); + } + if ((nr_entries % modulo) != 0) { + device_error(current, "incorrect number of entries for %s property %s, should be multiple of %d", + property_name, property_value, modulo); + } + return nr_entries / modulo; +} + + + +/* parse:
::= ; device dependant */ + +STATIC_INLINE_TREE\ +(const char *) +parse_address(device *current, + device *bus, + const char *chp, + device_unit *address) +{ + if (device_decode_unit(bus, chp, address) < 0) + device_error(current, "invalid unit address in %s", chp); + return skip_token(chp); +} + + +/* parse: ::= { "," } ; */ + +STATIC_INLINE_TREE\ +(const char *) +parse_size(device *current, + device *bus, + const char *chp, + device_unit *size) +{ + int i; + int nr; + const char *curr = chp; + memset(size, 0, sizeof(*size)); + /* parse the numeric list */ + size->nr_cells = device_nr_size_cells(bus); + nr = 0; + while (1) { + char *next; + size->cells[nr] = strtoul(curr, &next, 0); + if (curr == next) + device_error(current, "Problem parsing %s", chp); + nr += 1; + if (next[0] != ',') + break; + if (nr == size->nr_cells) + device_error(current, "Too many values in %s", chp); + curr = next + 1; + } + ASSERT(nr > 0 && nr <= size->nr_cells); + /* right align the numbers */ + for (i = 1; i <= size->nr_cells; i++) { + if (i <= nr) + size->cells[size->nr_cells - i] = size->cells[nr - i]; + else + size->cells[size->nr_cells - i] = 0; + } + return skip_token(chp); +} + + +/* parse: ::= {
} ; */ + +STATIC_INLINE_TREE\ +(void) +parse_reg_property(device *current, + const char *property_name, + const char *property_value) +{ + int nr_regs; + int reg_nr; + reg_property_spec *regs; + const char *chp; + + /* determine the number of reg entries by counting tokens */ + nr_regs = count_entries(current, property_name, property_value, 2); + + /* create working space */ + regs = zalloc(nr_regs * sizeof(*regs)); + + /* fill it in */ + chp = property_value; + for (reg_nr = 0; reg_nr < nr_regs; reg_nr++) { + chp = parse_address(current, device_parent(current), + chp, ®s[reg_nr].address); + chp = parse_size(current, device_parent(current), + chp, ®s[reg_nr].size); + } + + /* create it */ + device_add_reg_array_property(current, property_name, + regs, nr_regs); + + zfree(regs); +} + + +/* { }* */ + +STATIC_INLINE_TREE\ +(void) +parse_ranges_property(device *current, + const char *property_name, + const char *property_value) +{ + int nr_ranges; + int range_nr; + range_property_spec *ranges; + const char *chp; + + /* determine the number of ranges specified */ + nr_ranges = count_entries(current, property_name, property_value, 3); + + /* create a property of that size */ + ranges = zalloc(nr_ranges * sizeof(*ranges)); + + /* fill it in */ + chp = property_value; + for (range_nr = 0; range_nr < nr_ranges; range_nr++) { + chp = parse_address(current, current, + chp, &ranges[range_nr].child_address); + chp = parse_address(current, device_parent(current), + chp, &ranges[range_nr].parent_address); + chp = parse_size(current, current, + chp, &ranges[range_nr].size); + } + + /* create it */ + device_add_range_array_property(current, property_name, ranges, nr_ranges); + + zfree(ranges); +} + + +/* ... */ + +STATIC_INLINE_TREE\ +(void) +parse_integer_property(device *current, + const char *property_name, + const char *property_value) +{ + int nr_entries; + unsigned_cell words[1024]; + /* integer or integer array? */ + nr_entries = 0; + while (1) { + char *end; + words[nr_entries] = strtoul(property_value, &end, 0); + if (property_value == end) + break; + nr_entries += 1; + if (nr_entries * sizeof(words[0]) >= sizeof(words)) + device_error(current, "buffer overflow"); + property_value = end; + } + if (nr_entries == 0) + device_error(current, "error parsing integer property %s (%s)", + property_name, property_value); + else if (nr_entries == 1) + device_add_integer_property(current, property_name, words[0]); + else { + int i; + for (i = 0; i < nr_entries; i++) { + H2BE(words[i]); + } + /* perhaphs integer array property is better */ + device_add_array_property(current, property_name, words, + sizeof(words[0]) * nr_entries); + } +} + + +/* ... */ + +STATIC_INLINE_TREE\ +(void) +parse_string_property(device *current, + const char *property_name, + const char *property_value) +{ + char **strings; + const char *chp; + int nr_strings; + int approx_nr_strings; + + /* get an estimate as to the number of strings by counting double + quotes */ + approx_nr_strings = 2; + for (chp = property_value; *chp; chp++) { + if (*chp == '"') + approx_nr_strings++; + } + approx_nr_strings = (approx_nr_strings) / 2; + + /* create a string buffer for that many (plus a null) */ + strings = (char**)zalloc((approx_nr_strings + 1) * sizeof(char*)); + + /* now find all the strings */ + chp = property_value; + nr_strings = 0; + while (1) { + + /* skip leading space */ + while (*chp != '\0' && isspace(*chp)) + chp += 1; + if (*chp == '\0') + break; + + /* copy it in */ + if (*chp == '"') { + /* a quoted string - watch for '\' et.al. */ + /* estimate the size and allocate space for it */ + int pos; + chp++; + pos = 0; + while (chp[pos] != '\0' && chp[pos] != '"') { + if (chp[pos] == '\\' && chp[pos+1] != '\0') + pos += 2; + else + pos += 1; + } + strings[nr_strings] = zalloc(pos + 1); + /* copy the string over */ + pos = 0; + while (*chp != '\0' && *chp != '"') { + if (*chp == '\\' && *(chp+1) != '\0') { + strings[nr_strings][pos] = *(chp+1); + chp += 2; + pos++; + } + else { + strings[nr_strings][pos] = *chp; + chp += 1; + pos++; + } + } + if (*chp != '\0') + chp++; + strings[nr_strings][pos] = '\0'; + } + else { + /* copy over a single unquoted token */ + int len = 0; + while (chp[len] != '\0' && !isspace(chp[len])) + len++; + strings[nr_strings] = zalloc(len + 1); + strncpy(strings[nr_strings], chp, len); + strings[nr_strings][len] = '\0'; + chp += len; + } + nr_strings++; + if (nr_strings > approx_nr_strings) + device_error(current, "String property %s badly formatted", + property_name); + } + ASSERT(strings[nr_strings] == NULL); /* from zalloc */ + + /* install it */ + if (nr_strings == 0) + device_add_string_property(current, property_name, ""); + else if (nr_strings == 1) + device_add_string_property(current, property_name, strings[0]); + else { + const char **specs = (const char**)strings; /* stop a bogus error */ + device_add_string_array_property(current, property_name, + specs, nr_strings); + } + + /* flush the created string */ + while (nr_strings > 0) { + nr_strings--; + zfree(strings[nr_strings]); + } + zfree(strings); +} + + +/* */ + +STATIC_INLINE_TREE\ +(void) +parse_ihandle_property(device *current, + const char *property, + const char *value) +{ + ihandle_runtime_property_spec ihandle; + const char *chp; + name_specifier ihandle_spec; + + /* copy over the full path */ + ihandle.full_path = value; + + /* copy over the args (if present) */ + chp = strchr(value, '\0'); + while (chp > value && *chp != '/' && *chp != ':') + chp--; + if (*chp == ':') { + chp += 1; + ihandle.args = chp; + } + else { + ihandle.args = NULL; + } + + /* save this ready for the ihandle create */ + ihandle.phandle = split_fill_path(current, ihandle.full_path, &ihandle_spec); + device_add_ihandle_runtime_property(current, property, + &ihandle); +} + + + +EXTERN_TREE\ +(device *) +tree_parse(device *current, + const char *fmt, + ...) +{ + char device_specifier[1024]; + name_specifier spec; + + /* format the path */ + { + va_list ap; + va_start(ap, fmt); + vsprintf(device_specifier, fmt, ap); + va_end(ap); + if (strlen(device_specifier) >= sizeof(device_specifier)) + error("device_tree_add_deviced: buffer overflow\n"); + } + + /* construct the tree down to the final device */ + current = split_fill_path(current, device_specifier, &spec); + + /* is there an interrupt spec */ + if (spec.property == NULL + && spec.value != NULL) { + char *op = split_value(&spec); + switch (op[0]) { + case '>': + { + char *my_port_name = split_value(&spec); + int my_port; + char *dest_port_name = split_value(&spec); + int dest_port; + name_specifier dest_spec; + char *dest_device_name = split_value(&spec); + device *dest; + /* find my name */ + my_port = device_interrupt_decode(current, my_port_name, + output_port); + /* find the dest device and port */ + dest = split_fill_path(current, dest_device_name, &dest_spec); + dest_port = device_interrupt_decode(dest, dest_port_name, + input_port); + /* connect the two */ + device_interrupt_attach(current, + my_port, + dest, + dest_port, + permenant_object); + } + break; + default: + device_error(current, "unreconised interrupt spec %s\n", spec.value); + break; + } + } + + /* is there a property */ + if (spec.property != NULL) { + if (strcmp(spec.value, "true") == 0) + device_add_boolean_property(current, spec.property, 1); + else if (strcmp(spec.value, "false") == 0) + device_add_boolean_property(current, spec.property, 0); + else { + const device_property *property; + switch (spec.value[0]) { + case '*': + parse_ihandle_property(current, spec.property, spec.value + 1); + break; + case '[': + { + unsigned8 words[1024]; + char *curr = spec.value + 1; + int nr_words = 0; + while (1) { + char *next; + words[nr_words] = H2BE_1(strtoul(curr, &next, 0)); + if (curr == next) + break; + curr = next; + nr_words += 1; + } + device_add_array_property(current, spec.property, + words, sizeof(words[0]) * nr_words); + } + break; + case '"': + parse_string_property(current, spec.property, spec.value); + break; + case '!': + spec.value++; + property = tree_find_property(current, spec.value); + if (property == NULL) + device_error(current, "property %s not found\n", spec.value); + device_add_duplicate_property(current, + spec.property, + property); + break; + default: + if (strcmp(spec.property, "reg") == 0 + || strcmp(spec.property, "assigned-addresses") == 0 + || strcmp(spec.property, "alternate-reg") == 0){ + parse_reg_property(current, spec.property, spec.value); + } + else if (strcmp(spec.property, "ranges") == 0) { + parse_ranges_property(current, spec.property, spec.value); + } + else if (isdigit(spec.value[0]) + || (spec.value[0] == '-' && isdigit(spec.value[1])) + || (spec.value[0] == '+' && isdigit(spec.value[1]))) { + parse_integer_property(current, spec.property, spec.value); + } + else + parse_string_property(current, spec.property, spec.value); + break; + } + } + } + return current; +} + + +INLINE_TREE\ +(void) +tree_traverse(device *root, + tree_traverse_function *prefix, + tree_traverse_function *postfix, + void *data) +{ + device *child; + if (prefix != NULL) + prefix(root, data); + for (child = device_child(root); + child != NULL; + child = device_sibling(child)) { + tree_traverse(child, prefix, postfix, data); + } + if (postfix != NULL) + postfix(root, data); +} + + +STATIC_INLINE_TREE\ +(void) +print_address(device *bus, + const device_unit *phys) +{ + char unit[32]; + device_encode_unit(bus, phys, unit, sizeof(unit)); + printf_filtered(" %s", unit); +} + +STATIC_INLINE_TREE\ +(void) +print_size(device *bus, + const device_unit *size) +{ + int i; + for (i = 0; i < size->nr_cells; i++) + if (size->cells[i] != 0) + break; + if (i < size->nr_cells) { + printf_filtered(" 0x%lx", (unsigned long)size->cells[i]); + i++; + for (; i < size->nr_cells; i++) + printf_filtered(",0x%lx", (unsigned long)size->cells[i]); + } + else + printf_filtered(" 0"); +} + +STATIC_INLINE_TREE\ +(void) +print_reg_property(device *me, + const device_property *property) +{ + int reg_nr; + reg_property_spec reg; + for (reg_nr = 0; + device_find_reg_array_property(me, property->name, reg_nr, ®); + reg_nr++) { + print_address(device_parent(me), ®.address); + print_size(me, ®.size); + } +} + +STATIC_INLINE_TREE\ +(void) +print_ranges_property(device *me, + const device_property *property) +{ + int range_nr; + range_property_spec range; + for (range_nr = 0; + device_find_range_array_property(me, property->name, range_nr, &range); + range_nr++) { + print_address(me, &range.child_address); + print_address(device_parent(me), &range.parent_address); + print_size(me, &range.size); + } +} + +STATIC_INLINE_TREE\ +(void) +print_string(const char *string) +{ + printf_filtered(" \""); + while (*string != '\0') { + switch (*string) { + case '"': + printf_filtered("\\\""); + break; + case '\\': + printf_filtered("\\\\"); + break; + default: + printf_filtered("%c", *string); + break; + } + string++; + } + printf_filtered("\""); +} + +STATIC_INLINE_TREE\ +(void) +print_string_array_property(device *me, + const device_property *property) +{ + int nr; + string_property_spec string; + for (nr = 0; + device_find_string_array_property(me, property->name, nr, &string); + nr++) { + print_string(string); + } +} + +STATIC_INLINE_TREE\ +(void) +print_properties(device *me) +{ + const device_property *property; + for (property = device_find_property(me, NULL); + property != NULL; + property = device_next_property(property)) { + printf_filtered("%s/%s", device_path(me), property->name); + if (property->original != NULL) { + printf_filtered(" !"); + printf_filtered("%s/%s", + device_path(property->original->owner), + property->original->name); + } + else { + switch (property->type) { + case array_property: + if ((property->sizeof_array % sizeof(signed_cell)) == 0) { + unsigned_cell *w = (unsigned_cell*)property->array; + int cell_nr; + for (cell_nr = 0; + cell_nr < (property->sizeof_array / sizeof(unsigned_cell)); + cell_nr++) { + printf_filtered(" 0x%lx", (unsigned long)BE2H_cell(w[cell_nr])); + } + } + else { + unsigned8 *w = (unsigned8*)property->array; + printf_filtered(" ["); + while ((char*)w - (char*)property->array < property->sizeof_array) { + printf_filtered(" 0x%2x", BE2H_1(*w)); + w++; + } + } + break; + case boolean_property: + { + int b = device_find_boolean_property(me, property->name); + printf_filtered(" %s", b ? "true" : "false"); + } + break; + case ihandle_property: + { + if (property->array != NULL) { + device_instance *instance = device_find_ihandle_property(me, property->name); + printf_filtered(" *%s", device_instance_path(instance)); + } + else { + /* not yet initialized, ask the device for the path */ + ihandle_runtime_property_spec spec; + device_find_ihandle_runtime_property(me, property->name, &spec); + printf_filtered(" *%s", spec.full_path); + if (spec.args != NULL) + printf_filtered(":%s", spec.args); + } + } + break; + case integer_property: + { + unsigned_word w = device_find_integer_property(me, property->name); + printf_filtered(" 0x%lx", (unsigned long)w); + } + break; + case range_array_property: + print_ranges_property(me, property); + break; + case reg_array_property: + print_reg_property(me, property); + break; + case string_property: + { + const char *s = device_find_string_property(me, property->name); + print_string(s); + } + break; + case string_array_property: + print_string_array_property(me, property); + break; + } + } + printf_filtered("\n"); + } +} + +STATIC_INLINE_TREE\ +(void) +print_interrupts(device *me, + int my_port, + device *dest, + int dest_port, + void *ignore_or_null) +{ + char src[32]; + char dst[32]; + device_interrupt_encode(me, my_port, src, sizeof(src), output_port); + device_interrupt_encode(dest, dest_port, dst, sizeof(dst), input_port); + printf_filtered("%s > %s %s %s\n", + device_path(me), + src, dst, + device_path(dest)); +} + +STATIC_INLINE_TREE\ +(void) +print_device(device *me, + void *ignore_or_null) +{ + printf_filtered("%s\n", device_path(me)); + print_properties(me); + device_interrupt_traverse(me, print_interrupts, NULL); +} + +INLINE_TREE\ +(void) +tree_print(device *root) +{ + tree_traverse(root, + print_device, NULL, + NULL); +} + + +INLINE_TREE\ +(void) +tree_usage(int verbose) +{ + if (verbose == 1) { + printf_filtered("\n"); + printf_filtered("A device/property specifier has the form:\n"); + printf_filtered("\n"); + printf_filtered(" /path/to/a/device [ property-value ]\n"); + printf_filtered("\n"); + printf_filtered("and a possible device is\n"); + printf_filtered("\n"); + } + if (verbose > 1) { + printf_filtered("\n"); + printf_filtered("A device/property specifier () has the format:\n"); + printf_filtered("\n"); + printf_filtered(" ::= [ ] ;\n"); + printf_filtered(" ::= { } { \"/\" } ;\n"); + printf_filtered(" ::= ( | \"/\" | \"../\" | \"./\" ) ;\n"); + printf_filtered(" ::= [ \"@\" ] [ \":\" ] ;\n"); + printf_filtered(" ::= { \",\" } ;\n"); + printf_filtered("\n"); + printf_filtered("Where:\n"); + printf_filtered("\n"); + printf_filtered(" is the name of a device (list below)\n"); + printf_filtered(" is the unit-address relative to the parent bus\n"); + printf_filtered(" additional arguments used when creating the device\n"); + printf_filtered(" ::= ( # integer property\n"); + printf_filtered(" | \"[\" { } # array property (byte)\n"); + printf_filtered(" | \"{\" { } # array property (cell)\n"); + printf_filtered(" | [ \"true\" | \"false\" ] # boolean property\n"); + printf_filtered(" | \"*\" # ihandle property\n"); + printf_filtered(" | \"!\" # copy property\n"); + printf_filtered(" | \">\" [ ] # attach interrupt\n"); + printf_filtered(" | \"<\" # attach child interrupt\n"); + printf_filtered(" | \"\\\"\" # string property\n"); + printf_filtered(" | # string property\n"); + printf_filtered(" ) ;\n"); + printf_filtered("\n"); + printf_filtered("And the following are valid device names:\n"); + printf_filtered("\n"); + } +} + + + +INLINE_TREE\ +(device_instance *) +tree_instance(device *root, + const char *device_specifier) +{ + /* find the device node */ + device *me; + name_specifier spec; + if (!split_device_specifier(root, device_specifier, &spec)) + return NULL; + me = split_find_device(root, &spec); + if (spec.name != NULL) + return NULL; + /* create the instance */ + return device_create_instance(me, device_specifier, spec.last_args); +} + + +INLINE_TREE\ +(device *) +tree_find_device(device *root, + const char *path_to_device) +{ + device *node; + name_specifier spec; + + /* parse the path */ + split_device_specifier(root, path_to_device, &spec); + if (spec.value != NULL) + return NULL; /* something wierd */ + + /* now find it */ + node = split_find_device(root, &spec); + if (spec.name != NULL) + return NULL; /* not a leaf */ + + return node; +} + + +INLINE_TREE\ +(const device_property *) +tree_find_property(device *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier(root, path_to_property, &spec)) + device_error(root, "Invalid property path %s", path_to_property); + root = split_find_device(root, &spec); + return device_find_property(root, spec.property); +} + +INLINE_TREE\ +(int) +tree_find_boolean_property(device *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier(root, path_to_property, &spec)) + device_error(root, "Invalid property path %s", path_to_property); + root = split_find_device(root, &spec); + return device_find_boolean_property(root, spec.property); +} + +INLINE_TREE\ +(signed_cell) +tree_find_integer_property(device *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier(root, path_to_property, &spec)) + device_error(root, "Invalid property path %s", path_to_property); + root = split_find_device(root, &spec); + return device_find_integer_property(root, spec.property); +} + +INLINE_TREE\ +(device_instance *) +tree_find_ihandle_property(device *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier(root, path_to_property, &spec)) + device_error(root, "Invalid property path %s", path_to_property); + root = split_find_device(root, &spec); + return device_find_ihandle_property(root, spec.property); +} + +INLINE_TREE\ +(const char *) +tree_find_string_property(device *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier(root, path_to_property, &spec)) + device_error(root, "Invalid property path %s", path_to_property); + root = split_find_device(root, &spec); + return device_find_string_property(root, spec.property); +} + + +#endif /* _PARSE_C_ */ -- 2.30.2