2 * TODO TODO TODO TODO TODO TODO TODO TODO TODO
4 * some ROM functions are not completely implemented nor documented
5 * emulate more of smb access with fifo, rom functions emulate
6 * argument pointer evaluate location
17 //for SMB input from user HACK
18 extern u8
* test_buf(void);
20 #define r_r3 read_reg8(MAIN_REG_R3, 1)
21 #define r_r2 read_reg8(MAIN_REG_R2, 1)
22 #define r_r1 read_reg8(MAIN_REG_R1, 1)
23 #define r_r0 read_reg8(MAIN_REG_R0, 1)
25 #define w_r3(x) write_reg8(MAIN_REG_R3, x, 1)
26 #define w_r2(x) write_reg8(MAIN_REG_R2, x, 1)
27 #define w_r1(x) write_reg8(MAIN_REG_R1, x, 1)
28 #define w_r0(x) write_reg8(MAIN_REG_R0, x, 1)
30 #define r_st(x) read_mem(stack_ptr + (x), 1)
31 #define w_st(x, y) write_mem(stack_ptr + (x), y, 1)
33 /** ********* rom routines ************/
35 static u16
rom_execute(u16 stack_ptr
)
38 log_comment_add(" void? rom_execute(void?) //untested\n");
40 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
45 static u16
smbSlaveCmd(u16 stack_ptr
)
49 u16 table_ptr
= (r_r1
<< 8) | r_r0
;
56 " unsigned *table() = %04hx)\n",
63 write_ip(read_pc()+1, 1);
65 //TODO ?need modify rom code, perma hook?
66 ret
= table_ptr
+ cmd
;
68 //cannot be set registers will be changed in jumped functions (maybe use footer detection :-/ )
69 // reg[3] = 0; //ret success
70 // reg[2] = 1; //ret success
78 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
83 static u16
smb_NACK(u16 stack_ptr
)
85 log_comment_add(" void smb_NACK(void)\n");
87 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
92 static u16
smb_ACK(u16 stack_ptr
)
94 log_comment_add(" void smb_ACK(void)\n");
96 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
102 // u8 smb_data_val=0x71;
104 static u16
smbSlaveRcvWord(u16 stack_ptr
)
106 u16 data
= (r_r3
<< 8) | r_r2
;
109 " int smbSlaveRcvWord(int *data = [%04hx])\n",
117 val
= test_buf()[0] << 8;
118 val
|= test_buf()[0];
120 log_comment_add(" VVV %04hx\n", val
);
122 // smb_data_val = 0x73;
124 write_mem(data
, val
& 0xff, 1);
125 write_mem(data
+1, (val
>> 8) & 0xff, 1);
128 log_comment_add(" XXX %02hhx %02hhx\n",
134 w_r3(0); //ret success
135 w_r2(1); //ret success
137 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
142 static u16
smbSlaveSndWord(u16 stack_ptr
)
144 u16 data
= (r_r3
<< 8) | r_r2
;
147 " int smbSlaveSndWord(int data = %04hx)\n",
151 w_r3(0); //ret success
152 w_r2(1); //ret success
154 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
160 static u16
smbSlaveSndBlock(u16 stack_ptr
)
163 u16 dptr
= (r_r2
<< 8) | r_r1
;
166 " void smbSlaveSndBlock(\n"
167 " u8 byte_cnt = %hhu,\n"
168 " u8 *block = [%04hx])\n",
173 log_comment_add("\n");
174 log_comment_add(" Data: {");
176 for (unsigned a
=0;a
<cnt
;a
++) {
177 data
= read_mem(dptr
+ a
, 1);
178 log_comment_add("%02hhx, ", data
);
180 log_comment_add("}\n");
182 w_r3(0); //ret success
183 w_r2(1); //ret success
185 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
191 static u16
smbSlaveRcvBlock(u16 stack_ptr
)
193 u16 cnt_ptr
= (r_r3
<< 8) | r_r2
;
194 u16 dptr
= (r_r1
<< 8) | r_r0
;
197 " void smbSlaveRcvBlock(\n"
198 " u8 *byte_cnt = [%04hx],\n"
199 " u8 *block = [%04hx])\n",
204 u8 cnt
= test_buf()[0];
207 write_mem(cnt_ptr
, cnt
, 1);
209 log_comment_add("\n");
210 log_comment_add(" Cnt=%hhu\n", cnt
);
211 log_comment_add(" Data: {");
212 for (unsigned a
=0;a
<cnt
;a
++) {
213 data
= test_buf()[0];
214 log_comment_add("%02hhx, ", data
);
215 write_mem(dptr
+ a
, data
, 1);
217 log_comment_add("}\n");
219 w_r3(0); //ret success
220 w_r2(1); //ret success
222 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
229 static u16
smbSlaveWord(u16 stack_ptr
)
231 u16 dir_ptr
= (r_r3
<< 8) | r_r2
;
232 u16 data_ptr
= (r_r1
<< 8) | r_r0
;
235 " int smbSlaveWord(\n"
236 " u8 *dir = [%04hx],\n"
237 " int *data = [%04hx])\n",
242 log_comment_add("\n");
243 log_comment_add(" read pre %02hhx %02hhx\n",
244 read_mem(data_ptr
, 0),
245 read_mem(data_ptr
+1, 0)
248 //this are changeable values
249 u8 flag_written
= test_buf()[0];
251 write_mem(dir_ptr
, flag_written
, 1);
254 u8 lo
= test_buf()[0];
255 u8 hi
= test_buf()[0];
257 log_comment_add(" write %02hhx %02hhx\n",
261 write_mem(data_ptr
, lo
, 1);
262 write_mem(data_ptr
+1, hi
, 1);
265 w_r3(0); //ret success
266 w_r2(1); //ret success
268 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
274 static u16
smbSlaveBlock(u16 stack_ptr
)
276 u16 drdy_ptr
= (r_r3
<< 8) | r_r2
;
277 u16 bytecnt_ptr
= (r_r1
<< 8) | r_r0
;
279 u16 block_ptr
= (r_st(1) << 8) | r_st(2);
282 " int smbSlaveBlock(\n"
283 " u8 *drdy = [%04hx],\n"
284 " u8 *bytecnt = [%04hx],\n"
285 " u8 maxcnt = %hhu,\n"
286 " u8 *blocks = [%04hx])\n",
292 log_comment_add("\n");
296 //this are changeable values
297 u8 flag_written
= test_buf()[0];
298 write_mem(drdy_ptr
, flag_written
, 1);
300 u8 bytecnt
= read_mem(bytecnt_ptr
, 0);
301 log_comment_add(" Cnt=%hhu\n", bytecnt
);
302 log_comment_add(" Data (slave->master): {");
303 for (unsigned a
=0;a
<bytecnt
;a
++) {
304 log_comment_add("%02hhx, ", read_mem(block_ptr
+ a
, 0));
306 log_comment_add("}\n");
310 bytecnt
= test_buf()[0];
311 log_comment_add(" Cnt=%hhu\n", bytecnt
);
312 log_comment_add(" Data (master->slave): {");
313 for (unsigned a
=0;a
<bytecnt
;a
++) {
314 data
= test_buf()[0];
315 log_comment_add("%02hhx, ", data
);
316 write_mem(block_ptr
+ a
, data
, 1);
318 log_comment_add("}\n");
322 w_r3(0); //ret success
323 w_r2(1); //ret success
325 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
331 #define BQ29330_REG_NUM 9
332 u8 bq29330
[BQ29330_REG_NUM
];
334 void write_bq29330_reg(u8 reg
, u8 val
)
336 if (reg
>= BQ29330_REG_NUM
)
342 // #define BQ29330_REG_NAMES_MAX 16
344 const char *bq29330_reg_names
[BQ29330_REG_NUM
] = {
356 const char *bq29330_bits_names
[BQ29330_REG_NUM
][8] = {
358 "scd", "scc", "ol", "wdf", "zv", "rsvd5", "rsvd6", "rsvd7"
361 "ltclr", "dsg", "chg", "xzv", "gpod", "pms_chg", "rsvd6", "rsvd7"
364 "sleep", "ship", "wddis", "wdrst", "rsns", "rsvd5", "rsvd6", "rsvd7"
367 "vmen", "pack", "bat", "tout", "rsvd4", "rsvd5", "rsvd6", "rsvd7"
370 "cell0", "cell1", "cal0", "cal1", "cb0", "cb1", "cb2", "cb3"
373 "olv0", "olv1", "olv2", "olv3", "olv4", "rsvd5", "rsvd6", "rsvd7"
376 "old0", "old1", "old2", "old3", "rsvd4", "rsvd5", "rsvd6", "rsvd7"
379 "sccv0", "sccv1", "sccv2", "sccv3", "sccd0", "sccd1", "sccd2", "sccd3"
382 "scdv0", "scdv1", "scdv2", "scdv3", "scdd0", "scdd1", "scdd2", "scdd3"
388 static u16
I2CWriteBlock(u16 stack_ptr
)
393 u16 dptr
= (r_st(0) << 8) | r_st(1);
396 " u8 I2CWriteBlock(\n"
397 " u8 addr = %02hhx,\n"
398 " u8 cmd = %02hhx,\n"
400 " u8 *data = [%04hx])\n",
407 log_comment_add("\n");
410 // if (addr == 0x40) {
411 for (u8 idx
= 0; idx
< cnt
; idx
++) {
413 if ((cmd
+idx
) < BQ29330_REG_NUM
) {
414 u8 val_old
= bq29330
[cmd
+idx
];
415 u8 val_new
= read_mem(dptr
+ idx
, 0);
417 log_comment_reg_bits(
418 bq29330_reg_names
[cmd
+idx
],
419 bq29330_bits_names
[cmd
+idx
],
424 bq29330
[cmd
+idx
] = val_new
;
426 if (((cmd
+idx
)==1) && (val_new
&1)) {
433 log_comment_add(" unknown bq29330[%hhd]=%02hhx\n",
435 read_mem(dptr
+ idx
, 1));
439 for (u8 idx
= 0; idx
< cnt
; idx
++) {
440 log_comment_add(" unknown dev[%hhd]=%02hhx\n",
442 read_mem(dptr
+ idx
, 1));
446 w_r3(0); //ret success
447 w_r2(1); //ret success
449 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
454 static u16
I2CReadBlock(u16 stack_ptr
)
460 u16 dptr
= (r_st(0) << 8) | r_st(1);
463 " u8 I2CReadBlock(\n"
464 " u8 addr = %02hhx,\n"
465 " u8 cmd = %02hhx,\n"
467 " u8 *data = [%04hx])\n",
474 log_comment_add("\n");
477 // if (addr == 0x40) {
478 for (u8 idx
= 0; idx
< cnt
; idx
++) {
480 if ((cmd
+idx
) < BQ29330_REG_NUM
) {
481 u8 val
= bq29330
[cmd
+ idx
];
483 log_comment_reg_bits(
484 bq29330_reg_names
[cmd
+idx
],
485 bq29330_bits_names
[cmd
+idx
],
490 write_mem(dptr
+ idx
, val
, 1);
492 log_comment_add(" unknown bq29330[%hhd]=%02hhx\n",
494 read_mem(dptr
+ idx
, 1));
498 for (u8 idx
= 0; idx
< cnt
; idx
++) {
499 log_comment_add(" unknown dev[%hhd]=%02hhx\n",
501 read_mem(dptr
+ idx
, 1));
505 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
507 w_r3(0); //ret success
508 w_r2(1); //ret success
514 static u16
FdataEraseRow(u16 stack_ptr
)
517 u16 flash_addr
= 32*row
+ 0x4000;
519 log_comment_add(" void FdataEraseRow(u8 row = %hhd)\n",
523 log_comment_add("\n");
524 log_comment_add(" FLASH[%04hx]\n",
528 //NOTICE erases 2 rows
529 for (unsigned a
=0;a
<64;a
++) {
530 write_mem(flash_addr
+ a
, 0xff, 1);
533 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
539 static u16
FdataProgRow(u16 stack_ptr
)
545 u16 flash_addr
= 32*row
+ col
+ 0x4000;
546 u16 dptr
= (r_st(0) << 8) | r_st(1);
549 " void FdataProgRow(\n"
553 " u8 *data = [%04hx])\n",
560 log_comment_add("\n");
561 log_comment_add(" FLASH[%04hx]\n",
565 log_comment_add(" Data: {");
567 for (unsigned a
=0;a
<cnt
;a
++) {
568 data
= read_mem(dptr
+ a
, 1);
569 log_comment_add("%02hhx, ", data
);
570 write_mem(flash_addr
+ a
, data
, 1);
572 log_comment_add("}\n");
574 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
579 static u16
FdataProgWord(u16 stack_ptr
)
581 u16 flash_addr
= (r_r3
<< 8) | r_r2
;
585 " void FdataProgWord(\n"
586 " u8 *addr = [%04hx],\n"
587 " u8 data = %02hhx)\n",
592 write_mem(flash_addr
, data
, 1);
594 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
599 //program memory, read only LSB u16
600 static u16
FlashRdRow(u16 stack_ptr
)
602 u16 row
= (r_r3
<< 8) | r_r2
;
605 u16 dataptr
= (r_st(0) << 8) | r_st(1);
608 " void FlashRdRow(\n"
612 " u16 *data = [%04hx])\n",
613 row
, col
, cnt
, dataptr
616 u16 prog_addr
= row
*32+col
;
617 struct opcode_word prog_word
= read_code(prog_addr
);
619 log_comment_add(" code[%04hx]=%06x\n",
620 prog_addr
, prog_word
.raw
623 //TODO missing cnt > 1 (implement!)
624 write_mem(dataptr
+ 0, (prog_word
.raw
>> 8) & 0xff, 1);
625 write_mem(dataptr
+ 1, (prog_word
.raw
>> 0) & 0xff, 1);
627 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
633 static u16
FdataMassErase(u16 stack_ptr
)
635 log_comment_add(" void FdataMassErase(void)\n");
637 for (unsigned a
=0x4000;a
<0x4800;a
++) {
638 write_mem(a
, 0xff, 0); //NOTICE, that would be hell to log
641 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
647 static u16
SetAddr(u16 stack_ptr
)
649 log_comment_add(" void SetAddr(void)\n");
650 log_comment_add(" fully transparent\n");
652 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
657 static u16
PokeByte(u16 stack_ptr
)
659 log_comment_add(" void PokeByte(void)\n");
660 log_comment_add(" fully transparent\n");
662 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
667 static u16
PeekByte(u16 stack_ptr
)
669 log_comment_add(" void PeekByte(void)\n");
670 log_comment_add(" fully transparent\n");
672 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
678 static u16
ReadRAMBlk(u16 stack_ptr
)
680 log_comment_add(" void ReadRAMBlk(void)\n");
681 log_comment_add(" fully transparent\n");
683 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
688 static u16
smbWaitBusFree(u16 stack_ptr
)
692 log_comment_add(" int smbWaitBusFree(u8 status = %hhd)\n",
696 w_r3(0); //ret success
697 w_r2(1); //ret success
699 // sim_breakpoint_set(SIM_BREAKPOINT_CODE);
707 static u16
mulhisi3(u16 stack_ptr
)
709 s16 a
= (r_r3
<< 8) | r_r2
;
710 s16 b
= (r_r1
<< 8) | r_r0
;
721 log_comment_add("\n");
722 log_comment_add(" mul=%li\n", m
);
724 w_r3((m
>> 24) & 0xff);
725 w_r2((m
>> 16) & 0xff);
726 w_r1((m
>> 8) & 0xff);
727 w_r0((m
>> 0) & 0xff);
729 // sim_breakpoint_set(SIM_BREAKPOINT_CODE);
734 static u16
umulhisi3(u16 stack_ptr
)
736 u16 a
= (r_r3
<< 8) | r_r2
;
737 u16 b
= (r_r1
<< 8) | r_r0
;
748 log_comment_add("\n");
749 log_comment_add(" mul=%u\n", m
);
751 w_r3((m
>> 24) & 0xff);
752 w_r2((m
>> 16) & 0xff);
753 w_r1((m
>> 8) & 0xff);
754 w_r0((m
>> 0) & 0xff);
760 static u16
mulsi3(u16 stack_ptr
)
783 log_comment_add("\n");
784 log_comment_add(" mul=%lu\n", m
);
786 w_r3((m
>> 24) & 0xff);
787 w_r2((m
>> 16) & 0xff);
788 w_r1((m
>> 8) & 0xff);
789 w_r0((m
>> 0) & 0xff);
794 static u16
udivmodhi4(u16 stack_ptr
)
796 u16 a
= (r_r3
<< 8) | r_r2
;
797 u16 b
= (r_st(0) << 8) | r_st(1);
809 log_comment_add("\n");
810 log_comment_add(" rem=%hu quot=%hu\n", r
, q
);
812 w_r3((r
>> 8) & 0xff);
813 w_r2((r
>> 0) & 0xff);
814 w_r1((q
>> 8) & 0xff);
815 w_r0((q
>> 0) & 0xff);
820 static u16
divmodsi4(u16 stack_ptr
)
823 a
= (r_r3
<< 24) & 0xff;
824 a
|= (r_r2
<< 16) & 0xff;
825 a
|= (r_r1
<< 8) & 0xff;
826 a
|= (r_r0
<< 0) & 0xff;
844 log_comment_add("\n");
845 log_comment_add(" rem=%u quot=%u\n", r
, q
);
847 w_r3((q
>> 24) & 0xff);
848 w_r2((q
>> 16) & 0xff);
849 w_r1((q
>> 8) & 0xff);
850 w_r0((q
>> 0) & 0xff);
852 w_st(0, (r
>> 24) & 0xff);
853 w_st(1, (r
>> 16) & 0xff);
854 w_st(2, (r
>> 8) & 0xff);
855 w_st(3, (r
>> 0) & 0xff);
860 static u16
divmodhi4(u16 stack_ptr
)
862 s16 a
= (r_r1
<< 8) | r_r0
;
863 s16 b
= (r_st(0) << 8) | r_st(1);
875 log_comment_add("\n");
876 log_comment_add(" rem=%hi quot=%hi\n", r
, q
);
878 w_r3((r
>> 8) & 0xff);
879 w_r2((r
>> 0) & 0xff);
880 w_r1((q
>> 8) & 0xff);
881 w_r0((q
>> 0) & 0xff);
888 static u16
IrqROMHandler(u16 stack_ptr
)
890 log_comment_add(" void IrqROMHandler(void)\n");
891 log_comment_add(" unknown function, maybe rom irq handler, where to return?\n");
893 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);
899 //TODO maybe bitfield of input params, output params
900 //will be limited to 64 probably (u64 bitfield)
901 #define FCN_OSTACK (1U<<0)
902 #define FCN_ISTACK(x) ((x)<<1)
906 u16 (*fcn_call
)(u16
);
910 static const struct rom_fcn fcns
[] = {
911 {0x8004, rom_execute
, 0},
912 // {0x8005, smbMasterWrWord, 0},
913 {0x8009, smbSlaveCmd
, 0},
914 {0x800a, smbSlaveRcvWord
, 0},
915 {0x800b, smbSlaveSndWord
, 0},
916 {0x800c, smbSlaveSndBlock
, 0},
917 {0x800d, smbSlaveRcvBlock
, 0},
918 {0x800e, smbSlaveWord
, 0},
919 {0x800f, smbSlaveBlock
, FCN_ISTACK(3)},
920 {0x8012, smb_ACK
, 0},
921 {0x8013, smb_NACK
, 0},
922 {0x8014, FlashRdRow
, FCN_ISTACK(2)},
923 {0x8017, SetAddr
, 0}, //calls+jmp
924 {0x8018, PokeByte
, 0}, //calls+jmp
925 {0x8019, PeekByte
, 0}, //calls+jmp
926 {0x801a, ReadRAMBlk
, 0}, //calls+jmp
928 {0x801c, mulhisi3
, 0},
929 {0x801d, umulhisi3
, 0},
930 {0x801e, mulsi3
, FCN_ISTACK(8)},
931 {0x8020, divmodhi4
, FCN_ISTACK(2)},
932 {0x8021, udivmodhi4
, FCN_ISTACK(2)},
933 {0x8022, divmodsi4
, FCN_ISTACK(4) | FCN_OSTACK
},
935 {0x8037, FdataProgRow
, FCN_ISTACK(2)},
936 {0x8038, FdataProgWord
, 0},
937 {0x8039, FdataEraseRow
, 0},
938 {0x803a, FdataMassErase
, 0},
939 {0x803b, I2CReadBlock
, FCN_ISTACK(2)},
940 {0x803c, I2CWriteBlock
, FCN_ISTACK(2)},
941 // {0x803d, I2CDeviceAvail, 0},
942 // {0x803e, I2CCompareBlock, 0},
943 {0x8043, smbWaitBusFree
, 0},
946 // {0x8040, rsvd/tramp?/irq6+},
947 {0x8040, IrqROMHandler
, 0},
949 //last entry, just dump stack
950 {0, NULL
, FCN_ISTACK(8)},
957 * args: r3, r2, r1, r0, stack 0, stack 1, 2 3 4...
959 * rets: r2 (lsb), r3 (msb)
961 * NOTICE R0 can be skipped if u16 not aligned?
964 u16
check_rom_funcs(u16 pc
)
969 log_comment_add("=== ROM routines: ===\n");
971 unsigned flag_hit
= 0;
972 u16 sw_stack_ptr
= read_ix(I_REG_3
, 1);
975 log_comment_add(" Input: r3=%02hhx r2=%02hhx r1=%02hhx r0=%02hhx ",
976 read_reg8(MAIN_REG_R3
, 0),
977 read_reg8(MAIN_REG_R2
, 0),
978 read_reg8(MAIN_REG_R1
, 0),
979 read_reg8(MAIN_REG_R0
, 0)
985 if ((fcns
[idx
].pc
== pc
) || (fcns
[idx
].pc
== 0)) {
988 sti
<((fcns
[idx
].flags
>> 1) & 0xf);
991 log_comment_add("st[%i]=%02hhx ",
992 sti
, read_mem(sw_stack_ptr
+ sti
, 0)
995 log_comment_add("\n\n");
997 if (fcns
[idx
].pc
== 0)
1000 pc
= fcns
[idx
].fcn_call(sw_stack_ptr
);
1003 log_comment_add("\n");
1004 log_comment_add(" Output: r3=%02hhx r2=%02hhx r1=%02hhx r0=%02hhx ",
1005 read_reg8(MAIN_REG_R3
, 0),
1006 read_reg8(MAIN_REG_R2
, 0),
1007 read_reg8(MAIN_REG_R1
, 0),
1008 read_reg8(MAIN_REG_R0
, 0)
1011 if (fcns
[idx
].flags
& 1) {
1012 for (unsigned sti
=0;sti
<4;sti
++) {
1013 log_comment_add("st[%i]=%02hhx ",
1014 sti
, read_mem(sw_stack_ptr
+ sti
, 0)
1018 log_comment_add("\n\n");
1026 if (flag_hit
== 0) {
1027 log_comment_add(" !!unknown routine @%04hx()\n", pc
);
1029 sim_breakpoint_set(SIM_BREAKPOINT_CODE
);