diff --git a/docs/DSA_Assembly_Reference.md b/docs/DSA_Assembly_Reference.md
index 7f99089..7c6a81d 100644
--- a/docs/DSA_Assembly_Reference.md
+++ b/docs/DSA_Assembly_Reference.md
@@ -42,20 +42,25 @@ stw rg0, rg1, 8 ; Store rg0 TO address (rg1+8)
| Register(s) | Type | Description | Usage Notes |
|-------------|------|-------------|-------------|
| **rg0-rgf** | General | 16 general-purpose registers | Use for variables, temporaries |
-| **acc** | Special | Accumulator | ⚠️ Volatile - pseudo-instructions may overwrite |
-| **spr** | Special | Stack pointer | Points to top of stack |
+| **acc** | Special | Accumulator | ⚠️ **VOLATILE** - Used as scratch by pseudo-instructions |
+| **spr** | Special | Stack pointer | Points to current top of stack |
| **bpr** | Special | Base pointer | Used for stack frames |
-| **ret** | Special | Return address | Holds return address for functions |
+| **ret** | Special | Return address | Holds function return addresses |
| **zero** | Read-only | Always zero | Reads return 0, writes discarded |
| **pcx** | Read-only | Program counter | Cannot be written directly |
| **idr** | Privileged | Interrupt descriptor table | Kernel mode only |
| **mmr** | Privileged | Memory map register | Kernel mode only |
| **noreg** | Placeholder | No register | Used in encoding, triggers fault if accessed |
+**Alternative Names:**
+- **noreg** can also be referenced as **null** in assembly
+
**Register Conventions:**
-- **acc**: Used by pseudo-instructions for temporary values - do not rely on it being preserved
-- **rgf**: Used by label-addressing pseudo-instructions as a scratch register
-- **rg0-rge**: Available for general use; calling convention defines which are preserved
+- **acc**: Volatile scratch register used by pseudo-instructions - **never preserved across pseudo-ops**
+- **rg0-rge**: Available for general use; calling convention defines preservation rules
+- **rgf**: General purpose register, available for use
+
+**⚠️ CRITICAL:** The `acc` register is used internally by label-based memory operations and other pseudo-instructions. Do not assume its value is preserved across any pseudo-instruction!
## Hardware Instructions
@@ -130,36 +135,50 @@ lli 0x1234, rg0 ; rg0 = 0x00001234
lui 0xABCD, rg0 ; rg0 = 0xABCD1234
```
+**Note:** The assembler may process the immediate value for `lui` - specify the upper 16 bits directly (e.g., `lui 0xABCD, rg0` to set upper bits to 0xABCD).
+
**Loading Addresses:** See `lwi` pseudo-instruction
### Jump and Branch Instructions
```asm
-jmp addr [, offset_reg] ; Unconditional jump
-jeq addr [, offset_reg] ; Jump if equal
-jne addr [, offset_reg] ; Jump if not equal
-jgt addr [, offset_reg] ; Jump if greater than
-jge addr [, offset_reg] ; Jump if greater or equal
-jlt addr [, offset_reg] ; Jump if less than
-jle addr [, offset_reg] ; Jump if less or equal
+jmp offset, base_reg ; Unconditional jump to (base_reg + offset)
+jeq offset, base_reg ; Jump if equal
+jne offset, base_reg ; Jump if not equal
+jgt offset, base_reg ; Jump if greater than
+jge offset, base_reg ; Jump if greater or equal
+jlt offset, base_reg ; Jump if less than
+jle offset, base_reg ; Jump if less or equal
+```
+
+**Target Address Calculation:**
+```
+target = base_reg + sign_extend(offset)
```
**Jump Modes:**
```asm
; Absolute jump (using zero register)
jmp label, zero ; Jump to label address
-jmp 0x4000, zero ; Jump to absolute address 0x4000
-; Register-based jump
+; Register-based jump
jmp 0, ret ; Jump to address in ret register
jmp 4, ret ; Jump to (ret + 4)
-; PC-relative (if assembler supports)
-jeq loop_start ; Jump to loop_start if equal flag set
+; PC-relative (if assembler supports label resolution)
+jeq loop_start, zero ; Jump to loop_start if equal flag set
```
**Conditional Jumps:** Based on flags set by `cmp` instruction
+**Examples:**
+```asm
+jmp start, zero ; Absolute jump to 'start'
+jmp 4, ret ; Jump to (ret + 4)
+jeq end, zero ; Jump to 'end' if equal flag set
+jgt loop, zero ; Jump to 'loop' if greater than flag set
+```
+
### Comparison
```asm
@@ -168,17 +187,17 @@ cmp reg1, reg2 ; Compare reg1 with reg2, set flags
**Flags Set:**
- Equal: `reg1 == reg2`
-- GreaterThan: `reg1 > reg2`
-- LessThan: `reg1 < reg2`
+- GreaterThan: `reg1 > reg2` (signed comparison)
+- LessThan: `reg1 < reg2` (signed comparison)
- GreaterThanOrEqual: `reg1 >= reg2`
- LessThanOrEqual: `reg1 <= reg2`
**Example:**
```asm
cmp rg0, zero ; Compare rg0 with 0
-jeq is_zero ; Branch if rg0 == 0
-jgt is_positive ; Branch if rg0 > 0
-jlt is_negative ; Branch if rg0 < 0
+jeq is_zero, zero ; Branch if rg0 == 0
+jgt is_positive, zero ; Branch if rg0 > 0
+jlt is_negative, zero ; Branch if rg0 < 0
```
### Arithmetic Instructions
@@ -186,8 +205,8 @@ jlt is_negative ; Branch if rg0 < 0
```asm
add src1, src2, dest ; dest = src1 + src2
sub src1, src2, dest ; dest = src1 - src2
-iadd src, immediate, dest ; dest = src + immediate
-isub src, immediate, dest ; dest = src - immediate
+iadd src, immediate, dest ; dest = src + immediate (DEST REQUIRED!)
+isub src, immediate, dest ; dest = src - immediate (DEST REQUIRED!)
inc reg ; reg = reg + 1
dec reg ; reg = reg - 1
```
@@ -196,13 +215,14 @@ dec reg ; reg = reg - 1
```asm
add rg0, rg1, rg2 ; rg2 = rg0 + rg1
sub rg0, rg1, rg2 ; rg2 = rg0 - rg1
-iadd rg0, 10, rg0 ; rg0 = rg0 + 10
+iadd rg0, 10, rg0 ; rg0 = rg0 + 10 (in-place)
+iadd rg0, 10, rg1 ; rg1 = rg0 + 10 (separate dest)
isub rg1, 5, rg2 ; rg2 = rg1 - 5
inc spr ; spr = spr + 1
dec spr ; spr = spr - 1
```
-**Note:** For `iadd`/`isub`, destination can be the same as source for in-place operations.
+**⚠️ Note:** For `iadd`/`isub`, the destination register is **required** (not optional). For in-place operations, specify the source register as both source and destination.
### Bitwise Logical Operations
@@ -232,14 +252,16 @@ shr reg, shift_amount ; Shift right by amount (0-31)
```
**Shift Amount:**
-- Can be a literal: `shl rg0, 2` (shift by 2)
-- Can be a register: `shl rg0, rg1` (shift by value in rg1, uses low 5 bits)
+- **Literal:** `shl rg0, 2` - shift by constant 2
+- **Register:** `shl rg0, rg1` - shift by value in rg1 (low 5 bits)
+
+**⚠️ Note:** Current assembler may only support literal shift amounts. Check your assembler documentation for register shift support.
**Examples:**
```asm
shl rg0, 2 ; rg0 = rg0 << 2
shr rg1, 3 ; rg1 = rg1 >> 3
-shl rg0, rg1 ; rg0 = rg0 << (rg1 & 0x1F)
+; shl rg0, rg1 ; May not be supported by assembler
```
**Note:** Shift right is logical (zero-fill), not arithmetic
@@ -265,6 +287,8 @@ irt ; Return from interrupt handler
Pseudo-instructions are assembly-level constructs that expand into one or more hardware instructions.
+**⚠️ IMPORTANT:** Many pseudo-instructions use the `acc` register as a scratch register. The value in `acc` is **not preserved** across these operations!
+
### Data Definition Directives
```asm
@@ -282,7 +306,7 @@ dw stack_base: 0x10000 ; Single word value
dw table: 0, 0, 0, 0 ; Array of 4 words
```
-**String Encoding:** Strings are encoded as byte sequences with escape sequences:
+**String Encoding:** Strings are automatically null-terminated and encoded as byte sequences with escape sequences:
- `\n` = newline (0x0A)
- `\t` = tab (0x09)
- `\r` = carriage return (0x0D)
@@ -290,6 +314,8 @@ dw table: 0, 0, 0, 0 ; Array of 4 words
- `\"` = double quote
- `\0` = null (0x00)
+**⚠️ Endianness Note:** Numeric values in data directives are stored in **big-endian** format by the assembler, unlike the little-endian used for instructions.
+
### Memory Reservation Directives
```asm
@@ -314,19 +340,19 @@ push reg ; Push register onto stack
pop reg ; Pop stack into register
```
+**⚠️ CRITICAL - Stack Direction:** The DSA stack grows **DOWNWARD** (toward lower memory addresses).
+
**Expansion:**
```asm
; push rg0 expands to:
-iadd spr, 4, spr ; spr = spr + 4 (stack grows up)
+subi spr, 4, spr ; spr = spr - 4 (allocate space, stack grows down)
stw rg0, spr, 0 ; Store rg0 to [spr]
; pop rg0 expands to:
ldw spr, rg0, 0 ; Load [spr] into rg0
-isub spr, 4, spr ; spr = spr - 4
+addi spr, 4, spr ; spr = spr + 4 (deallocate space)
```
-**Note:** DSA stack grows upward (toward higher addresses).
-
**Examples:**
```asm
push rg0 ; Save rg0 on stack
@@ -336,6 +362,51 @@ pop rg1 ; Restore rg1
pop rg0 ; Restore rg0
```
+**Stack Diagram:**
+```
+Higher Memory Addresses
+ ↑
+ │ (old data)
+ ├─────────────┤
+ │ rg0 value │ ← After first push
+ ├─────────────┤ ← SPR after first push
+ │ rg1 value │ ← After second push
+ ├─────────────┤ ← SPR after second push (stack grew down)
+ ↓
+Lower Memory Addresses
+```
+
+### Push/Pop Multiple Registers
+
+```asm
+pusha count ; Push first 'count' general registers (rg0-rgN)
+popa count ; Pop first 'count' general registers
+```
+
+**Examples:**
+```asm
+pusha 4 ; Push rg0, rg1, rg2, rg3
+; ... do work ...
+popa 4 ; Pop rg3, rg2, rg1, rg0
+```
+
+**Expansion:**
+```asm
+; pusha 3 expands to:
+subi spr, 12, spr ; Allocate space for 3 words
+stw rg0, spr, 0 ; Store rg0
+stw rg1, spr, 4 ; Store rg1
+stw rg2, spr, 8 ; Store rg2
+
+; popa 3 expands to:
+ldw spr, rg0, 0 ; Load rg0
+ldw spr, rg1, 4 ; Load rg1
+ldw spr, rg2, 8 ; Load rg2
+addi spr, 12, spr ; Deallocate space
+```
+
+**Note:** Registers are pushed/popped in order (rg0, rg1, rg2, ...).
+
### Load Address Pseudo-Instruction
```asm
@@ -354,7 +425,7 @@ lui message, rg0 ; Load upper 16 bits of address
db message: "Hello!", 0
lwi message, rg0 ; rg0 = address of message
-ldb rg0, rg1 ; rg1 = first byte of message ('H')
+ldb rg0, rg1, 0 ; rg1 = first byte of message ('H')
```
### Memory Access with Labels
@@ -370,49 +441,66 @@ sth src_reg, label [, offset]
stw src_reg, label [, offset]
```
-**Expansion (uses rgf as scratch):**
+**⚠️ CRITICAL:** These pseudo-instructions use `acc` as a scratch register! The value in `acc` will be overwritten.
+
+**Expansion:**
```asm
-; ldb buffer, rg2 expands to:
-lli buffer, rgf ; Load lower 16 bits of buffer address
-lui buffer, rgf ; Load upper 16 bits of buffer address
-ldb rgf, rg2, 0 ; Load byte from address in rgf
+; ldw buffer, rg2 expands to:
+lli buffer, acc ; Load lower 16 bits of buffer address into acc
+lui buffer, acc ; Load upper 16 bits of buffer address into acc
+ldw acc, rg2, 0 ; Load word from address in acc into rg2
; stw rg1, current expands to:
-lli current, rgf ; Load lower 16 bits of current address
-lui current, rgf ; Load upper 16 bits of current address
-stw rg1, rgf, 0 ; Store word to address in rgf
+lli current, acc ; Load lower 16 bits of current address into acc
+lui current, acc ; Load upper 16 bits of current address into acc
+stw rg1, acc, 0 ; Store word from rg1 to address in acc
```
-**⚠️ Important:** These pseudo-instructions use `rgf` as a scratch register! Do not use `rgf` for other purposes when using label-based memory access.
-
**Examples:**
```asm
dw counter: 0
-ldw counter, rg0 ; Load value of counter
-iadd rg0, 1, rg0 ; Increment
-stw rg0, counter ; Store back
+ldw counter, rg0 ; Load value of counter (clobbers acc!)
+addi rg0, 1, rg0 ; Increment
+stw rg0, counter ; Store back (clobbers acc!)
```
-### Function Call Pseudo-Instructions
+**⚠️ Warning Example - ACC Clobbering:**
+```asm
+lli 100, acc ; acc = 100
+ldw data, rg0 ; ACC IS NOW OVERWRITTEN!
+; acc now contains garbage (address calculation temp)
+; The value 100 is LOST!
+```
+
+# DSA Assembly Language Reference - Part 2
+
+## Function Call Pseudo-Instructions
```asm
call namespace::function ; Call function from included module
return ; Return from function
```
-**Expansion:**
+**⚠️ CRITICAL:** The calling mechanism uses the **STACK** to store return addresses, not just the `ret` register!
+
+**CALL Expansion:**
```asm
; call print::print expands to:
-lwi print::print, ret ; Load function address into ret
-jmp 0, ret ; Jump to function (saves return in pcx)
-; (The assembler/linker resolves namespace::function to address)
-
-; return expands to:
-jmp 0, ret ; Jump to address in ret register
+subi spr, 4, spr ; Decrement stack pointer (allocate space)
+stw pcx, spr, 0 ; Store return address (PCX) on stack
+jmp function_addr, zero ; Jump to function address
```
-**Note:** The actual return address handling may be more complex depending on the calling convention.
+**RETURN Expansion:**
+```asm
+; return expands to:
+ldw spr, ret, 0 ; Load return address from stack into ret
+addi spr, 4, spr ; Increment stack pointer (deallocate)
+jmp 4, ret ; Jump to (ret + 4)
+```
+
+**Note on RETURN +4 Offset:** The implementation adds 4 to the return address. This may be to account for instruction sizing or pipeline considerations. Consult CPU documentation if modifying.
### Module System
@@ -437,25 +525,44 @@ call math::multiply
## Calling Convention
-DSA uses a standard calling convention for function calls.
+DSA uses a stack-based calling convention with downward-growing stack.
### Stack Frame Layout
+**⚠️ CRITICAL:** Stack grows DOWNWARD (toward lower addresses)!
+
```
-Higher Addresses
-├─────────────┤
-│ Arg N │ ← spr + (8 + 4*(N-1))
-│ ... │
-│ Arg 2 │ ← spr + 16
-│ Arg 1 │ ← spr + 12
-│ Arg 0 │ ← spr + 8 (first argument)
-├─────────────┤
-│ Ret Addr │ ← spr + 4 (return address)
-├─────────────┤
-│ Old BPR │ ← spr + 0 (saved base pointer)
-├─────────────┤ ← bpr, spr (current frame)
-│ Locals │ (local variables, if any)
-Lower Addresses
+Higher Memory Addresses ↑
+ │
+ ┌─────────────┐
+ │ Caller's │
+ │ Frame │
+ └─────────────┘
+ │ Arg N │ ← Caller pushed (highest address argument)
+ │ ... │
+ │ Arg 2 │
+ │ Arg 1 │
+ │ Arg 0 │ ← First argument (lowest address argument)
+ ├─────────────┤
+ │ Ret Addr │ ← Return address (pushed by CALL)
+ ├─────────────┤
+ │ Old BPR │ ← Saved base pointer (pushed by callee)
+ ├─────────────┤ ← BPR (current base), SPR (current top)
+ │ Locals │ ← Local variables (if any)
+ │ ... │
+ └─────────────┘ ← SPR grows downward
+ │
+Lower Memory Addresses ↓
+```
+
+**Frame Pointer Offsets** (from BPR):
+```
+bpr + 0 = Old BPR (saved by function prologue)
+bpr + 4 = Return address (pushed by CALL)
+bpr + 8 = Argument 0 (first argument)
+bpr + 12 = Argument 1
+bpr + 16 = Argument 2
+bpr + 8 + 4*N = Argument N
```
### Calling Sequence
@@ -464,19 +571,19 @@ Lower Addresses
1. **Push arguments in reverse order** (last argument first):
```asm
-push arg2
+push arg2 ; Push last argument first
push arg1
-push arg0
+push arg0 ; First argument pushed last
```
2. **Call the function:**
```asm
-call namespace::function
+call namespace::function ; Pushes return address, jumps to function
```
3. **Clean up arguments** after return:
```asm
-pop zero ; Discard or retrieve arg0
+pop zero ; Discard arg0 (or pop rg0 to get return value)
pop zero ; Discard arg1
pop zero ; Discard arg2
```
@@ -486,15 +593,15 @@ pop zero ; Discard arg2
1. **Set up stack frame:**
```asm
function:
- push bpr ; Save old base pointer
+ push bpr ; Save caller's base pointer
mov spr, bpr ; Establish new base pointer
```
2. **Access arguments:**
```asm
- ldw bpr, rg0, 8 ; Load arg0 from spr+8
- ldw bpr, rg1, 12 ; Load arg1 from spr+12
- ldw bpr, rg2, 16 ; Load arg2 from spr+16
+ ldw bpr, rg0, 8 ; Load arg0 from bpr+8
+ ldw bpr, rg1, 12 ; Load arg1 from bpr+12
+ ldw bpr, rg2, 16 ; Load arg2 from bpr+16
```
3. **Execute function body:**
@@ -503,56 +610,101 @@ function:
add rg0, rg1, acc ; Example: acc = arg0 + arg1
```
-4. **Store return value** (optional, overwrites arg0):
+4. **Store return value** (optional - overwrites arg0 location):
```asm
stw acc, bpr, 8 ; Store result where arg0 was
```
5. **Restore stack frame:**
```asm
- mov bpr, spr ; Restore stack pointer
- pop bpr ; Restore old base pointer
+ mov bpr, spr ; Restore stack pointer to base
+ pop bpr ; Restore caller's base pointer
```
6. **Return to caller:**
```asm
- return
+ return ; Pop return address and jump
```
-### Complete Example
+### Stack Evolution During Call
+
+**Before CALL:**
+```
+ ┌─────────────┐
+ │ Arg 2 │
+ │ Arg 1 │
+ │ Arg 0 │ ← SPR points here
+ └─────────────┘
+```
+
+**After CALL (before function prologue):**
+```
+ ┌─────────────┐
+ │ Arg 2 │
+ │ Arg 1 │
+ │ Arg 0 │
+ │ Ret Addr │ ← SPR points here (CALL pushed this)
+ └─────────────┘
+```
+
+**After Function Prologue:**
+```
+ ┌─────────────┐
+ │ Arg 2 │
+ │ Arg 1 │
+ │ Arg 0 │
+ │ Ret Addr │
+ │ Old BPR │ ← SPR and BPR point here
+ └─────────────┘
+```
+
+### Complete Calling Example
```asm
; Function: add two numbers
; Args: arg0, arg1
-; Returns: sum in arg0 position
+; Returns: sum (overwrites arg0 position)
add_function:
- push bpr ; Save base pointer
- mov spr, bpr ; Set up stack frame
+ ; Prologue
+ push bpr ; Save caller's base pointer
+ mov spr, bpr ; Set up our stack frame
- ldw bpr, rg0, 8 ; Load arg0
- ldw bpr, rg1, 12 ; Load arg1
+ ; Load arguments
+ ldw bpr, rg0, 8 ; rg0 = arg0
+ ldw bpr, rg1, 12 ; rg1 = arg1
+
+ ; Perform operation
add rg0, rg1, acc ; acc = arg0 + arg1
- stw acc, bpr, 8 ; Store result
+ ; Store return value (overwrites arg0 position)
+ stw acc, bpr, 8 ; Store result at bpr+8
- mov bpr, spr ; Restore stack
- pop bpr ; Restore base pointer
- return
+ ; Epilogue
+ mov bpr, spr ; Restore stack pointer
+ pop bpr ; Restore caller's base pointer
+ return ; Return to caller
-; Caller:
+; Caller example:
main:
+ ; Set up stack
lwi stack_base, bpr
mov bpr, spr
- lli 5, rg0
- lli 7, rg1
+ ; Prepare arguments
+ lli 5, rg0 ; First argument = 5
+ lli 7, rg1 ; Second argument = 7
- push rg1 ; Push arg1 (7)
- push rg0 ; Push arg0 (5)
+ ; Push arguments (reverse order!)
+ push rg1 ; Push arg1 (7) first
+ push rg0 ; Push arg0 (5) second
+
+ ; Call function
call local::add_function
- pop rg2 ; Get result (12)
- pop zero ; Discard arg1
+
+ ; Retrieve result and clean up
+ pop rg2 ; Get result (12) - was at arg0 position
+ pop zero ; Discard arg1 slot
hlt
@@ -561,20 +713,45 @@ dw stack_base: 0x10000
### Register Usage Conventions
-| Register(s) | Usage | Preserved? |
-|-------------|-------|------------|
-| rg0-rg3 | Function arguments, temporaries | No (caller-saved) |
-| rg4-rge | Local variables | Yes (callee-saved if used) |
-| rgf | Scratch (used by label addressing) | No |
-| acc | Temporary calculations | No |
-| spr | Stack pointer | Yes (must be restored) |
-| bpr | Base pointer | Yes (must be restored) |
-| ret | Return address | Managed by call/return |
+| Register(s) | Usage | Preserved Across Calls? |
+|-------------|-------|------------------------|
+| **rg0-rg3** | Function arguments, temporaries | No (caller-saved) |
+| **rg4-rge** | Local variables | Conditional (callee-saved if used) |
+| **rgf** | General purpose | Conditional (callee-saved if used) |
+| **acc** | Temporary calculations, scratch | **Never** (volatile) |
+| **spr** | Stack pointer | Yes (must be restored) |
+| **bpr** | Base pointer | Yes (must be restored) |
+| **ret** | Return address | Managed by call/return |
-**Notes:**
-- Functions should save and restore rg4-rge if they use them
-- rg0-rg3 may be overwritten by called functions
-- acc and rgf are volatile - assume they're overwritten
+**Preservation Rules:**
+- **Caller-saved (rg0-rg3, acc):** Caller must save these before calling if needed after
+- **Callee-saved (rg4-rgf):** Callee must save/restore if it uses them
+- **Always preserved (spr, bpr):** Must be restored to original values
+- **Never preserved (acc):** Assume destroyed by any operation
+
+**Example - Callee-Saved Registers:**
+```asm
+my_function:
+ push bpr
+ mov spr, bpr
+
+ ; We want to use rg4 and rg5 - must save them!
+ push rg4
+ push rg5
+
+ ; Use rg4 and rg5 for local work
+ lli 100, rg4
+ lli 200, rg5
+ add rg4, rg5, acc
+
+ ; Restore callee-saved registers before returning
+ pop rg5
+ pop rg4
+
+ mov bpr, spr
+ pop bpr
+ return
+```
## Complete Examples
@@ -586,18 +763,18 @@ dw stack_base: 0x10000
//
// Usage:
// include multiply "multiply.dsa"
-// push arg1
-// push arg0
+// push multiplicand
+// push multiplier
// call multiply::multiply
-// pop result
-// pop zero ; discard second argument
+// pop result ; Result is in arg0 position
+// pop zero ; Clean up arg1
multiply:
push bpr
mov spr, bpr
- ldw bpr, rg0, 8 ; Load multiplier
- ldw bpr, rg1, 12 ; Load multiplicand
+ ldw bpr, rg0, 8 ; Load multiplier (arg0)
+ ldw bpr, rg1, 12 ; Load multiplicand (arg1)
lli 0, acc ; Initialize result to 0
@@ -606,9 +783,9 @@ loop_start:
dec rg1 ; multiplicand--
cmp rg1, zero
- jgt loop_start ; Continue if multiplicand > 0
+ jgt loop_start, zero ; Continue if multiplicand > 0
- stw acc, bpr, 8 ; Store result for caller
+ stw acc, bpr, 8 ; Store result for caller (at arg0)
mov bpr, spr
pop bpr
@@ -639,19 +816,19 @@ print:
mov spr, bpr
ldw bpr, rg0, 8 ; Get string address argument
- ldw current, rg1 ; Get current cursor position
+ ldw current, rg1 ; Get current cursor position (clobbers acc!)
print_loop:
- ldb rg0, acc ; Load character
- stb acc, rg1 ; Store to display
+ ldb rg0, acc, 0 ; Load character
+ stb acc, rg1, 0 ; Store to display
- iadd rg0, 1, rg0 ; Advance string pointer
- iadd rg1, 1, rg1 ; Advance cursor
+ addi rg0, 1, rg0 ; Advance string pointer
+ addi rg1, 1, rg1 ; Advance cursor
cmp acc, zero ; Check for null terminator
- jne print_loop ; Continue if not null
+ jne print_loop, zero ; Continue if not null
- stw rg1, current ; Save cursor position
+ stw rg1, current ; Save cursor position (clobbers acc!)
mov bpr, spr
pop bpr
@@ -662,8 +839,8 @@ reset:
push bpr
mov spr, bpr
- ldw display, rg1 ; Load display base
- stw rg1, current ; Reset cursor to start
+ ldw display, rg1 ; Load display base (clobbers acc!)
+ stw rg1, current ; Reset cursor to start (clobbers acc!)
mov bpr, spr
pop bpr
@@ -683,17 +860,17 @@ db string: "'To confuse your enemy, you must first confuse yourself' - Probably
init:
// Set up stack
- ldw stack, bpr
+ ldw stack, bpr ; Load stack base (clobbers acc!)
mov bpr, spr
start:
// Load string address
- lwi string, rg1
+ lwi string, rg1 ; Load address of string
// Call print function
push rg1
call print::print
- pop rg1 ; Clean up (rg1 now contains arg we passed)
+ pop rg1 ; Clean up (or pop zero to discard)
hlt
```
@@ -706,27 +883,24 @@ start:
dw value: 42
main:
- ldw value, rg0
+ ldw value, rg0 ; Load value (clobbers acc!)
cmp rg0, zero
- jeq is_zero
- jgt is_positive
- jlt is_negative
+ jeq is_zero, zero
+ jgt is_positive, zero
+ jlt is_negative, zero
is_zero:
- // Handle zero case
lwi zero_msg, rg1
- jmp print_and_exit
+ jmp print_and_exit, zero
is_positive:
- // Handle positive case
lwi positive_msg, rg1
- jmp print_and_exit
+ jmp print_and_exit, zero
is_negative:
- // Handle negative case
lwi negative_msg, rg1
- jmp print_and_exit
+ jmp print_and_exit, zero
print_and_exit:
push rg1
@@ -747,21 +921,21 @@ db negative_msg: "Value is negative", 0
dw stack: 0x10000
main:
- ldw stack, bpr
+ ldw stack, bpr ; Set up stack
mov bpr, spr
lli 0, rg0 ; Counter = 0
lli 10, rg1 ; Limit = 10
loop:
- // Do something with counter in rg0
+ // Process counter value
push rg0
call process_value
pop zero
inc rg0 ; Counter++
cmp rg0, rg1 ; Compare with limit
- jlt loop ; Loop if counter < limit
+ jlt loop, zero ; Loop if counter < limit
hlt
@@ -780,61 +954,73 @@ process_value:
## Best Practices
### 1. Stack Management
-- Always balance push/pop operations
-- Set up stack frame in every function
-- Clean up arguments after function calls
+- **Always balance push/pop operations** in the same function
+- Set up stack frame (`push bpr; mov spr, bpr`) in every function
+- Clean up arguments after function calls (caller's responsibility)
- Use `pop zero` to discard unwanted values
+- Remember: stack grows DOWNWARD
### 2. Register Usage
-- Don't rely on `acc` being preserved
-- Don't use `rgf` for variables (used by label addressing)
-- Save callee-saved registers if you modify them
+- **Never rely on `acc` being preserved** across ANY operation
+- Treat `acc` as write-only temporary storage
+- Save caller-saved registers (rg0-rg3) before calls if needed
+- Restore callee-saved registers (rg4-rgf) if modified
- Use `zero` register for zero constants
### 3. Memory Access
- Ensure proper alignment for halfword/word access
-- Use label-based addressing for clearer code
+- Be aware that label-based loads/stores clobber `acc`
+- Prefer register-based addressing when `acc` value matters
- Check that labels are defined before use
### 4. Function Design
-- Document calling convention in comments
+- **Document calling convention** in function comments
+- Always include prologue and epilogue
- Validate input arguments when appropriate
-- Use consistent parameter order
-- Return values via stack or designated register
+- Use consistent parameter order across related functions
+- Return values via stack (overwrite arg0) or designated register
### 5. Code Organization
-- Use meaningful label names
+- Use meaningful label names (e.g., `loop_start` not `l1`)
- Comment complex operations
- Group related functions in modules
- Use includes for code reuse
+- Keep functions focused and small
-### 6. Performance
-- Minimize memory accesses (use registers)
+### 6. Performance Considerations
+- Minimize memory accesses (use registers when possible)
- Avoid unnecessary comparisons
-- Use shifts for multiplication/division by powers of 2
-- Consider instruction pipelining if supported
+- Use shifts for multiplication/division by powers of 2:
+ ```asm
+ shl rg0, 3 ; Multiply by 8 (2^3)
+ shr rg0, 2 ; Divide by 4 (2^2)
+ ```
+- Consider instruction pipelining if CPU supports it
-## Assembler Directives
+### 7. ACC Register Awareness
+**⚠️ CRITICAL - Common Mistakes:**
-### Alignment (if supported)
```asm
-.align 4 ; Align to 4-byte boundary
-.align 2 ; Align to 2-byte boundary
-```
+; WRONG - acc gets clobbered:
+lli 100, acc
+ldw data, rg0 ; acc is now GARBAGE!
+add acc, rg0, rg1 ; Using garbage value!
-### Origin (if supported)
-```asm
-.org 0x1000 ; Set location counter to 0x1000
-```
+; RIGHT - use a different register:
+lli 100, rg2
+ldw data, rg0 ; acc clobbered (don't care)
+add rg2, rg0, rg1 ; rg2 still has 100
-### Section Control (if supported)
-```asm
-.text ; Code section
-.data ; Data section
-.bss ; Uninitialized data section
-```
+; WRONG - assuming acc preserved across call:
+lli 42, acc
+call some_function
+add acc, rg0, rg1 ; acc probably destroyed!
-**Note:** Assembler directive support depends on the specific DSA assembler implementation.
+; RIGHT - use caller-saved register:
+lli 42, rg0
+call some_function
+add rg0, rg1, rg2 ; rg0 might be destroyed, so save it first!
+```
## Common Patterns
@@ -842,82 +1028,139 @@ process_value:
```asm
lli lower_16_bits, reg
lui upper_16_bits, reg
+
+; Example:
+lli 0x1234, rg0 ; rg0 = 0x00001234
+lui 0xABCD, rg0 ; rg0 = 0xABCD1234
```
### Zero a Register
```asm
-mov zero, reg ; Method 1
-xor reg, reg, reg ; Method 2
-lli 0, reg ; Method 3
+mov zero, reg ; Method 1 (preferred - clearest)
+xor reg, reg, reg ; Method 2 (clever but less clear)
+lli 0, reg ; Method 3 (works but wastes upper bits clear)
```
### Copy Memory
```asm
-ldw src_addr, rg0 ; Load from source
-stw rg0, dest_addr ; Store to destination
+ldw src_addr, rg0 ; Load from source (clobbers acc)
+stw rg0, dest_addr, 0 ; Store to destination (clobbers acc)
+
+; If you need acc preserved:
+lli 0x1234, acc ; Some value in acc
+push acc ; Save it
+ldw src_addr, rg0 ; acc clobbered
+stw rg0, dest_addr, 0 ; acc clobbered again
+pop acc ; Restore acc
```
-### Multiply by Power of 2
+### Multiply/Divide by Power of 2
```asm
-shl reg, 3 ; Multiply by 8 (2^3)
-```
-
-### Divide by Power of 2
-```asm
-shr reg, 2 ; Divide by 4 (2^2)
+shl reg, 3 ; Multiply by 8 (2^3)
+shr reg, 2 ; Divide by 4 (2^2)
```
### Boolean NOT
```asm
cmp reg, zero
-jeq was_zero ; If reg == 0, result is 1
+jeq was_zero, zero ; If reg == 0, result is 1
lli 0, reg
-jmp done
+jmp done, zero
was_zero:
-lli 1, reg
+ lli 1, reg
done:
```
### Min/Max
```asm
; max(rg0, rg1) -> rg2
-mov rg0, rg2 ; Assume rg0 is max
+mov rg0, rg2 ; Assume rg0 is max
cmp rg0, rg1
-jge done
-mov rg1, rg2 ; rg1 was larger
+jge done, zero ; If rg0 >= rg1, we're done
+mov rg1, rg2 ; rg1 was larger
done:
```
+### Array Indexing
+```asm
+; Access array[i] where array is 32-bit words
+; rg0 = array base address
+; rg1 = index i
+; Result in rg2
+
+shl rg1, 2 ; Convert index to byte offset (i * 4)
+add rg0, rg1, acc ; acc = base + offset (use acc for temp)
+ldw acc, rg2, 0 ; Load array[i]
+```
+
## Troubleshooting
### Common Errors
**Alignment Fault:**
-- Check that halfword loads/stores use even addresses
-- Check that word loads/stores use addresses divisible by 4
+- Symptom: Exception when loading/storing halfword or word
+- Cause: Address not properly aligned
+- Fix: Ensure halfword addresses are even, word addresses divisible by 4
**Illegal Instruction:**
-- Verify opcode is valid
-- Check that shift amount is 0 for non-shift instructions
-- Ensure you're not using `noreg` as a source/destination
+- Symptom: Unexpected halt or exception
+- Cause: Invalid opcode or malformed instruction
+- Fix: Check assembly syntax, verify instruction encoding
**Stack Corruption:**
-- Verify push/pop balance
-- Check that functions restore `bpr` before returning
-- Ensure caller cleans up arguments
+- Symptom: Function returns to wrong address, registers have wrong values
+- Cause: Unbalanced push/pop, incorrect stack frame management
+- Fix:
+ - Verify push/pop balance
+ - Check function epilogue restores bpr
+ - Ensure caller cleans up arguments
+ - Verify stack grows downward (push decrements)
-**Wrong Results:**
-- Verify `lli` is called before `lui` when loading constants
-- Check that you're not relying on `acc` or `rgf` being preserved
-- Verify signed vs. unsigned loads (ldb vs. ldbs)
+**Wrong Results / Unexpected Values:**
+- Symptom: Calculations produce incorrect results
+- Cause: ACC clobbering, wrong register assumptions
+- Fix:
+ - Check if acc was assumed preserved (it never is!)
+ - Verify lli called before lui for 32-bit constants
+ - Check signed vs unsigned loads (ldb vs ldbs)
+ - Verify register preservation across calls
+
+**Label Not Found:**
+- Symptom: Assembler error about undefined label
+- Cause: Label used before definition, typo in label name
+- Fix: Define labels before use, check spelling
### Debugging Tips
-1. Add `nop` instructions as breakpoint markers
-2. Print register values using display memory
-3. Use single-step execution to trace program flow
-4. Verify stack pointer values at function boundaries
-5. Check label addresses in disassembly
+1. **Add NOP markers** at key points for breakpoints:
+ ```asm
+ nop ; Breakpoint here
+ ```
+
+2. **Print register values** using display memory:
+ ```asm
+ stw rg0, debug_out ; Store to known location
+ ```
+
+3. **Use single-step execution** to trace program flow
+
+4. **Verify stack pointer** values at function boundaries:
+ ```asm
+ ; After prologue, check:
+ ; spr == bpr (should point to same location)
+ ; After epilogue, check:
+ ; spr restored to entry value
+ ```
+
+5. **Check label addresses** in disassembly output
+
+6. **Trace ACC usage**:
+ ```asm
+ lli 0xDEAD, acc ; Marker value
+ ; ... your code ...
+ cmp acc, zero
+ jeq acc_was_clobbered, zero ; If acc==0, it was overwritten
+ ```
## Appendix: Instruction Quick Reference
@@ -933,12 +1176,24 @@ done:
| **Logical** | and, or, xor, not, nand, nor, xnor |
| **Shift** | shl, shr |
| **System** | hlt, nop, int, irt |
-| **Pseudo** | db, dh, dw, resb, resh, resw, push, pop, lwi, call, return, include |
+| **Pseudo - Data** | db, dh, dw, resb, resh, resw |
+| **Pseudo - Stack** | push, pop, pusha, popa |
+| **Pseudo - Memory** | lwi, ldb/ldh/ldw with labels, stb/sth/stw with labels |
+| **Pseudo - Control** | call, return |
+| **Pseudo - Module** | include |
## Version History
-- **v1.0** - Initial comprehensive reference
- - Combined hardware instructions and pseudo-instructions
- - Added complete calling convention
- - Included practical examples
- - Documented common patterns and best practices
+- **v2.0** - Corrected comprehensive reference based on implementation
+ - **CORRECTED:** Stack grows downward (not upward)
+ - **CORRECTED:** CALL/RETURN use stack for return addresses
+ - **CORRECTED:** Pseudo-instructions use ACC as scratch (not rgf)
+ - **CORRECTED:** Label loads use ACC for address calculation
+ - **CORRECTED:** IADD/ISUB require destination (not optional)
+ - **ADDED:** PUSHA/POPA documentation
+ - **ADDED:** Detailed ACC volatility warnings throughout
+ - **ADDED:** Stack evolution diagrams
+ - **CLARIFIED:** Big-endian data directive encoding
+ - **CLARIFIED:** Jump instruction semantics
+ - All examples updated to reflect correct stack direction
+ - Added extensive troubleshooting for ACC-related issues
diff --git a/docs/DSA_ISA_Specification.md b/docs/DSA_ISA_Specification.md
index c2973ee..fdb709d 100644
--- a/docs/DSA_ISA_Specification.md
+++ b/docs/DSA_ISA_Specification.md
@@ -12,7 +12,9 @@ The Damn Simple Architecture (DSA) is a 32-bit RISC-style architecture designed
| Halfword | 16 bits | 2-byte aligned |
| Word | 32 bits | 4-byte aligned |
-All multi-byte values use little-endian byte order.
+**Note on Endianness:**
+- Instructions and numeric data in memory: Little-endian
+- Data defined via `db/dh/dw` directives: Big-endian (assembler-specific)
## Registers
@@ -23,33 +25,32 @@ DSA provides 32 programmer-accessible registers plus several internal system reg
| Hex | Register | Type | Description |
|-----|----------|------|-------------|
| 0x00-0x0F | **rg0-rgf** | General Purpose | 16 general-purpose registers for variables and temporary values |
-| 0x10 | **acc** | Special | Accumulator for calculations and temporary storage
⚠️ May be overwritten by pseudo-instructions |
+| 0x10 | **acc** | Special | Accumulator for calculations and temporary storage
⚠️ Used as scratch by pseudo-instructions - volatile |
| 0x11 | **spr** | Special | Stack pointer - points to top of stack |
| 0x12 | **bpr** | Special | Base pointer - used for stack frame management |
-| 0x13 | **ret** | Special | Return address register - stores function return addresses |
+| 0x13 | **ret** | Special | Return address register - used for function returns |
| 0x14 | **idr** | Privileged | Interrupt descriptor table address
Read/write triggers protection fault in user mode |
| 0x15 | **mmr** | Privileged | Hardware memory map table address
Read/write triggers protection fault in user mode |
| 0x16 | **zero** | Read-only | Constant zero value
Reads always return 0, writes are discarded |
-| 0x17 | **noreg** | Placeholder | Indicates unused register field
Read/write triggers illegal instruction fault |
+| 0x17 | **noreg** | Placeholder | Indicates unused register field
Read/write triggers illegal instruction fault
Can also be referenced as **null** |
| 0x18-0x1F | - | Reserved | Reserved for future use |
+**System Registers (indices 0x18-0x1C):**
+These exist in the encoding space but are internal to the CPU implementation:
+
+| Hex | Register | Description |
+|-----|----------|-------------|
+| 0x18 | **mar** | Memory Address Register (CPU internal) |
+| 0x19 | **mdr** | Memory Data Register (CPU internal) |
+| 0x1A | **sts** | Status Register (CPU internal) |
+| 0x1B | **cir** | Current Instruction Register (CPU internal) |
+| 0x1C | **pcx** | Program Counter (read-only, special access) |
+
**Note on PCX (Program Counter):**
-- PCX is a read-only system register that can be accessed in some contexts
+- PCX can be read in certain contexts (e.g., stored during CALL)
- Writing to PCX triggers a protection fault
- PCX is automatically updated by jump and branch instructions
-### System Registers (Internal)
-
-These registers are used internally by the CPU and are not directly accessible via assembly instructions:
-
-| Register | Description |
-|----------|-------------|
-| **MAR** | Memory Address Register - holds address for memory operations |
-| **MDR** | Memory Data Register - holds data for memory transfers |
-| **CIR** | Current Instruction Register - holds instruction being executed |
-| **STS** | Status Register - stores comparison and arithmetic flags |
-| **PCX** | Program Counter - stores address of next instruction |
-
### Status Register (STS) Layout
The status register is a 32-bit register with the following flag bits:
@@ -108,7 +109,7 @@ Used for operations with a 16-bit immediate value.
**Usage:**
- Arithmetic: Immediate is a signed value
- Memory access: Immediate is a signed byte offset from base address
-- Branches: Immediate is a signed offset from current PCX
+- Branches: Immediate is a signed offset added to base register
- Literal loads: Immediate is unsigned 16-bit value
### J-Type (Jump) Instructions
@@ -131,7 +132,7 @@ Used for absolute jumps with large address ranges.
**Jump Range:** 256MB region around current PC (±128MB)
-**Note:** J-type instructions are defined but currently unused. Use I-type JMP with register addressing for long jumps.
+**Note:** J-type instructions are defined but currently unused. Use I-type JMP with register addressing for all jumps.
## Hardware Instructions
@@ -197,8 +198,8 @@ In machine code: SrcReg (SrcReg field), BaseReg (DestReg field), Offset (Immedia
| Hex | Mnemonic | Type | Operands | Description |
|-----|----------|------|----------|-------------|
-| 0x0B | **LLI** | I | DestReg, Value | Load 16-bit value into lower 16 bits
⚠️ **CLEARS upper 16 bits!** |
-| 0x0C | **LUI** | I | DestReg, Value | Load 16-bit value into upper 16 bits
Lower 16 bits unchanged |
+| 0x0B | **LLI** | I | Value, DestReg | Load 16-bit value into lower 16 bits
⚠️ **CLEARS upper 16 bits!** |
+| 0x0C | **LUI** | I | Value, DestReg | Load 16-bit value into upper 16 bits
Lower 16 bits unchanged |
**Usage for 32-bit Values:**
```
@@ -208,29 +209,38 @@ LUI 0xABCD, rg0 ; rg0 = 0xABCD1234
**⚠️ CRITICAL:** Always execute LLI before LUI, as LLI clears the upper 16 bits!
+**Note on LUI:** The assembler may shift the immediate value right by 16 bits when encoding, so specify the upper 16 bits directly (e.g., `LUI 0xABCD, rg0` not `LUI 0xABCD0000, rg0`).
+
**Encoding Note:**
-In machine code: Value (Immediate field), DestReg field (SrcReg unused, set to noreg)
+In machine code: Value (Immediate field), DestReg (SrcReg field for LLI, SrcReg field for LUI)
### Jump and Branch Instructions
| Hex | Mnemonic | Type | Operands | Description |
|-----|----------|------|----------|-------------|
-| 0x0D | **JMP** | I | DestReg, Offset | Unconditional jump to (DestReg + Offset) |
-| 0x0E | **JEQ** | I | DestReg, Offset | Jump if Equal flag set |
-| 0x0F | **JNE** | I | DestReg, Offset | Jump if Equal flag NOT set |
-| 0x10 | **JGT** | I | DestReg, Offset | Jump if GreaterThan flag set |
-| 0x11 | **JGE** | I | DestReg, Offset | Jump if GreaterThan OR Equal flag set |
-| 0x12 | **JLT** | I | DestReg, Offset | Jump if LessThan flag set |
-| 0x13 | **JLE** | I | DestReg, Offset | Jump if LessThan OR Equal flag set |
+| 0x0D | **JMP** | I | Offset, BaseReg | Unconditional jump to (BaseReg + Offset) |
+| 0x0E | **JEQ** | I | Offset, BaseReg | Jump if Equal flag set |
+| 0x0F | **JNE** | I | Offset, BaseReg | Jump if Equal flag NOT set |
+| 0x10 | **JGT** | I | Offset, BaseReg | Jump if GreaterThan flag set |
+| 0x11 | **JGE** | I | Offset, BaseReg | Jump if GreaterThan OR Equal flag set |
+| 0x12 | **JLT** | I | Offset, BaseReg | Jump if LessThan flag set |
+| 0x13 | **JLE** | I | Offset, BaseReg | Jump if LessThan OR Equal flag set |
**Jump Calculation:**
-- Target address = DestReg + SignExtend(Offset)
-- If DestReg = zero, this becomes absolute addressing with Offset
-- If DestReg = pcx, this becomes PC-relative addressing
+- Target address = BaseReg + SignExtend(Offset)
+- If BaseReg = zero, this becomes absolute addressing with Offset
+- If BaseReg = ret, this becomes return-style addressing
- Conditional jumps check flags in STS register
+**Common Patterns:**
+```
+JMP label, zero ; Absolute jump to label address
+JMP 0, ret ; Jump to address in ret register
+JMP 4, ret ; Jump to (ret + 4)
+```
+
**Encoding Note:**
-In machine code: DestReg field, Offset (Immediate field) (SrcReg unused, set to noreg)
+In machine code: Offset (Immediate field), BaseReg (SrcReg field) (DestReg unused, set to noreg)
### Comparison
@@ -265,8 +275,8 @@ DestReg and ShiftAmt fields unused (set to noreg and 0)
- Other flags undefined after arithmetic (use CMP for comparisons)
**Encoding Notes:**
-- INC/DEC: Reg in SrcReg1 field, also copied to DestReg field
-- IADD/ISUB: Immediate is signed 16-bit value
+- INC/DEC: Reg in SrcReg1 field, DestReg set to noreg
+- IADD/ISUB: Immediate is signed 16-bit value, all three operands required
### Bitwise Logical Operations
@@ -285,7 +295,7 @@ DestReg and ShiftAmt fields unused (set to noreg and 0)
- Other flags undefined
**Encoding Note:**
-NOT uses only Src and Dest; SrcReg2 unused (set to noreg)
+NOT uses only Src (SrcReg1) and Dest (DestReg); SrcReg2 unused (set to noreg)
### Shift Operations
@@ -295,17 +305,22 @@ NOT uses only Src and Dest; SrcReg2 unused (set to noreg)
| 0x18 | **SHR** | R | Reg, ShiftAmount | Shift Reg right by ShiftAmount bits
Zero-fill from left (logical shift) |
**Shift Amount:**
-- Can be a 5-bit literal (0-31) in ShiftAmt field
-- Can be a register value (low 5 bits used)
- - If using register: Place in SrcReg2, set ShiftAmt to 0
- - If using literal: Place in ShiftAmt field, set SrcReg2 to noreg
+- **Literal shifts**: ShiftAmount is a 5-bit literal (0-31) in assembly
+ - Stored in ShiftAmt field of instruction
+ - SrcReg2 set to noreg
+- **Register shifts**: ShiftAmount is a register containing shift value
+ - Register specified in SrcReg2 field
+ - ShiftAmt field must be 0
+ - Only low 5 bits of register value used
+
+**Note:** Current assembler implementation may only support literal shifts. Check assembler documentation.
**Flag Effects:**
- Zero flag set if result is zero
**Encoding Notes:**
-- Reg in both SrcReg1 and DestReg fields
-- For literal shifts: ShiftAmt field contains shift count
+- Reg in both SrcReg1 and DestReg fields (shifted in place)
+- For literal shifts: ShiftAmt field contains shift count, SrcReg2 = noreg
- For register shifts: SrcReg2 contains register, ShiftAmt must be 0
### System and Control Instructions
@@ -331,6 +346,17 @@ NOT uses only Src and Dest; SrcReg2 unused (set to noreg)
- INT: InterruptCode in low 8 bits of Immediate field
- IRT/HLT: All register fields set to noreg, ShiftAmt to 0
+### Meta Instructions (Assembler/Linker)
+
+These instructions are used by the assembler and linker but may not represent real CPU operations.
+
+| Hex | Mnemonic | Description |
+|-----|----------|-------------|
+| 0x27 | **SEGMENT** | Segment marker (implementation-specific) |
+| 0x3E | **DATA** | Raw data embedding |
+
+**Note:** The SEGMENT instruction opcode may vary between implementations (0x27 in assembler, 0x3F in some contexts). Consult your specific toolchain documentation.
+
## Instruction Summary Table
| Opcode | Mnemonic | Type | Category |
@@ -374,6 +400,8 @@ NOT uses only Src and Dest; SrcReg2 unused (set to noreg)
| 0x24 | HLT | R | System |
| 0x25 | IADD | I | Arithmetic |
| 0x26 | ISUB | I | Arithmetic |
+| 0x27 | SEGMENT | - | Meta |
+| 0x3E | DATA | - | Meta |
## Exception Conditions
@@ -393,9 +421,9 @@ See the DSA Assembly Language Reference for the complete calling convention and
## Notes on Design
1. **Word Size:** All addresses and general computation is 32-bit
-2. **Endianness:** Little-endian byte order
-3. **Stack Growth:** Stack grows upward (incrementing addresses)
+2. **Endianness:** Little-endian for instructions and runtime data; assembler data directives may use big-endian
+3. **Stack Growth:** Stack grows **downward** (toward lower addresses) - PUSH decrements SPR
4. **Alignment:** Natural alignment required for halfword and word accesses
5. **Sign Extension:** All immediate values are sign-extended unless noted
6. **Zero Register:** Provides constant zero, writes are legal but discarded
-7. **Reserved Encodings:** Opcodes 0x27-0x3F reserved for future use
+7. **Reserved Encodings:** Opcodes 0x27-0x3D and 0x3F reserved or implementation-specific
diff --git a/docs/DSA_Project_Roadmap.md b/docs/DSA_Project_Roadmap.md
index 9ad612a..19ecaf7 100644
--- a/docs/DSA_Project_Roadmap.md
+++ b/docs/DSA_Project_Roadmap.md
@@ -263,12 +263,12 @@
- [ ] Array syntax
- [ ] Struct syntax
- [x] Pointer syntax
- - [ ] Namespaced call syntax
+ - [x] Namespaced call syntax
- [x] AST node definitions
- [ ] Error recovery mechanisms
- [ ] Comprehensive parser tests
- [ ] Syntax error message quality testing
-- [ ] Implement C frontend by moving lexer/parser from `c_compiler` to the new `compiler` project structure
+- [x] Implement C frontend by moving lexer/parser from `c_compiler` to the new `compiler` project structure
- [ ] Evaluate possible memory management strategies (e.g., keep all variables on the stack vs spill only when calling functions)
---
@@ -290,7 +290,7 @@
- [ ] Optimize register allocation further
- [x] Implement proper function calling conventions
- [ ] Add constant folding optimization
-- [ ] Dead code elimination
+- [x] Dead code elimination
- [ ] Test each feature thoroughly
---
@@ -376,7 +376,7 @@
**Dependencies:** None
**Deliverable:** `docs/build-system-design.md`
-- [ ] Define project structure conventions
+- [x] Define project structure conventions
- [ ] Design build manifest format (`dsa-project.toml` or similar)
- [ ] Dependency resolution strategy
- [ ] Build cache design
@@ -391,12 +391,12 @@
**Dependencies:** 3.1.1, 1.2.2, 1.1.3, 2.1.3
**Deliverable:** `dsa-build` executable
-- [ ] Create crate: `dsa-build`
+- [x] Create crate: `dsa-build`
- [ ] Manifest parser
- [ ] Dependency graph builder
- [ ] Task orchestrator
- - [ ] Compilation tasks
- - [ ] Assembly tasks
+ - [x] Compilation tasks
+ - [x] Assembly tasks
- [ ] Linking tasks
- [ ] Build cache implementation
- [ ] Parallel build support
@@ -412,11 +412,11 @@
**Dependencies:** 3.1.2
**Deliverable:** Enhanced `dsa-build` with project management
-- [ ] `dsa new ` — Create new project
-- [ ] `dsa init` — Initialize in existing directory
+- [x] `dsa new ` — Create new project
+- [x] `dsa init` — Initialize in existing directory
- [ ] `dsa add ` — Add dependency
- [ ] Binary vs library project types
-- [ ] Template system for project scaffolding
+- [x] Template system for project scaffolding
- [ ] Documentation for each command
---