7 #include <netinet/in.h>
14 unsigned text_start
= ~0;
15 unsigned text_size
= 0;
16 unsigned mif_size
= 16384;
18 int rs232in_fd
, rs232out_fd
;
19 unsigned rs232in_data
= 0;
20 unsigned char rs232in_cnt
= 0;
21 unsigned rs232in_pending
= 0; // last one is simulation only
23 unsigned nsections
= 0;
24 unsigned section_start
[99];
25 unsigned section_size
[99];
26 static int text_segments
= 0;
30 #define H(x) (endian_is_big ? ntohs(x) : x)
31 #define W(x) (endian_is_big ? ntohl(x) : x)
33 void service_rs232(void)
36 * Check the serial port and update rs232in_data and
37 * rs232in_cnt accordingly.
39 if (rs232in_fd
>= 0 && !rs232in_pending
) {
41 int count
= read(rs232in_fd
, &ch
, 1);
43 rs232in_pending
= 3; // Minimum 2
49 void initialize_memory(void)
51 const unsigned megabyte
= 1024 * 1024;
54 // ensure_mapped_memory_range(0, megabyte); // XXX Don't !
55 ensure_mapped_memory_range(0x40000000, megabyte
);
56 // ensure_mapped_memory_range(0x90000000, megabyte);
57 // ensure_mapped_memory_range(0x80000000-megabyte+1, megabyte-1);
58 ensure_mapped_memory_range(0xBFC00000, megabyte
); // Really only 16KiB
64 for (p
= 0x40000000, k
= megabyte
; k
> 0; p
+= 4, k
-= 4)
65 store(p
, 0xe2e1e2e1, 4);
67 for (p
= 0x40000000, k
= megabyte
; k
> 0; p
+= 4, k
-= 4)
68 assert(load(p
, 4, 0) == 0xe2e1e2e1);
71 void ensure_mapped_memory_range(unsigned addr
, unsigned len
)
76 printf("Ensure mapped [%08x; %08x]\n", addr
, addr
+ len
- 1);
80 while (segment(addr
) != segment(addr
+ len
- 1)) {
81 ensure_mapped_memory_range(addr
, (1 << OFFSETBITS
) - offset(addr
));
82 addr
+= (1 << OFFSETBITS
) - offset(addr
);
83 assert(len
>= (1 << OFFSETBITS
) - offset(addr
));
84 len
-= (1 << OFFSETBITS
) - offset(addr
);
88 if (!addr_mapped(addr
+ len
- 1)) {
89 memory_segment_size
[seg
] = 1 + offset(addr
+ len
- 1);
91 realloc(memory_segment
[seg
], memory_segment_size
[seg
]);
94 printf("Segment %2d virt [%08x; %08x] phys [%p; %p]\n",
98 memory_segment
[seg
] + memory_segment_size
[seg
] - 1);
101 // Make sure it's good
102 *(char*)(memory_segment
[seg
] + memory_segment_size
[seg
] - 1) = 0;
105 assert(addr_mapped(addr
+ len
- 1));
108 void exception(char *kind
)
110 printf("Exception caught: %s\n", kind
);
114 void loadsection(FILE *f
, unsigned f_offset
, unsigned f_len
, unsigned m_addr
,
119 // m_len += 0x1000; // XXX Fudge factor? hw writes outside BBS
121 ensure_mapped_memory_range(m_addr
, m_len
);
123 section_start
[nsections
] = m_addr
;
124 section_size
[nsections
++] = m_len
;
125 assert(nsections
< sizeof section_start
/ sizeof(unsigned));
128 * We clear memory so that BBS doesn't need special
131 phys
= addr2phys(m_addr
);
132 memset(phys
, 0, m_len
);
134 fseek(f
, f_offset
, SEEK_SET
);
135 assert(segment(m_addr
) == segment(m_addr
+ m_len
)); // Handle that case later
136 fread(addr2phys(m_addr
), f_len
, 1, f
);
139 void readelf(char *name
)
141 static int memory_is_initialized
= 0;
148 FILE *f
= fopen(name
, "r");
151 fatal("Can't open %s\n", name
);
153 if (fread(&ehdr
, sizeof(ehdr
), 1, f
) != 1)
154 fatal("Can't read the ELF header of %s", name
);
156 if (strncmp((char *) ehdr
.e_ident
, ELFMAG
, SELFMAG
))
157 fatal("%s is not an ELF file\n", name
);
159 endian_is_big
= ehdr
.e_ident
[EI_DATA
] == 2;
162 * We can't initialize memory until we know the endian,
163 * otherwise the RTL view of memory will not match.
165 if (!memory_is_initialized
) {
167 memory_is_initialized
= 1;
172 if (H(ehdr
.e_type
) != ET_EXEC
)
173 fatal("%s is not an executable\n", name
);
175 if (H(ehdr
.e_machine
) != EM_MIPS
)
176 fatal("%s is not a MIPS executable\n", name
);
178 if (enable_verb_elf
) {
179 printf("%s:\n", name
);
180 printf("%sendian\n", endian_is_big
? "big" : "little");
181 printf("Entry: %08x\n", W(ehdr
.e_entry
)); /* Entry point virtual address */
182 printf("Proc Flags: %08x\n", W(ehdr
.e_flags
)); /* Processor-specific flags */
183 printf("Phdr.tbl entry cnt % 8d\n", H(ehdr
.e_phnum
)); /*Program header table entry count */
184 printf("Shdr.tbl entry cnt % 8d\n", H(ehdr
.e_shnum
)); /*Section header table entry count */
185 printf("Shdr.str tbl idx % 8d\n", H(ehdr
.e_shstrndx
)); /*Section header string table index */
187 program_entry
= W(ehdr
.e_entry
);
189 if (H(ehdr
.e_ehsize
) != sizeof(ehdr
)) {
190 fprintf(stderr
, "Oops, I can't handle this Elf header size");
194 phentsize
= H(ehdr
.e_phentsize
);
196 if (H(ehdr
.e_shentsize
) != sizeof(Elf32_Shdr
)) {
197 fprintf(stderr
, "Oops, I can't handle this Elf section header size");
201 // Allocate program headers
202 ph
= malloc(sizeof(*ph
) * H(ehdr
.e_phnum
));
204 for (i
= 0; i
< H(ehdr
.e_phnum
); ++i
) {
205 fseek(f
, W(ehdr
.e_phoff
) + i
* phentsize
, SEEK_SET
);
206 if (fread(&ph
[i
], sizeof(ph
[i
]), 1, f
) != 1)
207 fatal("Can't read a program header");
209 if (enable_verb_elf
) {
210 printf("\nProgram header #%d (%lx)\n", i
, ftell(f
));
211 printf(" type %08x\n", W(ph
[i
].p_type
));
212 printf(" filesz %08x\n", W(ph
[i
].p_filesz
));
213 printf(" offset %08x\n", W(ph
[i
].p_offset
));
214 printf(" vaddr %08x\n", W(ph
[i
].p_vaddr
));
215 printf(" paddr %08x\n", W(ph
[i
].p_paddr
));
216 printf(" memsz %08x\n", W(ph
[i
].p_memsz
));
217 printf(" flags %08x\n", W(ph
[i
].p_flags
));
218 printf(" align %08x\n", W(ph
[i
].p_align
));
221 if (enable_firmware_mode
&&
222 (W(ph
[i
].p_vaddr
) & 0xFFFF0000) != 0xBFC00000)
223 // we simulate the bare hardware, we cannot preload
224 // the sram. Thus we'll ignore everything that isn't
228 if (W(ph
[i
].p_type
) == PT_LOAD
) {
229 ensure_mapped_memory_range(W(ph
[i
].p_vaddr
),
231 if (W(ph
[i
].p_filesz
)) {
233 fprintf(stderr
, "Loading section [%08x; %08x]\n",
234 W(ph
[i
].p_vaddr
), W(ph
[i
].p_memsz
));
235 loadsection(f
, W(ph
[i
].p_offset
), W(ph
[i
].p_filesz
),
236 W(ph
[i
].p_vaddr
), W(ph
[i
].p_memsz
));
240 if (W(ph
[i
].p_flags
) & 1) {
241 // XXX I _think_ this means executable, but I
244 text_start
= W(ph
[i
].p_vaddr
);
245 text_size
= W(ph
[i
].p_memsz
);
249 if (enable_verb_elf
) {
252 fseek(f
, W(ehdr
.e_shoff
), SEEK_SET
);
253 for (i
= 0; i
< H(ehdr
.e_shnum
); ++i
) {
256 if (fread(&sh
, sizeof(sh
), 1, f
) != 1)
257 fatal("Can't read a section header");
259 printf("\nSection header #%d (%lx)\n", i
, ftell(f
));
260 printf(" name %08x\n", W(sh
.sh_name
));
261 printf(" type %08x\n", W(sh
.sh_type
));
262 printf(" flags %08x\n", W(sh
.sh_flags
));
263 printf(" addr %08x\n", W(sh
.sh_addr
));
264 printf(" offset %08x\n", W(sh
.sh_offset
));
265 printf(" size %08x\n", W(sh
.sh_size
));
266 printf(" link %08x\n", W(sh
.sh_link
));
267 printf(" info %08x\n", W(sh
.sh_info
));
268 printf(" addralign %08x\n", W(sh
.sh_addralign
));
269 printf(" entsize %08x\n", W(sh
.sh_entsize
));
271 printf(" (now at %lx)\n", ftell(f
));
275 void dis_load_store(char *buf
, char *name
, inst_t i
)
278 sprintf(buf
, "%-6s$%d,%d($%d)", name
, i
.r
.rt
, i
.i
.imm
, i
.r
.rs
);
280 sprintf(buf
, "%-6s$%d,($%d)", name
, i
.r
.rt
, i
.r
.rs
);
283 void dis_load_store_cp1(char *buf
, char *name
, inst_t i
)
286 sprintf(buf
, "%-6s$f%d,%d($%d)", name
, i
.r
.rt
, i
.i
.imm
, i
.r
.rs
);
288 sprintf(buf
, "%-6s$f%d,($%d)", name
, i
.r
.rt
, i
.r
.rs
);
291 void disass(unsigned pc
, inst_t i
)
294 unsigned npc
= pc
+ 4;
296 switch (i
.j
.opcode
) {
297 default: fatal("Unknown instruction opcode 0d%d", i
.j
.opcode
);
301 default: sprintf(buf
,"??0x%x?? $%d,$%d,%d", i
.r
.funct
, i
.r
.rd
, i
.r
.rt
, i
.r
.sa
);
304 if (i
.r
.rd
| i
.r
.rt
| i
.r
.sa
)
305 sprintf(buf
,"%-6s$%d,$%d,%d", "sll", i
.r
.rd
, i
.r
.rt
, i
.r
.sa
);
309 case SRL
: sprintf(buf
,"%-6s$%d,$%d,%d","srl", i
.r
.rd
, i
.r
.rt
, i
.r
.sa
); break;
310 case SRA
: sprintf(buf
,"%-6s$%d,$%d,%d","sra", i
.r
.rd
, i
.r
.rt
, i
.r
.sa
); break;
311 case SLLV
: sprintf(buf
,"%-6s$%d,$%d,$%d","sllv", i
.r
.rd
, i
.r
.rt
, i
.r
.rs
); break;
312 case SRLV
: sprintf(buf
,"%-6s$%d,$%d,$%d","srlv", i
.r
.rd
, i
.r
.rt
, i
.r
.rs
); break;
313 case SRAV
: sprintf(buf
,"%-6s$%d,$%d,$%d","srav", i
.r
.rd
, i
.r
.rt
, i
.r
.rs
); break;
314 case JR
: sprintf(buf
,"%-6s$%d","jr", i
.r
.rs
); break;
317 sprintf(buf
,"%-6s$%d","jalr", i
.r
.rs
);
319 sprintf(buf
,"%-6s$%d,$%d","jalr", i
.r
.rs
, i
.r
.rd
);
322 case SYSCALL
: sprintf(buf
,"%-6s","syscall"); break;
324 case MFHI
: sprintf(buf
,"%-6s$%d","mfhi", i
.r
.rd
); break;
325 case MTHI
: sprintf(buf
,"%-6s$%d","mthi", i
.r
.rs
); break;
326 case MFLO
: sprintf(buf
,"%-6s$%d","mflo", i
.r
.rd
); break;
327 case MTLO
: sprintf(buf
,"%-6s$%d","mtlo", i
.r
.rs
); break;
328 case MULT
: sprintf(buf
,"%-6s$%d,$%d","mult", i
.r
.rs
, i
.r
.rt
); break;
329 case MULTU
:sprintf(buf
,"%-6s$%d,$%d","multu", i
.r
.rs
, i
.r
.rt
); break;
330 case DIV
: sprintf(buf
,"%-6s$%d,$%d","div", i
.r
.rs
, i
.r
.rt
); break;
331 case DIVU
: sprintf(buf
,"%-6s$%d,$%d","divu", i
.r
.rs
, i
.r
.rt
); break;
332 case ADD
: sprintf(buf
,"%-6s$%d,$%d,$%d","add", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
335 sprintf(buf
,"%-6s$%d,$%d,$%d","addu", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
);
337 sprintf(buf
,"%-6s$%d,$%d","move", i
.r
.rd
, i
.r
.rs
);
339 case SUB
: sprintf(buf
,"%-6s$%d,$%d,$%d","sub", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
340 case SUBU
: sprintf(buf
,"%-6s$%d,$%d,$%d","subu", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
341 case AND
: sprintf(buf
,"%-6s$%d,$%d,$%d","and", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
344 sprintf(buf
,"%-6s$%d,$%d,$%d","or",i
.r
.rd
, i
.r
.rs
, i
.r
.rt
);
346 sprintf(buf
,"%-6s$%d,$%d","move",i
.r
.rd
, i
.r
.rs
);
348 case XOR
: sprintf(buf
,"%-6s$%d,$%d,$%d","xor", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
349 case NOR
: sprintf(buf
,"%-6s$%d,$%d,$%d","nor", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
350 case SLT
: sprintf(buf
,"%-6s$%d,$%d,$%d","slt", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
351 case SLTU
: sprintf(buf
,"%-6s$%d,$%d,$%d","sltu", i
.r
.rd
, i
.r
.rs
, i
.r
.rt
); break;
352 case TEQ
: sprintf(buf
,"%-6s$%d,$%d,%d","teq", i
.r
.rs
, i
.r
.rt
, i
.r
.sa
); break;
353 case BREAK
:sprintf(buf
,"%-6s","break"); break;
358 default: fatal("REGIMM rt=%d", i
.r
.rt
);
359 case BLTZ
: sprintf(buf
,"%-6s$%d,0x%08x","bltz", i
.r
.rs
, npc
+ (i
.i
.imm
<< 2)); break;
360 case BGEZ
: sprintf(buf
,"%-6s$%d,0x%08x","bgez", i
.r
.rs
, npc
+ (i
.i
.imm
<< 2)); break;
361 case BLTZAL
:sprintf(buf
,"%-6s$%d,0x%08x","bltzal", i
.r
.rs
, npc
+ (i
.i
.imm
<< 2)); break;
364 sprintf(buf
,"%-6s$%d,0x%08x","bgezal", i
.r
.rs
, npc
+ (i
.i
.imm
<< 2));
366 sprintf(buf
,"%-6s0x%08x","bal", npc
+ (i
.i
.imm
<< 2));
369 sprintf(buf
, "%-6s%d($%d)", "synci", i
.i
.imm
, i
.r
.rs
);
373 case J
: sprintf(buf
,"%-6s0x%08x","j", (npc
& ~((1<<28)-1)) | (i
.j
.offset
<< 2)); break;
374 case JAL
: sprintf(buf
,"%-6s0x%08x","jal", (npc
& ~((1<<28)-1)) | (i
.j
.offset
<< 2)); break;
377 sprintf(buf
,"%-6s$%d,$%d,0x%08x","beq", i
.r
.rs
, i
.r
.rt
, npc
+ (i
.i
.imm
<< 2));
379 sprintf(buf
,"%-6s0x%08x","b", npc
+ (i
.i
.imm
<< 2));
381 case BNE
: sprintf(buf
,"%-6s$%d,$%d,0x%08x","bne", i
.r
.rs
, i
.r
.rt
, npc
+ (i
.i
.imm
<< 2)); break;
382 case BLEZ
: sprintf(buf
,"%-6s$%d,$%d,0x%08x","blez", i
.r
.rs
, i
.r
.rt
, npc
+ (i
.i
.imm
<< 2)); break;
383 case BGTZ
: sprintf(buf
,"%-6s$%d,$%d,0x%08x","bgtz", i
.r
.rs
, i
.r
.rt
, npc
+ (i
.i
.imm
<< 2)); break;
384 case ADDI
: sprintf(buf
,"%-6s$%d,$%d,%d","addi", i
.r
.rt
, i
.r
.rs
, i
.i
.imm
); break;
387 sprintf(buf
,"%-6s$%d,$%d,%d","addiu", i
.r
.rt
, i
.r
.rs
, i
.i
.imm
);
389 sprintf(buf
,"%-6s$%d,%d","li", i
.r
.rt
, i
.i
.imm
);
391 case SLTI
: sprintf(buf
,"%-6s$%d,$%d,%d","slti", i
.r
.rt
, i
.r
.rs
, i
.i
.imm
); break;
392 case SLTIU
:sprintf(buf
,"%-6s$%d,$%d,%d","sltiu", i
.r
.rt
, i
.r
.rs
, i
.i
.imm
); break;
393 case ANDI
: sprintf(buf
,"%-6s$%d,$%d,0x%04x","andi", i
.r
.rt
, i
.r
.rs
, i
.u
.imm
); break;
394 case ORI
: sprintf(buf
,"%-6s$%d,$%d,0x%04x","ori", i
.r
.rt
, i
.r
.rs
, i
.u
.imm
); break;
395 case XORI
: sprintf(buf
,"%-6s$%d,$%d,0x%04x","xori", i
.r
.rt
, i
.r
.rs
, i
.u
.imm
); break;
396 case LUI
: sprintf(buf
,"%-6s$%d,0x%x","lui", i
.r
.rt
, i
.u
.imm
); break;
398 /* Two possible formats */
402 i
.r
.funct
== C0_TLBR
? "tlbr" :
403 i
.r
.funct
== C0_TLBWI
? "tlbwi" :
404 i
.r
.funct
== C0_TLBWR
? "tlbwr" :
405 i
.r
.funct
== C0_TLBP
? "tlbp" :
406 i
.r
.funct
== C0_ERET
? "eret" :
407 i
.r
.funct
== C0_DERET
? "deret" :
408 i
.r
.funct
== C0_WAIT
? "wait" :
411 /* Regular r format with i.r.rs[3] ? MT : MF */
413 "%-6s$%d,$%d (sel %d, rs %d)",
414 i
.r
.rs
& 4 ? "mtc0" : "mfc0",
421 40806800 mtc0 zero,$13
426 case CP1
: sprintf(buf
,"%-6s", "cp1"); break;
428 /* Two possible formats */
431 sprintf(buf
,"%-6s%08x", "cp2", i
.raw
); break;
433 /* Regular r format with i.r.rs[3] ? MT : MF */
435 "%-6s$%d,$%d (sel %d, rs %d)",
436 i
.r
.rs
& 4 ? "mtc2" : "mfc2",
442 case CP1X
: sprintf(buf
,"%-6s", "cp1x"); break;
443 case BEQL
: sprintf(buf
,"%-6s","bbql"); break;
445 if (i
.r
.funct
== 59) {
446 sprintf(buf
,"%-6s$%d,$%d", "rdhwr", i
.r
.rt
, i
.r
.rd
);
451 case LB
: dis_load_store(buf
, "lb", i
); break;
452 case LH
: dis_load_store(buf
, "lh", i
); break;
453 case LW
: dis_load_store(buf
, "lw", i
); break;
454 case LWL
: dis_load_store(buf
, "lwl", i
); break;
455 case LWR
: dis_load_store(buf
, "lwr", i
); break;
456 case LBU
: dis_load_store(buf
, "lbu", i
); break;
457 case LHU
: dis_load_store(buf
, "lhu", i
); break;
458 case SB
: dis_load_store(buf
, "sb", i
); break;
459 case SH
: dis_load_store(buf
, "sh", i
); break;
460 case SW
: dis_load_store(buf
, "sw", i
); break;
461 case SWL
: dis_load_store(buf
, "swl", i
); break;
462 case SWR
: dis_load_store(buf
, "swr", i
); break;
463 case LWC1
: dis_load_store_cp1(buf
, "lwc1", i
); break;
464 case SWC1
: dis_load_store_cp1(buf
, "swc1", i
); break;
465 case LDC1
: dis_load_store_cp1(buf
, "ldc1", i
); break;
466 case SDC1
: dis_load_store_cp1(buf
, "sdc1", i
); break;
468 printf("%-24s", buf
);
471 unsigned load(unsigned a
, // IN: address
472 int c
, // IN: count of bytes to load
473 int fetch
) // IN: instruction or data?
478 * Handle special load devices.
479 * So far we only have a serial output port.
481 if (!fetch
&& (a
>> 4) == 0xFF00000) {
482 switch ((a
>> 2) & 0xF) {
483 case 0: // rs232out_busy
485 serial_wait
--; // Not quite accurate, but ..
490 case 1: res
= rs232in_data
& 255;
492 fprintf(stderr
, "\nSERIAL INPUT '%c' (%d)\n",
498 if (rs232in_pending
> 1) {
499 if (--rs232in_pending
== 1)
502 res
= rs232in_cnt
; break;
510 fatal("Unknown register 0x%08x\n", a
);
517 case 1: return (res
>> (~a
& 3) * 8) & 0xFF;
518 case 2: return (res
>> (~a
& 1) * 16) & 0xFFFF;
524 if (!(addr_mapped(a
) && addr_mapped(a
+ c
- 1))) {
525 // fatal("Loading from outside memory 0x%08x\n", a);
526 fprintf(stderr
, "Loading from outside memory 0x%08x\n", a
);
531 if (!fetch
&& (a
& 0xFFF00000) == 0xBFC00000) {
532 fatal("\tloading from boot PROM 0x%08x\n", a
);
537 fatal("Unaligned load from 0x%08x\n", a
);
543 res
= *(u_int8_t
*)addr2phys(a
);
546 res
= H(*(u_int16_t
*)addr2phys(a
));
549 res
= W(*(u_int32_t
*)addr2phys(a
));
554 if (0 && enable_disass
&& !fetch
)
556 case 1: printf("\t\t\t\t\t%02x <- [%08x]\n",
559 case 2: printf("\t\t\t\t\t%04x <- [%08x]\n",
562 case 4: printf("\t\t\t\t\t%08x <- [%08x]\n",
570 void store(unsigned a
, unsigned v
, int c
)
576 * Handle special load devices.
577 * So far we only have a serial output port.
579 if (a
== 0xFF000000) {
580 unsigned char ch
= v
;
583 fprintf(stderr
, "\nSERIAL OUTPUT '%c' (%d)\n",
589 if (rs232out_fd
>= 0) {
590 // fputc(ch, stderr);
591 // fprintf(stderr, "SERIAL OUT '%c' (%d)\n", ch, ch);
592 write(rs232out_fd
, &ch
, 1);
597 if (!(addr_mapped(a
) && addr_mapped(a
+ c
- 1)))
598 fatal("\tstoring outside memory 0x%08x\n", a
);
600 if ((a
& 0xFFF00000) == 0xBFC00000) {
601 fatal("\tstoring to boot PROM 0x%08x\n", a
);
605 fatal("\tUnaligned store at 0x%08x\n", a
);
607 if (0 && enable_disass
)
609 case 1: printf("\t\t\t\t\t%02x -> [%08x] (was %02x)\n",
610 v
, a
, *(u_int8_t
*)addr2phys(a
));
612 case 2: printf("\t\t\t\t\t%04x -> [%08x] (was %04x)\n",
613 v
, a
, ntohs(*(u_int16_t
*)addr2phys(a
)));
615 case 4: printf("\t\t\t\t\t%08x -> [%08x] (was %08x)\n",
616 v
, a
, ntohl(*(u_int32_t
*)addr2phys(a
)));
621 case 1: *(u_int8_t
*)(phys
= addr2phys(a
)) = v
; break;
622 case 2: *(u_int16_t
*)(phys
= addr2phys(a
)) = H(v
); break;
623 case 4: *(u_int32_t
*)(phys
= addr2phys(a
)) = W(v
); break;
631 return (x
& 255) + ((x
>> 8) & 255) + ((x
>> 16) & 255) + ((x
>> 24) & 255);
636 unsigned p
= text_start
;
639 // assert(text_start == 0x80000000);
641 // This is used to dump to "prom" and doesn't need to be very general
642 assert(text_segments
== 1);
646 printf("-- yarisim generated Memory Initialization File (.mif)\n"
651 "ADDRESS_RADIX=HEX;\n"
658 for (i
= 0; p
< text_start
+ text_size
; p
+= 4, ++i
) {
659 unsigned data
= load(p
, 4, 1);
662 printf("%08X\n", data
);
663 else if (kind
== 'm') {
664 printf("\t%08x : %08x;\n", i
, data
);
666 unsigned char checksum
;
667 checksum
= 4 + chksum(i
) + chksum(data
);
668 printf(":04%04x00%08x%02x",
680 static void tinymon_cmd(unsigned char cmd
, unsigned val
)
682 unsigned char chk
= cmd
;
684 int leading_zero
= 1;
687 for (i
= 0; i
< 8; ++i
) {
688 unsigned char c
= "0123456789abcdef"[val
>> 28];
690 if ((val
>> 28) != 0 || !leading_zero
|| i
== 7) {
699 putchar("0123456789abcdef"[chk
>> 4]);
700 putchar("0123456789abcdef"[chk
& 15]);
705 void dump_tinymon_old(void)
711 for (k
= 0; k
< nsections
; ++k
) {
712 tinymon_cmd('l', section_start
[k
]);
713 unsigned end
= section_start
[k
] + section_size
[k
];
714 for (p
= section_start
[k
]; p
< end
; p
+= 4)
715 tinymon_cmd('w', load(p
, 4, 1));
718 tinymon_cmd('e', program_entry
);
722 * Base85 encoding inspired by git, though much simplified by only
723 * considering word-at-a-time encoding. This makes this encoding 3%
724 * less efficient which I think we can live with. Note, bigendian
725 * encoding in to slightly simplify the decoder.
727 static void tinymon_encode_word_base85(unsigned w
)
729 unsigned e
= w
% 85; w
/= 85;
730 unsigned d
= w
% 85; w
/= 85;
731 unsigned c
= w
% 85; w
/= 85;
732 unsigned b
= w
% 85; w
/= 85;
733 unsigned a
= w
% 85; w
/= 85;
743 * Dump the section in base85. Format:
745 * x <size in words> \n
746 * <5 base85 bytes encoding a word> repeat size times
747 * <5 base85 bytes encoding the checksum>
750 void dump_tinymon(void)
756 for (k
= 0; k
< nsections
; ++k
) {
757 unsigned w
= 0, chk
= 0;
758 unsigned end
= section_start
[k
] + section_size
[k
];
761 tinymon_cmd('l', section_start
[k
]);
762 tinymon_cmd('x', section_size
[k
] / 4);
763 for (b
= 1, p
= section_start
[k
]; p
< end
; p
+= 4, b
++) {
766 tinymon_encode_word_base85(w
);
769 putchar('\n'), b
= 0;
771 tinymon_encode_word_base85(-chk
);
775 tinymon_cmd('e', program_entry
);
780 // c-style-variables-are-local-p: t
781 // c-file-style: "linux"