https://bitbucket.org/coutts/5dplus
Raw File
Tip revision: 0d7cbec6dea8a278a468d89a5bf23bf5670a3172 authored by Coutts on 21 June 2012, 12:32:49 UTC
Fix font sizes (thanks Alex!) and fixed problem of bmp_buffer moving around, using a pointer to the bmp_vram now instead of the raw address. Also testing ML menu with skeleton shoot menu, not working yet though.
Tip revision: 0d7cbec
arm-mcr.h
/** \file
 * ARM control registers
 */
/*
 * Copyright (C) 2009 Trammell Hudson <hudson+ml@osresearch.net>
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#ifndef _arm_mcr_h_
#define _arm_mcr_h_

asm(
    ".text\n"
    ".align 4\n"
);

#include <stdint.h>
#include <limits.h>
#include <sys/types.h>
#include "compiler.h"

typedef void (*thunk)(void);


#if 0
typedef signed long    int32_t;
typedef unsigned long    uint32_t;
typedef signed short    int16_t;
typedef unsigned short    uint16_t;
typedef signed char    int8_t;
typedef unsigned char    uint8_t;

typedef uint32_t    size_t;
typedef int32_t        ssize_t;
#endif

static inline uint32_t
read_lr( void )
{
    uint32_t lr;
    asm( "mov %0, lr" : "=r"(lr) );
    return lr;
}


static inline void
select_normal_vectors( void )
{
    uint32_t reg;
    asm(
        "mrc p15, 0, %0, c1, c0\n"
        "bic %0, %0, #0x2000\n"
        "mcr p15, 0, %0, c1, c0\n"
        : "=r"(reg)
    );
}



static inline void
flush_caches( void )
{
    uint32_t reg = 0;
    asm(
        "mov %0, #0\n"
        "mcr p15, 0, %0, c7, c5, 0\n" // entire I cache
        "mov %0, #0\n"
        "mcr p15, 0, %0, c7, c6, 0\n" // entire D cache
        "mcr p15, 0, %0, c7, c10, 4\n" // drain write buffer
        : : "r"(reg)
    );
}


static inline void
clean_d_cache( void )
{
    uint32_t segment = 0;
    do {
        uint32_t line = 0;
        for( ; line != 0x400 ; line += 0x20 )
        {
            asm(
                "mcr p15, 0, %0, c7, c14, 2"
                : : "r"( line | segment )
            );
        }
    } while( segment += 0x40000000 );
}

// This must be a macro
#define setup_memory_region( region, value ) \
    asm __volatile__ ( "mcr p15, 0, %0, c6, c" #region "\n" : : "r"(value) )

#define set_d_cache_regions( value ) \
    asm __volatile__ ( "mcr p15, 0, %0, c2, c0\n" : : "r"(value) )

#define set_i_cache_regions( value ) \
    asm __volatile__ ( "mcr p15, 0, %0, c2, c0, 1\n" : : "r"(value) )

#define set_d_buffer_regions( value ) \
    asm __volatile__ ( "mcr p15, 0, %0, c3, c0\n" : : "r"(value) )

#define set_d_rw_regions( value ) \
    asm __volatile__ ( "mcr p15, 0, %0, c5, c0, 0\n" : : "r"(value) )

#define set_i_rw_regions( value ) \
    asm __volatile__ ( "mcr p15, 0, %0, c5, c0, 1\n" : : "r"(value) )

static inline void
set_control_reg( uint32_t value )
{
    asm __volatile__ ( "mcr p15, 0, %0, c3, c0\n" : : "r"(value) );
}

static inline uint32_t
read_control_reg( void )
{
    uint32_t value;
    asm __volatile__ ( "mrc p15, 0, %0, c3, c0\n" : "=r"(value) );
    return value;
}


static inline void
set_d_tcm( uint32_t value )
{
    asm( "mcr p15, 0, %0, c9, c1, 0\n" : : "r"(value) );
}

static inline void
set_i_tcm( uint32_t value )
{
    asm( "mcr p15, 0, %0, c9, c1, 1\n" : : "r"(value) );
}


/** Routines to enable / disable interrupts */
static inline uint32_t
cli(void)
{
    uint32_t old_cpsr;
    uint32_t new_cpsr;
    asm __volatile__ (
        "mrs %0, CPSR\n"
        "orr %1, %0, #0x80\n" // set I flag to disable IRQ
        "msr CPSR_c, %1\n"
        : "=r"(old_cpsr)
        : "r"(new_cpsr)
    );
    return old_cpsr & 0x80; // return true if the flags are set
}

static inline void
sei( uint32_t old_cpsr )
{
    uint32_t new_cpsr;
    asm __volatile__ (
        "mrs %0, CPSR\n"
        "bic %0, %0, #0x80\n"
        "orr %0, %0, %1\n"
        "msr CPSR_c, %0" : : "r"(new_cpsr), "r"(old_cpsr) );
}


/**
 * Some common instructions.
 */
#define RET_INSTR    0xe12fff1e    // bx lr
#define FAR_CALL_INSTR    0xe51ff004    // ldr pc, [pc,#-4]
#define LOOP_INSTR    0xeafffffe    // 1: b 1b
#define NOP_INSTR    0xe1a00000    // mov r0, r0
#define MOV_R0_0_INSTR 0xe3a00000




#define BL_INSTR(pc,dest) \
    ( 0xEB000000 \
    | ((( ((uint32_t)dest) - ((uint32_t)pc) - 8 ) >> 2) & 0x00FFFFFF) \
    )

/** Simple boot loader memcpy.
 *
 * \note This is not general purpose; len must be > 0 and must be % 4
 */
static inline void
blob_memcpy(
    void *        dest_v,
    const void *    src_v,
    const void *    end
)
{
    uint32_t *    dest = dest_v;
    const uint32_t * src = src_v;
    const uint32_t len = ((const uint32_t*) end) - src;
    uint32_t i;

    for( i=0 ; i<len ; i++ )
        dest[i] = src[i];
}

#endif
back to top