view STATUS @ 297:499ea85d95f4

l1p_cmpl.c: intram compilation passes, but the link fails
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 02 Oct 2017 06:23:52 +0000
parents f2f7f4dff6d7
children 7ad882cbce4c
line wrap: on
line source

Objects in l1_ext.lib:

l1_afunc.obj:	not exact, see explanation below
l1_async.obj:	perfect match
l1_cmplx.obj:	perfect match to 20070608 version except line number points
l1_init.obj:	perfect match
l1_pwmgr.obj:	perfect match
l1_small.obj:	perfect match
l1_sync.obj:	not exact, see explanation below
l1_trace.obj:	bits match perfectly, diff only in symbolic metadata

l1_dyn_dwl_afunc.obj:	perfect match
l1_dyn_dwl_apihisr.obj:	perfect match
l1_dyn_dwl_async.obj:	perfect match
l1_dyn_dwl_func.obj:	not exact, see explanation below
l1_dyn_dwl_init.obj:	sole diff is in the num_of_primitives oddity,
			see explanation below
l1_dyn_dwl_sync.obj:	perfect match

l1audio_abb.obj:	perfect match
l1audio_afunc.obj:	bits match perfectly, diff only in symbolic metadata
l1audio_async.obj:	diffs only in register alloc and symbolic metadata
l1audio_back.obj:	perfect match
l1audio_drive.obj:	perfect match
l1audio_init.obj:	perfect match

l1tm_async.obj:	bits match perfectly, diff only in the line number points
l1tm_func.obj:	bits match perfectly, diffs only in symbolic and line numbers
l1tm_stats.obj:	perfect match

Objects in l1_int.lib:

dl1_com.obj:		not exact, see analysis below
l1_api_hisr.obj:	perfect match
l1_cmplx_intram.obj:	perfect match to 20070608 version
l1_ctl.obj:		perfect match to 20070608 version
l1_drive.obj:		perfect match
l1_func.obj:		perfect match
l1_mfmgr.obj:		perfect match
l1_sync_intram.obj:	not exact, see explanation below

l1audio_func.obj:	perfect match
l1audio_sync.obj:	perfect match

Objects in l1_custom_ext.lib:

l1audio_cust.obj:	dead functions not reconstructed, perfect match
			otherwise
l1tm_cust.obj:		perfect match
l1tm_tpu12.obj:		perfect match

Objects in l1_custom_int.lib:

ind_os.obj:	perfect match
l1_cust.obj:	perfect match

Objects in tpudrv.lib:

tpudrv.obj:	perfect match
tpudrv12.obj:	not exact, see analysis below

Detailed analysis of differences, i.e., cases where the reconstructed C code
compiles into an object that is not bit-identical to the original blob:

l1_afunc.obj:

	The l1_afunc.c module from LoCosto is used without any changes:
	it compiled right away after adding one constant to l1_const.h,
	and the result of recompilation is identical to the original up until
	the l1a_clip_txpwr() function, which is the last function in the module.

	Disassembly of the original blob version of this function has been
	analyzed and found to be identical in logic to the available C code,
	but there must have been some change to the code expression that
	results in different output from the compiler.  In particular, the
	symbolic info indicates the presence of a local variable named power
	in the original, but no such local var exists in the LoCosto version.
	The TSM30 version was of no help as it is entirely different there.

	See g23m/objdiff/l1_ext/l1_afunc.notes for further info.

l1_sync.obj:

	The last function in this module is l1s_dedicated_mode_manager();
	the two preceding functions match perfectly, but for this last function
	when the reconstructed code is recompiled, the compiler's register
	allocator makes different picks for reasons that could not be
	successfully reversed.  Because the code is compiled in Thumb mode
	and the compiler made a different choice between low and high registers
	in some places, the instructions do not line perfectly.  The logic match
	has instead been verified by manual comparison.

l1_sync_intram.obj:

	Similar situation in the l1s_schedule_tasks() function: the function
	is huge, there is an unknown set of factors determining what the
	compiler's register allocator will do, and in this case there is even
	a difference in the choice of register vs. stack for some temporaries.
	As a result, the code does not line up and the logic had to be verified
	manually.  All other functions (preceding and following) match
	perfectly.

dl1_com.obj:

	The reconstruction of this module is not exact, but the logic has
	been verified to be an exact match except for the removal of some
	non-functional bogons.  Specifically:

	l1_create_ISR(): diff in one local variable name (result vs. status),
	affects the generated assert string, but the length stays the same.
	This assert string also contains the line number which differs
	(3 digits in both cases), and the location of the string changes
	because of the diffs in later functions listed below.
	Verified exact match otherwise.

	TP_FrameIntHandler(): verified exact match.

	layer_1_sync_HISR_entry(): the version in the blob contains a
	non-functional bogon which has not been reconstructed, see the
	comments in the reconstructed source.  Verified to be an exact match
	except for the removal of this bogon.

	rx_tch_data(): empty function in both versions, trivial exact match.

	tx_tch_data(): this stub function is supposed to return a pointer,
	but the original blob does a bare bx lr, returning whatever happens to
	be in r0 on entry, which is unpredictable as the function takes no
	arguments.  The reconstructed version returns NULL.

	Strings and literals after the functions: manually verified to be an
	exact match.

	.bss section: the original blob contains these defunct uninitialized
	data objects: BACK_queue, DLL1_queue, L1C1_queue, RRM1_queue, pool_52,
	pool_100, pool_400, pool_1600, and a static variable i in
	layer_1_sync_HISR_entry() related to the bogon mentioned above.  These
	global data objects are not referenced from anywhere else in the
	firmware and the link succeeds without them being present, hence they
	have been omitted from the reconstruction.  The rest is an exact match.

l1_dyn_dwl_func.obj:

	The LoCosto version uses a function (implemented in l1_func.c in
	the LoCosto code) named l1_memcpy_16bit() to download patch bits
	into the DSP's API RAM; the function does what the name says, and
	the logic of using 16-bit accesses when hitting this API RAM makes
	perfect sense to me (Mychaela).  The original TCS211 code apparently
	used plain memcpy(), which the compiler turned into its C$MEMCPY call.

	If one does a #define l1_memcpy_16bit memcpy in l1_dyn_dwl_func.c,
	the resulting l1_dyn_dwl_func.obj is almost bit-identical to the
	original blob: the only diff is in register allocation - the compiler's
	register allocator picks a different choice of registers, but all
	instructions still perfectly line up.

	For production use of our reconstructed TCS211 L1 code, we have adopted
	the version with l1_memcpy_16bit() - the function body itself has been
	moved into l1_dyn_dwl_func.c so that l1_func.c remains a perfect match.

l1_dyn_dwl_init.obj:

	In the TCS211 configuration without L1_GTT, there are a total of 5
	signals (aka primitives aka L1 messages) which trigger a dynamic
	DSP patch download.  These 5 signals are enumerated in
	signal_patch_array[] in l1_dyn_dwl_afunc.c (which has been reconstructed
	to a perfect match), and their total count (which should be 5) goes into
	l1a.dyn_dwnld.num_of_primitives, set in l1_dyn_dwnld_initialize_var() in
	l1_dyn_dwl_init.c.

	In the original blob version this num_of_primitives variable ends up
	being set to 6: first set to 2, then incremented by 4.  In the LoCosto
	source this var is first set to 0 as they apparently have no patches
	that are independent of compilation config options, and then incremented
	for every enabled option.

	In our reconstruction we have made the GPRS and AMR_SCH patches and the
	primitives that trigger them mandatory, and conditionalized the E2 and
	AMR_MMS patches on MELODY_E2.  The GPRS and AMR_MMS critters are
	preinstalled by the static patch, and get pushed out by AMR_SCH and E2,
	respectively.  Of the 5 primitives listed in signal_patch_array[] in
	the original blob, the first 2 are always-present core ones, whereas
	the last 3 are specific to E2.  The AMR_MMS patch is reinstated upon
	L1_BACK_MELODY_E2_UNLOAD_INSTRUMENT_CON.

	Based on the above reasoning, our reconstructed version sets
	l1a.dyn_dwnld.num_of_primitives to 5 in the full configuration: first
	sets to 2, then increments by 3.  If one makes a sans-MELODY_E2 build,
	only the GPRS and AMR_SCH patches will be retained, and only the two
	non-E2 primitives for entry into and exit from dedicated mode.

l1audio_async.obj:

	The only bit diff is in register allocation - the compiler's register
	allocator picks a different choice of registers, but all instructions
	still perfectly line up.  There is also a slight diff in the symbolic
	metadata emitted for functions, which might be related to the diff in
	the register allocation.

	The root cause of these diffs could not be found, but there is no
	functional difference as only some in-function temporary registers
	have been interchanged.

l1audio_cust.obj:

	The original blob version has these demo/test functions at the end of
	the module:

	audio_melo_e1_demo1_start()
	audio_melo_e1_demo1_stop()
	audio_melo_e1_demo2_start()
	audio_melo_e1_demo2_stop()
	audio_melo_e2_load_lsi()
	audio_melo_e2_demo1_start()
	audio_melo_e2_demo1_stop()
	audio_melo_e2_demo2_start()
	audio_melo_e2_demo2_stop()

	These functions are dead code, i.e., they are not called or referenced
	from anywhere else in the firmware, and the link succeeds without them
	being present.  These dead functions have been omitted from the
	reconstructed version.  The reconstruction is a perfect match otherwise.

tpudrv12.obj:

	The reconstruction of this module was more of a translation of logic
	from disassembly to C than adaptation of source from other versions,
	hence it is not a bit-for-bit match or even close.  However, the logic
	has been carefully verified and confirmed to match the original; see
	chipsetsw/layer1/tpu_drivers/source0/tpudrv12.notes for the details.