isa/examples: distinguish between instr and data memory access. asm-version added.
authorBernhard Urban <lewurm@gmail.com>
Tue, 26 Oct 2010 17:48:30 +0000 (19:48 +0200)
committerBernhard Urban <lewurm@gmail.com>
Tue, 26 Oct 2010 17:48:30 +0000 (19:48 +0200)
99 instructions so far :)

2_isa/src/bootrom.c
2_isa/src/bootrom.s [new file with mode: 0644]

index d6e672eb32c55a1d3dac4de3aced68da5d0c7ed3..254faed0073fd6e62ef4e26863edb72feb89f9d7 100644 (file)
  * 'R'0xZZZZZZZZ          | H -> C    | read instr from address (0xZZ..Z)
  * 'F'0xYYYYYYYY          | C -> H    | instr read done and return instr
  *
+ * 'Q'0xZZZZZZZZ0xYYYYYYYY| H -> C    | write data (0xYY...Y) to
+ *                                    | address (0xZZ...Z)
+ * 'A'                    | C -> H    | data write done
+ *
+ * 'T'0xZZZZZZZZ          | H -> C    | read data from address (0xZZ..Z)
+ * 'G'0xYYYYYYYY          | C -> H    | read done and return data
+ *
  * 'J'0xZZZZZZZZ          | H -> C    | jump to address (0xZZ...Z)
  */
 
 #define UART_RECV_NEW 1
 
 /* TODO:
- * - use different read/write functions for instr and data space
- * - need absolute jump for program entry?
+ * - need jump to register value
+ * - uart: clear new_receive bit after the byte is copied?
+ *   (implementation issue...)
  */
 
+/* {d,i}{read,write}{8,32}:
+ * d ... data space
+ * i ... instruction space
+ */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
 void send_byte(u8 x)
 {
-       while(!(UART_STATUS & (1 << UART_TRANS_EMPTY)));
-       write8(UART_TRANS, x);
+       while(!(dread32(UART_STATUS) & (1 << UART_TRANS_EMPTY)));
+       dwrite8(UART_TRANS, x);
 }
 
 void send_word(u32 x)
@@ -49,8 +65,8 @@ void send_word(u32 x)
 u8 recv_byte(void)
 {
        u8 ret;
-       while(!(UART_STATUS & (1 << UART_RECV_NEW)));
-       ret = read8(UART_RECV);
+       while(!(dread32(UART_STATUS) & (1 << UART_RECV_NEW)));
+       ret = dread8(UART_RECV);
 }
 
 u32 recv_word(void)
@@ -73,15 +89,28 @@ void bootrom(void)
                                addr = recv_word();
                                instr = recv_word();
                                /* write to programm space */
-                               write32(addr, instr);
+                               iwrite32(addr, instr);
                                send_byte('D');
                                break;
                        case 'R':
                                addr = recv_word();
-                               instr = read32(addr);
+                               instr = iread32(addr);
                                send_byte('F');
                                send_word(instr);
                                break;
+                       case 'Q':
+                               addr = recv_word();
+                               instr = recv_word();
+                               /* write to data space */
+                               dwrite32(addr, instr);
+                               send_byte('A');
+                               break;
+                       case 'T':
+                               addr = recv_word();
+                               instr = dread32(addr);
+                               send_byte('G');
+                               send_word(instr);
+                               break;
                        case 'J':
                                addr = recv_word();
                                jump_to_instr_mem(addr);
@@ -105,11 +134,10 @@ void main(void)
        u32 to = TIMEOUT_START;
        u8 rec;
 
-       /* until to overflows */
+       /* until to is zeros */
        while(to != 0) {
-               /* noob timeout hack */
-               to++;
-               if(UART_STATUS & (1 << UART_RECV_NEW)) {
+               to--;
+               if(dread32(UART_STATUS) & (1 << UART_RECV_NEW)) {
                        rec = read8(UART_RECV);
                        if(rec == 'H') {
                                send_byte('O');
diff --git a/2_isa/src/bootrom.s b/2_isa/src/bootrom.s
new file mode 100644 (file)
index 0000000..9ae2570
--- /dev/null
@@ -0,0 +1,171 @@
+       .data
+
+       .text
+       ; r0 .. param0
+       ; r1 .. param1
+       ; r2 .. param2
+       ; r15 .. stackpointer
+       ; r0 .. return
+
+       ; TODO: will the assembler be able to evaluate these expressions?
+       UART_BASE=0x1000
+       UART_STATUS=(UART_BASE+0x4)
+       UART_RECV=(UART_BASE+0x8)
+       UART_TRANS=(UART_BASE+0xC)
+       UART_BAUD=(UART_BAUD+0x10)
+
+       UART_TRANS_EMPTY=0
+       UART_RECV_NEW=1
+
+send_byte:
+       ldil r3, UART_STATUS@lo 
+       ldih r3, UART_STATUS@hi
+       andi r3, r3, 1 << UART_TRANS_EMPTY
+       jumpzs+ send_byte ; jump if zero
+       ldil r3, UART_TRANS@lo  
+       ldih r3, UART_TRANS@hi
+       stb r0, 0(r3)
+       ret
+
+send_word:
+       ; TODO: loop? (less codesize...)
+       branch send_byte
+       lrs r0, r0, 8
+       branch send_byte
+       lrs r0, r0, 8
+       branch send_byte
+       lrs r0, r0, 8
+       branch send_byte
+       ret
+
+recv_byte:
+       ldil r3, UART_STATUS@lo 
+       ldih r3, UART_STATUS@hi
+       andi r3, r3, 1 << UART_RECV_NEW
+       jumpzs+ send_byte ; jump if zero
+       ldil r3, UART_RECV@lo   
+       ldih r3, UART_RECV@hi
+       lwb r0, 0(r3)
+       ret
+
+recv_word:
+       ldil r1, 0x0 
+       branch recv_byte
+       or r1, r1, r0
+
+       branch recv_byte
+       sll r0, r0, 8
+       or r1, r1, r0
+
+       branch recv_byte
+       sll r0, r0, 16
+       or r1, r1, r0
+
+       branch recv_byte
+       sll r0, r0, 24
+       or r1, r1, r0
+
+       addi r0, r1, 0x0
+       ret
+
+
+bootrom:
+       branch recv_byte
+
+       cmpi r0, 0x57 ; 'W'
+       jumpeq- bt_W
+
+       cmpi r0, 0x52 ; 'R'
+       jumpeq- bt_R
+
+       cmpi r0, 0x51 ; 'Q'
+       jumpeq- bt_Q
+
+       cmpi r0, 0x54 ; 'T'
+       jumpeq- bt_T
+
+       cmpi r0, 0x4a ; 'J'
+       jumpeq- bt_J
+
+       ; cmpi r0, 0x48 ; 'H'
+       ; jumpeq bt_H
+       ; FALL THROUGH ;)
+
+bt_H:
+       ldisl r0, 0x4f ; 'O'
+       branch send_byte
+       jump bootrom
+
+bt_W:
+       branch recv_word ; receive addr
+       addi r6, r0, 0x0
+       branch recv_word ; receive instr
+       stx r0, 0(r6)
+       ldisl r0, 0x44 ; 'D'
+       branch send_byte
+       jump bootrom
+
+bt_R:
+       branch recv_word ; receive addr
+       ldx r1, 0(r0)
+       ldisl r0, 0x46 ; 'F'
+       branch send_byte
+       addi r0, r1, 0x0
+       branch send_word
+       jump bootrom
+
+bt_Q:
+       branch recv_word ; receive addr
+       addi r6, r0, 0x0
+       branch recv_word ; receive data
+       stw r0, 0(r6)
+       ldisl r0, 0x41 ; 'A'
+       branch send_byte
+       jump bootrom
+
+bt_T:
+       branch recv_word ; receive addr
+       ldw r1, 0(r0)
+       ldisl r0, 0x47 ; 'G'
+       branch send_byte
+       addi r0, r1, 0x0
+       branch send_word
+       jump bootrom
+
+bt_J:
+       branch recv_word
+       jumpreg r0
+
+       
+       TIMEOUT_START=0x13371337
+       DEFAULT_PROG_START=0x200
+       STACKSTART=0x500 ; FIXME
+main:
+       ; setup stackframe
+       ldil r15, STACKSTART@lo 
+       ldih r15, STACKSTART@hi
+
+       ldil r3, TIMEOUT_START@lo       
+       ldih r3, TIMEOUT_START@hi
+
+timeout_loop:
+       ldil r3, UART_STATUS@lo 
+       ldih r3, UART_STATUS@hi
+       andi r3, r3, 1 << UART_RECV_NEW
+       jumpzs+ next; jump if zero
+
+       branch recv_byte
+       ; we received the enter bootrom sign
+       cmp r0, 0x48 ; 'H'
+       jumpeq- bt_H
+
+next:
+       subi r3, r3, 1
+       jumpnz+ timeout_loop
+       
+       ; branch to default entry point
+       ldil r0, DEFAULT_PROG_START@lo  
+       ldih r0, DEFAULT_PROG_START@hi
+       jumpreg r0
+
+; 99 instr. please update after modification