# MI_CpuCopy*

## 構文

  `#include <nitro/mi.h>`
  `void MI_CpuCopy8( const void* src, void* dest, u32 size );`
  `void MI_CpuCopy16( const void* src, void* dest, u32 size );`
  `void MI_CpuCopy32( const void* src, void* dest, u32 size );`
  `void MI_CpuCopyFast( const void* src, void* dest, u32 size );`
  `void MI_CpuCopy( const void* src, void* dest, u32 size );`

## 引数

src | 転送元アドレス
dest | 転送先アドレス
size | 転送サイズ

## 返り値

なし。

## 説明

CPUでメモリコピーを行います。

`MI_CpuCopy8()` は転送元アドレスと転送先アドレスから判断してできるだけ効率的なコピー方法を選択し、適宜 16ビットおよび 32ビット単位でコピーを行います。転送元アドレス、転送先アドレスのアラインメントを考慮する必要はありません。また、1バイト単位のアクセスを行いません。

`MI_CpuCopy16()` は 16ビット単位でコピーを行います。転送元アドレス、転送先アドレスは2バイトアラインメントする必要があります。

`MI_CpuCopy32()` は 32ビット単位でコピーを行います。転送元アドレス、転送先アドレスは4バイトアラインメントする必要があります。

`MI_CpuCopyFast()` は 32バイト単位で高速にコピーを行います。転送元アドレス、転送先アドレスは4バイトアラインメントする必要があります。転送サイズは4の整数倍バイトである必要があります。32の整数倍バイトである必要はありません。32バイト単位で転送した後の端数分は`MI_CpuCopy32()` と同じ処理を行ないます。

従って、`MI_CpuCopyFast()` と `MI_CpuCopy32()` は、転送サイズが 32 バイトより小さい場合、二つの関数で純粋な転送動作部分のコードは同じになります。 しかし`MI_CpuCopyFast()` では32バイトに満たない端数分かどうかという判定を行なっていますので、そのコードの分のロスが生じます。つまりこの状況では `MI_CpuCopy32()` が少しだけ速いということになります。しかしそれより転送サイズが大きくなれば `MI_CpuCopyFast()` の方が高速となります。

この考えに基づいて、一つの関数で効率の良い転送を行ないたい場合は、次のように実装することが考えられます。

> `static inline void myCpuCopy32( const void *src, void *dest, u32 size )
> {
> if ( size >= 0x20 )
> {
> MIi_CpuCopyFast(src, dest, size);
> }
> else
> {
> MIi_CpuCopy32(src, dest, size);
> }
> }`

しかし、転送を行なう領域のキャッシュの状態や転送アドレスなどの要因によって速度差の出るサイズの閾値が厳密に 32バイトのところにあるかは不定ですので、これは理論的な目安であると捉えるべきでしょう。

`MI_CpuCopy()` は `MI_CpuCopy8` と同様に転送先アドレスから判断してできるだけ効率的な方法を選択し、適宜 16ビットおよび 32ビット単位でコピーを行うのに加え 32バイト単位でのコピーも行います。転送元アドレス、転送先アドレスのアラインメントや転送サイズにも制限はありません。アラインメントや転送サイズが不定の場合以外は `MIi_CpuCopyFast()` や `MIi_CpuCopy32()` を呼び分けることが推奨されます。

## 内部動作

DMAコントローラは使用せず、CPUだけで処理します。システムコールは使用しません。
`MI_CpuCopy8()` に関しても16/32ビット単位でコピーが行なわれますので、直接VRAMへアクセスする場合でも問題は発生しません。
`MI_CpuCopy()` は、対象アドレスによっては8ビット単位でコピーを行う事がありますので、直接VRAMへアクセスする場合には使用しないで下さい。(TWL モードで、VRAM 拡張が行われている場合は使用することが可能です)

## 参照

`MI_CpuFill*, MI_CpuClear*, MI_CpuSend*, MI_DmaCopy*
`

## 履歴

2007/12/10 `MI_CpuCopy` を追加
2005/07/07 `MI_CpuCopy32` と `MI_CpuCopyFast` の速度について追記
2004/04/29 `MI_CpuCopy8` の記述を追加
2004/03/29 システムコールは使用しないと記述
2003/12/01 初版