Direct use of ldcode stcode for memory access - retrotruestory/M1DEV GitHub Wiki

Here's how to optimize memory access using Magic-1's ldcode and stcode instructions:

        .cseg
        .global _fast_code_read
        .global _fast_code_write
        .global _fast_code_copy

// Fast code space read
// uint16_t fast_code_read(void* addr)
_fast_code_read:
        enter   4           ; Setup stack frame
        push    b           ; Save register B
        
        ld.16   b,6(sp)    ; Load source address into B
        ldcode.16 a,(b)    ; Direct read from code space
        
        pop     b           ; Restore B
        leave
        ret

// Fast code space write
// void fast_code_write(void* addr, uint16_t value)
_fast_code_write:
        enter   4
        push    b
        
        ld.16   b,6(sp)    ; Load destination address
        ld.16   a,8(sp)    ; Load value to write
        stcode.16 (b),a    ; Direct write to code space
        
        pop     b
        leave
        ret

// Fast code space copy
// void fast_code_copy(void* dst, void* src, uint16_t count)
_fast_code_copy:
        enter   8
        push    a
        push    b
        push    c
        
        ld.16   b,12(sp)   ; Load destination
        ld.16   a,14(sp)   ; Load source
        ld.16   c,16(sp)   ; Load count
        
.loop:
        ldcode.16 a,(b)    ; Read from code space
        stcode.16 (b),a    ; Write to code space
        add.16  b,#2       ; Increment pointers
        sub.16  c,#2       ; Decrement count
        br.ne   .loop      ; Continue if not done
        
        pop     c
        pop     b
        pop     a
        leave
        ret

Create a C interface:

#ifndef FAST_ACCESS_H
#define FAST_ACCESS_H

#include <stdint.h>

extern uint16_t fast_code_read(void* addr);
extern void fast_code_write(void* addr, uint16_t value);
extern void fast_code_copy(void* dst, void* src, uint16_t count);

#endif

Example usage:

#include <stdio.h>
#include "fast_access.h"

int main() {
    uint16_t code_buffer[256];
    uint16_t dest_buffer[256];
    
    // Write to code space
    fast_code_write(&code_buffer[0], 0x1234);
    
    // Read from code space
    uint16_t value = fast_code_read(&code_buffer[0]);
    
    // Copy between code spaces
    fast_code_copy(dest_buffer, code_buffer, sizeof(code_buffer));
    
    return 0;
}

Update Makefile:

CC = clcc
AS = m1_as
CFLAGS = -O2 
OBJECTS = fast_access.o test_access.o

test_access: $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(OBJECTS)

%.o: %.s
    $(AS) -o $@ $<

%.o: %.c
    $(CC) $(CFLAGS) -c $<

clean:
    rm -f test_access *.o

Key features:

  • Direct use of ldcode/stcode instructions for fast memory access
  • No translation/page table overhead
  • Optimized for code space operations
  • Efficient for ROM/flash memory access
  • Useful for bootloader and low-level system code

This implementation is particularly efficient for:

  • Accessing program code
  • Boot ROM operations
  • Code patching/modification
  • Fast memory-mapped device access
⚠️ **GitHub.com Fallback** ⚠️