diff options
-rw-r--r-- | cpu/cpu.ml | 54 | ||||
-rw-r--r-- | cpu/os.asm | 169 |
2 files changed, 187 insertions, 36 deletions
@@ -9,6 +9,8 @@ let dbg_read_data, save_dbg_read_data = loop 8 let dbg_wa, save_dbg_wa = loop 16 let dbg_write_data, save_dbg_write_data = loop 8 +let d7_out = Array.to_list (Array.init 8 (fun i -> let v, sl = loop 8 in ("d7_"^(string_of_int i), v, sl, i))) + let cpu_ram ra we wa d = (* Ram chip has word size = 8 bits and address size = 16 bits 0x0000 to 0x3FFF is ROM0 @@ -65,6 +67,12 @@ let cpu_ram ra we wa d = save_next_ser (mux read_ser ser (zeroes 8)) ^. mux read_ser read_data ser in + let read_data = List.fold_left + (fun rd (_, prevd7digit, setd7digit, i) -> + let save_that_digit = we ^& (eq_c 16 wa (0x4200 + i)) in + setd7digit (mux save_that_digit (reg 8 prevd7digit) d) ^. rd) + read_data d7_out in + save_dbg_ra ra ^. save_dbg_read_data read_data ^. save_dbg_wa wa ^. @@ -298,28 +306,30 @@ let p = "tick", 1; "ser_in", 8; ] - [ - "read_ilow", 1, rl; - "read_ihi", 1, rh; - "ex_instr", 1, ex; - "ex_finish", 1, exf; - "i", 16, i; - "ra", 16, dbg_ra; - "read_data", 8, dbg_read_data; - "wa", 16, dbg_wa; - "write_data", 8, dbg_write_data; - "pc", 16, pc; - "r0_Z", 16, r0; - "r1_A", 16, r1; - "r2_B", 16, r2; - "r3_C", 16, r3; - "r4_D", 16, r4; - "r5_E", 16, r5; - "r6_F", 16, r6; - "r7_G", 16, r7; - "ser_out", 8, ser_out; - "ser_in_busy", 1, ser_in_busy; - ] + ( + [ + "read_ilow", 1, rl; + "read_ihi", 1, rh; + "ex_instr", 1, ex; + "ex_finish", 1, exf; + "i", 16, i; + "ra", 16, dbg_ra; + "read_data", 8, dbg_read_data; + "wa", 16, dbg_wa; + "write_data", 8, dbg_write_data; + "pc", 16, pc; + "r0_Z", 16, r0; + "r1_A", 16, r1; + "r2_B", 16, r2; + "r3_C", 16, r3; + "r4_D", 16, r4; + "r5_E", 16, r5; + "r6_F", 16, r6; + "r7_G", 16, r7; + "ser_out", 8, ser_out; + "ser_in_busy", 1, ser_in_busy; + ] @ List.map (fun (name, out, _, _) -> (name, 8, out)) d7_out + ) let () = Netlist_printer.print_program stdout p @@ -37,13 +37,14 @@ _end_process_input: jz A _main_loop jal incr_clock - jal disp_time + jal disp_clock_d7 j _main_loop # PROCEDURE: incr_clock # ROLE: take into account seconds increment # ARGUMENTS: number of seconds to add, in register A incr_clock: + push RA jz A _incr_clock_ret lb B var_sec @@ -71,11 +72,8 @@ incr_clock: lb B var_day add B B A - lb C var_month - li D days_in_month - add D D C - lb C 0(D) - divu A B C + jal get_dom + divu A B A move B E sb B var_day jz A _incr_clock_ret @@ -94,12 +92,65 @@ incr_clock: _incr_clock_ret: + pop RA jr RA -# PROCEDURE: disp_clock -# ROLE: display current time +# PROCEDURE: get_dom +# ROLE: how many days in current month ? +# RETURN VALUE: the result, in register A. +# PRESERVES REGISTERS: B +get_dom: + lb C var_month + li D days_in_month + add D D C + lb A 0(D) + + jr RA + +# PROCEDURE: disp_clock_d7 +# ROLE: display current time (H M S) to D7 display # ARGUMENTS: none -disp_time: +disp_clock_d7: + li D 10 + + lb A var_sec + divu A A D + move B E + push B + push A + push D + + lb A var_min + divu A A D + move B E + push B + push A + push D + + lb A var_hour + divu A A D + move B E + push B + push A + + li D d7_digits + li C 8 + li B 0x4200 +_disp_d7_loop: + pop A + add A A D + lb A 0(A) + sb A 0(B) + incri B 1 + incri C -1 + jnz C _disp_d7_loop + + jr RA + +# PROCEDURE: disp_clock_ser +# ROLE: display current time to serial output +# ARGUMENTS: none +disp_clock_ser: push RA lw A var_year @@ -147,6 +198,7 @@ disp_time: # PROCEDURE: run_cmd # ROLE: execute and clear command stored in cmdline # ARGUMENTS: none +# COMMAND FORMAT:[hmsYMD][0-9]+ run_cmd: push RA @@ -156,12 +208,94 @@ run_cmd: jal ser_out_str li A endl jal ser_out_str + + li A cmdline + incri A 1 + li C 0 +_decode_digit_loop: + lb B 0(A) + jz B _decode_digit_end + li D 10 + mulu C C D + li D '0' + sub B B D + add C C B + incri A 1 + j _decode_digit_loop +_decode_digit_end: - li A error + li A cmdline + lb A 0(A) + + sei B A 's' + jz B _test_min + li D 60 + sleu D D C + jnz D _error_too_big + sb C var_sec + j _return_run_cmd + +_test_min: + sei B A 'm' + jz B _test_hour + li D 60 + sleu D D C + jnz D _error_too_big + sb C var_min + j _return_run_cmd + +_test_hour: + sei B A 'h' + jz B _test_day + li D 24 + sleu D D C + jnz D _error_too_big + sb C var_hour + j _return_run_cmd + +_test_day: + sei B A 'D' + jz B _test_month + move B C + incri B -1 + jal get_dom + sleu D A B + jnz D _error_too_big + sb B var_day + j _return_run_cmd + +_test_month: + sei B A 'M' + jz B _test_year + li D 12 + sleu D D C + jnz D _error_too_big + incri C -1 + sb C var_month + j _return_run_cmd + +_test_year: + sei B A 'Y' + jz B _test_anything_else + sb C var_year + j _return_run_cmd + +_test_anything_else: + jz A _return_run_cmd + j _error_no_such_var + +_error_too_big: + li A error_too_big jal ser_out_str + j _return_run_cmd - li A cmdline_used - sw Z 0(A) +_error_no_such_var: + li A error_no_such_var + jal ser_out_str + +_return_run_cmd: + sw Z cmdline_used + jal disp_clock_ser pop RA jr RA @@ -380,8 +514,10 @@ prompt: ascii "\n$ " endl: ascii "\n" -error: - ascii "Sorry but I'm to stupid to understand that.\n" +error_too_big: + ascii "That number is too big!\n" +error_no_such_var: + ascii "No such variable...\n" # For unit-tests @@ -408,6 +544,11 @@ test3: days_in_month: byte 31 28 31 30 31 30 31 31 30 31 30 31 +d7_digits: + byte 0b1110111 0b0100100 0b1011101 0b1101101 0b0101110 + byte 0b1101011 0b1111011 0b0100101 0b1111111 0b1101111 + byte 0 + .data # Space where command-line is buffered from serial input (256 bytes) |