1
0

emualtor working

This commit is contained in:
Aiden
2026-05-25 21:00:25 +10:00
parent 3ab79648ff
commit 752148c585
22 changed files with 588 additions and 22 deletions

View File

@@ -0,0 +1,9 @@
Decompiler/Pseudocode Consistency
3 byte-immediate-to-word destination case(s) require explicit zero-extension in pseudocode.
- H'1043: MOV:G.W #H'00, @FRT1_FRC_H [requires_zero_extend8_to16_pseudocode]
Word-sized MOV with an 8-bit immediate writes a zero-extended word. Pseudocode should not model this as a one-byte write or preserve the old low byte.
- H'1058: MOV:G.W #H'00, @FRT2_FRC_H [requires_zero_extend8_to16_pseudocode]
Word-sized MOV with an 8-bit immediate writes a zero-extended word. Pseudocode should not model this as a one-byte write or preserve the old low byte.
- H'4067: MOV:G.W #H'00, @(-H'0790,R2) [requires_zero_extend8_to16_pseudocode]
Word-sized MOV with an 8-bit immediate writes a zero-extended word. Pseudocode should not model this as a one-byte write or preserve the old low byte.

View File

@@ -186062,6 +186062,42 @@
}
}
],
"decompiler_consistency": {
"kind": "decompiler_pseudocode_consistency",
"summary": "3 byte-immediate-to-word destination case(s) require explicit zero-extension in pseudocode.",
"checks": [
{
"kind": "byte_immediate_to_word_destination",
"status": "requires_zero_extend8_to16_pseudocode",
"address": 4163,
"address_hex": "H'1043",
"instruction": "MOV:G.W #H'00, @FRT1_FRC_H",
"expected_pseudocode_hint": "zero_extend8_to16",
"zero_extended_value_hex": "0x0000",
"summary": "Word-sized MOV with an 8-bit immediate writes a zero-extended word. Pseudocode should not model this as a one-byte write or preserve the old low byte."
},
{
"kind": "byte_immediate_to_word_destination",
"status": "requires_zero_extend8_to16_pseudocode",
"address": 4184,
"address_hex": "H'1058",
"instruction": "MOV:G.W #H'00, @FRT2_FRC_H",
"expected_pseudocode_hint": "zero_extend8_to16",
"zero_extended_value_hex": "0x0000",
"summary": "Word-sized MOV with an 8-bit immediate writes a zero-extended word. Pseudocode should not model this as a one-byte write or preserve the old low byte."
},
{
"kind": "byte_immediate_to_word_destination",
"status": "requires_zero_extend8_to16_pseudocode",
"address": 16487,
"address_hex": "H'4067",
"instruction": "MOV:G.W #H'00, @(-H'0790,R2)",
"expected_pseudocode_hint": "zero_extend8_to16",
"zero_extended_value_hex": "0x0000",
"summary": "Word-sized MOV with an 8-bit immediate writes a zero-extended word. Pseudocode should not model this as a one-byte write or preserve the old low byte."
}
]
},
"serial_semantics": {
"kind": "serial_semantics",
"protocol_semantics": [
@@ -196427,7 +196463,7 @@
"entry_label": "loc_4046",
"target_label": "loc_4067",
"condition_candidate": "F9C4 == 0 && ((FAA5.bit7 == 0) || (F9C3 == 0)) && F9B0 == F9B5",
"summary": "Idle/default report gate; when the FRT2 countdown clears and the queue is empty, loc_4046 can enqueue H'00FF for the later loc_BAF2 -> loc_BA26 send path.",
"summary": "Idle/default report gate; when the FRT2 countdown clears and the queue is empty, loc_4046 can enqueue H'0000 for the later loc_BAF2 -> loc_BA26 send path.",
"state_addresses_hex": [
"H'F9C4",
"H'FAA5",
@@ -196435,7 +196471,26 @@
"H'F9B0",
"H'F9B5"
],
"enqueued_report_candidate_hex": "H'00FF",
"enqueued_report_candidate_hex": "H'0000",
"write_semantics_candidate": "loc_4067 is MOV:G.W #H'00, @(-H'0790,R2): the byte immediate is zero-extended by the word destination, so the queue slot becomes H'0000.",
"runtime_trace_confirmation": {
"source": "h8536_emulator_probe target-frame run",
"report_id_hex": "H'0000",
"queue_write_address_hex": "H'4067",
"queue_write_semantics": "H'FFFF -> H'0000, not H'00FF",
"dequeue_path": [
"loc_4046",
"loc_BAF2",
"loc_BB08",
"loc_BB1C",
"loc_BB20",
"loc_BB2B",
"loc_BA26"
],
"emitted_frame_hex": "00 00 00 00 80 DA",
"checksum_seed_hex": "H'5A",
"checksum_hex": "H'DA"
},
"evidence_addresses": [
16454,
16458,
@@ -196847,6 +196902,32 @@
]
}
],
"runtime_confirmed_paths": [
{
"name": "idle_heartbeat_report_runtime_confirmation",
"report_id_hex": "H'0000",
"queue_write_address_hex": "H'4067",
"queue_write_semantics": "MOV:G.W #H'00 writes H'0000 to the queue slot",
"staging_path": [
"loc_4046",
"loc_BAF2",
"loc_BB08",
"loc_BB1C",
"loc_BB20",
"loc_BB2B",
"loc_BA26"
],
"emitted_frame_hex": "00 00 00 00 80 DA",
"checksum_hex": "H'DA"
}
],
"consistency_checks": [
{
"name": "idle_heartbeat_report_id_width",
"status": "pass",
"summary": "Decompiler mnemonic MOV:G.W and emulator execution now agree that the H'00 immediate at loc_4067 is zero-extended to report H'0000."
}
],
"observed_autonomous_output_caveat": "Real captures supplied so far show only heartbeat/idle, call, and camera-power autonomous TX frames. Other panel controls may require a host/device request or state transition before the firmware reports them.",
"confidence": "candidate-medium",
"caveat": "This is a TX/report model for the BB43 -> BA26 path, separate from RX command dispatch. Observed report names are a capture overlay candidate only, not hard-coded source truth.",
@@ -206677,7 +206758,7 @@
"entry_label": "loc_4046",
"target_label": "loc_4067",
"condition_candidate": "F9C4 == 0 && ((FAA5.bit7 == 0) || (F9C3 == 0)) && F9B0 == F9B5",
"summary": "Idle/default report gate; when the FRT2 countdown clears and the queue is empty, loc_4046 can enqueue H'00FF for the later loc_BAF2 -> loc_BA26 send path.",
"summary": "Idle/default report gate; when the FRT2 countdown clears and the queue is empty, loc_4046 can enqueue H'0000 for the later loc_BAF2 -> loc_BA26 send path.",
"state_addresses_hex": [
"H'F9C4",
"H'FAA5",
@@ -206685,7 +206766,26 @@
"H'F9B0",
"H'F9B5"
],
"enqueued_report_candidate_hex": "H'00FF",
"enqueued_report_candidate_hex": "H'0000",
"write_semantics_candidate": "loc_4067 is MOV:G.W #H'00, @(-H'0790,R2): the byte immediate is zero-extended by the word destination, so the queue slot becomes H'0000.",
"runtime_trace_confirmation": {
"source": "h8536_emulator_probe target-frame run",
"report_id_hex": "H'0000",
"queue_write_address_hex": "H'4067",
"queue_write_semantics": "H'FFFF -> H'0000, not H'00FF",
"dequeue_path": [
"loc_4046",
"loc_BAF2",
"loc_BB08",
"loc_BB1C",
"loc_BB20",
"loc_BB2B",
"loc_BA26"
],
"emitted_frame_hex": "00 00 00 00 80 DA",
"checksum_seed_hex": "H'5A",
"checksum_hex": "H'DA"
},
"evidence_addresses": [
16454,
16458,
@@ -207097,6 +207197,32 @@
]
}
],
"runtime_confirmed_paths": [
{
"name": "idle_heartbeat_report_runtime_confirmation",
"report_id_hex": "H'0000",
"queue_write_address_hex": "H'4067",
"queue_write_semantics": "MOV:G.W #H'00 writes H'0000 to the queue slot",
"staging_path": [
"loc_4046",
"loc_BAF2",
"loc_BB08",
"loc_BB1C",
"loc_BB20",
"loc_BB2B",
"loc_BA26"
],
"emitted_frame_hex": "00 00 00 00 80 DA",
"checksum_hex": "H'DA"
}
],
"consistency_checks": [
{
"name": "idle_heartbeat_report_id_width",
"status": "pass",
"summary": "Decompiler mnemonic MOV:G.W and emulator execution now agree that the H'00 immediate at loc_4067 is zero-extended to report H'0000."
}
],
"observed_autonomous_output_caveat": "Real captures supplied so far show only heartbeat/idle, call, and camera-power autonomous TX frames. Other panel controls may require a host/device request or state transition before the firmware reports them.",
"confidence": "candidate-medium",
"caveat": "This is a TX/report model for the BB43 -> BA26 path, separate from RX command dispatch. Observed report names are a capture overlay candidate only, not hard-coded source truth.",

View File

@@ -22,6 +22,8 @@ u16 SR;
u8 CCR, BR, EP, DP, TP;
int C, Z, N, V;
static inline u16 zero_extend8_to16(u8 value) { return (u16)value; }
/* H8/536 register field symbols used by this ROM. */
extern volatile u8 P1DDR; /* 0xFE80 */
extern volatile u8 P1DR; /* 0xFE82 */
@@ -468,11 +470,11 @@ void vec_reset_1000(void)
SYSCR2 = (uint8_t)(0x84); /* 1034; MOV:G.B #H'84, @SYSCR2; SYSCR2 = H'84 (IRQ5E=0 IRQ4E=0 IRQ3E=0 IRQ2E=0 P6PWME=1 P9PWME=0 P9SCI2E=0; enabled P6 PWM); SYSCR2 write leaves P9SCI2E=0; SCI2 pins are disabled, so SCI2 is not the traced MAX202 path; traced RS232/MAX202 remains SCI1 P95/P96; refs SYSCR2; cycles=9 */
FRT1_TCR = (uint8_t)(0x02); /* 1039; MOV:G.B #H'02, @FRT1_TCR; FRT1_TCR = H'02 (ICIE=0 OCIEB=0 OCIEA=0 OVIE=0 OEB=0 OEA=0 CKS1=1 CKS0=0); refs FRT1_TCR; cycles=9 */
FRT1_TCSR = (uint8_t)(0x01); /* 103E; MOV:G.B #H'01, @FRT1_TCSR; FRT1_TCSR = H'01 (ICF=0 OCFB=0 OCFA=0 OVF=0 OLVLB=0 OLVLA=0 IEDG=0 CCLRA=1); refs FRT1_TCSR; cycles=9 */
FRT1_FRC_H = (uint16_t)(0x00); /* 1043; MOV:G.W #H'00, @FRT1_FRC_H; FRT1_FRC_H = H'00; refs FRT1_FRC_H; FRT1_FRC W write high TEMP access; cycles=9 */
FRT1_FRC_H = zero_extend8_to16(0x00); /* 1043; MOV:G.W #H'00, @FRT1_FRC_H; FRT1_FRC_H = H'00; byte immediate zero-extended into word destination; refs FRT1_FRC_H; FRT1_FRC W write high TEMP access; cycles=9 */
FRT1_OCRA_H = (uint16_t)(0x009C); /* 1048; MOV:G.W #H'009C, @FRT1_OCRA_H; FRT1_OCRA_H = H'9C; refs FRT1_OCRA_H; FRT1_OCRA W write high TEMP access; cycles=11 */
FRT2_TCR = (uint8_t)(0x02); /* 104E; MOV:G.B #H'02, @FRT2_TCR; FRT2_TCR = H'02 (ICIE=0 OCIEB=0 OCIEA=0 OVIE=0 OEB=0 OEA=0 CKS1=1 CKS0=0); refs FRT2_TCR; cycles=9 */
FRT2_TCSR = (uint8_t)(0x01); /* 1053; MOV:G.B #H'01, @FRT2_TCSR; FRT2_TCSR = H'01 (ICF=0 OCFB=0 OCFA=0 OVF=0 OLVLB=0 OLVLA=0 IEDG=0 CCLRA=1); refs FRT2_TCSR; cycles=9 */
FRT2_FRC_H = (uint16_t)(0x00); /* 1058; MOV:G.W #H'00, @FRT2_FRC_H; FRT2_FRC_H = H'00; refs FRT2_FRC_H; FRT2_FRC W write high TEMP access; cycles=11 */
FRT2_FRC_H = zero_extend8_to16(0x00); /* 1058; MOV:G.W #H'00, @FRT2_FRC_H; FRT2_FRC_H = H'00; byte immediate zero-extended into word destination; refs FRT2_FRC_H; FRT2_FRC W write high TEMP access; cycles=11 */
FRT2_OCRA_H = (uint16_t)(0x7A12); /* 105D; MOV:G.W #H'7A12, @FRT2_OCRA_H; FRT2_OCRA_H = H'7A12; refs FRT2_OCRA_H; FRT2_OCRA W write high TEMP access; cycles=9 */
FRT3_TCR = (uint8_t)(0x00); /* 1063; MOV:G.B #H'00, @FRT3_TCR; FRT3_TCR = H'00 (ICIE=0 OCIEB=0 OCIEA=0 OVIE=0 OEB=0 OEA=0 CKS1=0 CKS0=0); refs FRT3_TCR; cycles=9 */
FRT3_TCSR = (uint8_t)(0x00); /* 1068; MOV:G.B #H'00, @FRT3_TCSR; FRT3_TCSR = H'00 (ICF=0 OCFB=0 OCFA=0 OVF=0 OLVLB=0 OLVLA=0 IEDG=0 CCLRA=0); refs FRT3_TCSR; cycles=9 */
@@ -3701,7 +3703,7 @@ loc_4059:
set_flags_cmp8(R2, MEM8[0xF9B5]); /* 405F; CMP:G.B @H'F9B5, R2; refs ram_F9B5; cycles=6 */
if (Z) { /* 4063; BNE loc_4074; cycles=3/8 nt/t */
R2 <<= 1; /* 4065; SHLL.B R2; cycles=2 */
MEM16[R2 - 0x0790] = (uint16_t)(0x00); /* 4067; MOV:G.W #H'00, @(-H'0790,R2); cycles=11 */
MEM16[R2 - 0x0790] = zero_extend8_to16(0x00); /* 4067; MOV:G.W #H'00, @(-H'0790,R2); byte immediate zero-extended into word destination; cycles=11 */
MEM8[0xF9B0] += (uint8_t)(1); /* 406C; ADD:Q.B #1, @H'F9B0; refs ram_F9B0; cycles=9 */
MEM8[0xF9B0] &= ~BIT(7); /* 4070; BCLR.B #7, @H'F9B0; refs ram_F9B0; cycles=9 */
}

View File

@@ -167,7 +167,7 @@
"H'BF23",
"H'BF2D"
],
"summary": "F9C4 gates the idle/default report enqueue. Reset/init loads H'14, each BA26 send reloads H'07, and the FRT2 OCIA handler decrements it; when it reaches zero loc_4046 can enqueue H'00FF if the queue is empty and the FAA5/F9C3 RX gate permits it. With FRT2 OCRA H'7A12 and CKS=phi/32, a phi near 10 MHz gives about 0.7s for H'07, matching the observed heartbeat cadence.",
"summary": "F9C4 gates the idle/default report enqueue. Reset/init loads H'14, each BA26 send reloads H'07, and the FRT2 OCIA handler decrements it; when it reaches zero loc_4046 can enqueue H'0000 if the queue is empty and the FAA5/F9C3 RX gate permits it. With FRT2 OCRA H'7A12 and CKS=phi/32, a phi near 10 MHz gives about 0.7s for H'07, matching the observed heartbeat cadence.",
"tick_handler_address_hex": "H'BF23",
"timer": {
"clock_select": "CKS1=1 CKS0=0 => phi/32",

View File

@@ -73,7 +73,7 @@ Evidence:
- H'BDFB: CLR.B @H'FAA3
- H'BDFF: CLR.B @H'FAA2
- loc_4046 idle heartbeat/report gate: present
F9C4 gates the idle/default report enqueue. Reset/init loads H'14, each BA26 send reloads H'07, and the FRT2 OCIA handler decrements it; when it reaches zero loc_4046 can enqueue H'00FF if the queue is empty and the FAA5/F9C3 RX gate permits it. With FRT2 OCRA H'7A12 and CKS=phi/32, a phi near 10 MHz gives about 0.7s for H'07, matching the observed heartbeat cadence.
F9C4 gates the idle/default report enqueue. Reset/init loads H'14, each BA26 send reloads H'07, and the FRT2 OCIA handler decrements it; when it reaches zero loc_4046 can enqueue H'0000 if the queue is empty and the FAA5/F9C3 RX gate permits it. With FRT2 OCRA H'7A12 and CKS=phi/32, a phi near 10 MHz gives about 0.7s for H'07, matching the observed heartbeat cadence.
- H'4046: TST.B @H'F9C4
- H'404A: BNE loc_4058
- H'404C: BTST.B #7, @H'FAA5

View File

@@ -191,7 +191,10 @@ extern volatile u8 MEM8[0x10000];
* - evidence: H'BBD8, H'BBDC, H'BBE0, H'BBE4, H'BBE8, H'BBEC, H'BBF0, H'BE4D, H'BE56, H'BE5E, H'BE66, H'BE52, H'BE5A, H'BE62, H'BE6A, H'BE29, H'BE2D, H'BE33, H'BE37, H'BE43, H'BE47, H'BE05, H'BE0D, H'BE15, H'BE09, H'BE11, H'BE19, H'BE22
* gate/queue state machine candidate:
* - main_loop_may_enter_report_builder: FAA2 == 0 && F9C0 == 0 && ((FAA5.bit7 == 0) || (F9C3 == 0)); Main-loop report gate; session must be idle, TX busy timer clear, and RX gate open.
* - idle_heartbeat_report_may_enqueue: F9C4 == 0 && ((FAA5.bit7 == 0) || (F9C3 == 0)) && F9B0 == F9B5; Idle/default report gate; when the FRT2 countdown clears and the queue is empty, loc_4046 can enqueue H'00FF for the later loc_BAF2 -> loc_BA26 send path.
* - idle_heartbeat_report_may_enqueue: F9C4 == 0 && ((FAA5.bit7 == 0) || (F9C3 == 0)) && F9B0 == F9B5; Idle/default report gate; when the FRT2 countdown clears and the queue is empty, loc_4046 can enqueue H'0000 for the later loc_BAF2 -> loc_BA26 send path.
* enqueues report H'0000
* write semantics: loc_4067 is MOV:G.W #H'00, @(-H'0790,R2): the byte immediate is zero-extended by the word destination, so the queue slot becomes H'0000.
* runtime-confirmed frame 00 00 00 00 80 DA via loc_4046 -> loc_BAF2 -> loc_BB08 -> loc_BB1C -> loc_BB20 -> loc_BB2B -> loc_BA26
* - queue_has_pending_report: F9B5 != F9B0; Queue/pending cursor gate; non-empty state stages through BB43 before loc_BA26.
* - periodic_resend_may_fire: (FAA5 & FAA3 & 0x80) != 0 && F9C6 == 0 && F9C8 != 0 after countdown; Resend gate masks pending state with FAA5, checks F9C6/F9C8, then calls BA26 at BED5.
* - rx_completion_sets_session_timer: RX completion sets F9C5 (observed reload H'14) after the sixth byte is captured.
@@ -204,6 +207,8 @@ extern volatile u8 MEM8[0x10000];
* TX/autonomous report model candidate:
* - loc_BB43 -> loc_BA26: bytes 0..2 encode candidate logical index/report id; bytes 3..4 come from current_value_table_candidate; byte5 is 0x5A XOR checksum
* - observed overlay candidates: heartbeat_or_idle_report_candidate: 00 00 00 00 80 DA; call_button_report_candidate: 00 00 15 80 00 CF, 00 00 15 00 00 4F; camera_power_report_candidate: 00 00 07 80 00 DD
* - runtime confirmation: idle_heartbeat_report_runtime_confirmation: report H'0000 emits 00 00 00 00 80 DA; MOV:G.W #H'00 writes H'0000 to the queue slot
* - consistency idle_heartbeat_report_id_width: pass; Decompiler mnemonic MOV:G.W and emulator execution now agree that the H'00 immediate at loc_4067 is zero-extended to report H'0000.
* - caveat: Real captures supplied so far show only heartbeat/idle, call, and camera-power autonomous TX frames. Other panel controls may require a host/device request or state transition before the firmware reports them.
* - evidence: H'BB1C, H'BB20, H'BB2B, H'BB39, H'BB3F, H'BB43
* heartbeat/periodic resend candidate:
@@ -273,6 +278,16 @@ static bool sci1_candidate_idle_heartbeat_enqueue_gate_open(void)
return idle_timer_clear && rx_gate_open && queue_empty;
}
static void sci1_candidate_enqueue_idle_heartbeat_report(void)
{
if (!sci1_candidate_idle_heartbeat_enqueue_gate_open()) {
return;
}
/* loc_4067 writes MOV:G.W #H'00, so the queue report id is 0x0000. */
candidate_enqueue_report(0x0000u);
}
static bool sci1_candidate_periodic_resend_gate_open(void)
{
bool pending = (MEM8[0xFAA5u] & MEM8[0xFAA3u] & 0x80u) != 0u;