Subscribe to RSS Feed ログイン

オーガニック・ウェルス

Saturday
2018年4月21日

インラインアセンブラでSSE

<sse3.c>

#include <stdio.h>
#include <stdlib.h>
float a[4] asm ("a")__attribute__((aligned(16))) ={0.0,0.0,0.0,0.0};
int main()
{
	float* c;
	int size_of_float = sizeof(float); // 32bit
	int num = 1024,i=0,limit;
	c = (float*)malloc(size_of_float * num);
	for(i = 0;i < num;i++){
		c[i] = i + 1;
	}
	//  aはアラインメントされているのでmovaps
	asm("movaps a,%xmm0");
	limit = num / 4;
	for(i = 0;i < limit;i++) {
		// cはアラインメントされていないのでmovups
		asm("movups (%0),%%xmm1"::"r"(c + i * size_of_float));
		asm("addps %xmm1,%xmm0");
	}
	asm("movaps %xmm0, a");

	printf("sum = %f\n",a[0] + a[1] + a[2] + a[3]);
	free(c);
	return 0;
}

$ gcc -o sse3 sse3.c
$ ./sse3

sum = 524800.000000

コメント(0)続きを読む

インラインアセンブラを試す

まずOSの情報を表示します。

# cat /proc/cpuinfo

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 44
model name      : Intel(R) Xeon(R) CPU           X5675  @ 3.07GHz
stepping        : 2
cpu MHz         : 3066.450
cache size      : 4096 KB
fpu             : yes
fpu_exception   : yes
cpuid level     : 11
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush mmx
fxsr sse sse2 ss syscall nx lm constant_tsc up unfair_spinlock pni pclmulqdq ssse3 cx16
 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm
bogomips        : 6132.90
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

さくらのクラウドでは上記のようなスペックになっています。
以下のサイトのコードをgcc様に書き換えて実行してみます。
http://www.isus.jp/article/compileroptimization/compiler_part1/

<inline_asm.c>

#include<stdio.h>

int a asm ("a") = 2;
int b asm ("b") = 3;
int c asm ("c")= 0;
int REG_eax asm ("REG_eax")= 0;
int REG_edx asm ("REG_edx")= 0;
int REG_ecx asm ("REG_ecx")= 0;
int main()
{
	asm("mov $1, %rax");
	asm("cpuid");
	asm("mov %edx, REG_edx"); 
	asm("mov %ecx, REG_ecx"); 
	if(REG_edx && 0x800000) printf("MMX ");
	if(REG_edx && 0x2000000) printf("SSE ");
	if(REG_edx && 0x4000000) printf("SSE2 ");
	if(REG_ecx && 0x00000001) printf("SSE3 ");
	if(REG_ecx && 0x00000200) printf("SSSE3 ");
	if(REG_ecx && 0x00080000) printf("SSE4.1 ");
	if(REG_ecx && 0x00100000) printf("SSE4.2 ");
	if(REG_ecx && 0x00200000) printf("AESNI ");
	if(REG_ecx && 0x00000002) printf("PCLMULQDQ ");

	printf("\n");
	printf("REG_edx = %x\n", REG_edx);
	printf("REG_ecx = %x\n", REG_ecx);

	asm("mov a, %rax");
	asm("add b, %rax");
	asm("add $100, %rax");
	asm("mov %rax, c");
	printf("%d\n", c);
	return 0;
}

$ gcc -o inline_asm inline_asm.c

MMX SSE SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 AESNI PCLMULQDQ
REG_edx = f8bf3ff
REG_ecx = 82982203
105

このような結果になりました。

コメント(0)続きを読む

64ビットでアセンブラをやってみる

以前アセンブラの記事を書いたのがどちらも32ビットでした。

先日64ビットのLinux環境でアセンブラを行ったら全く違う動作になったのでメモします。

<asm_test.c>

#include  <stdio.h>

extern int _add(int a, int b);
extern int _sub(int a, int b);
extern int _mul(int a, int b);
extern int _div(int a, int b);
extern float _fadd(float a, float b);
extern float _fsub(float a, float b);
extern float _fmul(float a, float b);
extern float _fdiv(float a, float b);

int main () {
	printf("_add 4 + 9 = %d\n", _add(4,9));
	printf("_sub 18 - 7 = %d\n", _sub(18,7));
	printf("_mul 8 * 6 = %d\n", _mul(8,6));
	printf("_div 27 / 8 = %d\n", _div(27,8));

	printf("_fadd %f\n", _fadd(4.15, 6.26));
	printf("_fsub %f\n", _fsub(8.56, 4.87));
	printf("_fmul %f\n", _fmul(2.5, 3.76));
	printf("_fdiv %f\n", _fdiv(15.98, 3.64));
    return 0;
}

<asm_test.s>

	bits 64
	global _add
	global _sub
	global _mul
	global _div
	global _fadd
	global _fsub
	global _fmul
	global _fdiv

    ;; start program area
    section .text

    ;; global functions

_add:
 ; rdi(引数1)をrax(戻り値)に格納
	mov    rax, rdi
 ; rsi(引数2)をraxに加算
	add    rax, rsi
    RET

_sub:
	mov    rax, rdi
	sub    rax, rsi
    RET

_mul:
	mov    rax, rdi
	imul    rax, rsi
    RET

_div:
	mov    rax, rdi
	mov    rbx, rsi
 ; 符号拡張した値をedxに格納
	cdq
	idiv    rbx
    RET

_fadd:
 ;xmm1をxmm0に加算し、xmm0に格納
	addss xmm0, xmm1
	ret

_fsub:
	subss xmm0, xmm1
	ret

_fmul:
	mulss xmm0, xmm1
	ret

_fdiv:
	divss xmm0, xmm1
	ret

上記2つのファイルを以下の方法でリンクします。


$ gcc -o asm_test.o -c asm_test.c
$ nasm -f elf64 -o asm_s.o asm_test.s
$ gcc -o asm_test asm_test.o asm_s.o

実行結果

_add 4 + 9 = 13
_sub 18 - 7 = 11
_mul 8 * 6 = 48
_div 27 / 8 = 3
_fadd 10.410000
_fsub 3.690001
_fmul 9.400000
_fdiv 4.390110

ただこのやり方が合ってるのかは不明ですが・・・

コメント(0)続きを読む

Javascriptで物理演算の練習2

以前作成した物理演算の練習に壁の跳ね返り、床を転がるモーションを追加しました。

以前作成したもの

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />

<title>物理演算</title>
<script>
<!--
var objects = [];

function CircleObject() {
  this.x = 5;
  this.y = 5;
  this.div_x = 0;
  this.div_y = 0;
}

var timerId;
var context;
var canObj= [];
window.onload = function myload() {
  var canvas = document.getElementById('canvas_1');
  if (!canvas || ! canvas.getContext) { return false; };
  context = canvas.getContext('2d');
  canObj.h = canvas.clientHeight;
  canObj.w = canvas.clientWidth;
  // Y軸の反転
  context.setTransform(1, 0, 0, -1, 0, canObj.h);

  timerId = setInterval(interval, 30);
}
function interval() {
  context.beginPath();
  context.clearRect(0, 0, 500, 500);
  for(i = 0;i < objects.length;i++) {
    var circle = objects[i];
    circle.x -= circle.div_x;
    circle.y -= circle.div_y;
    if(circle.y <= 0) {
      circle.y = 0;
      circle.div_y = (- (circle.div_y * 0.5)); // 反発係数
      circle.div_x = circle.div_x * 0.9; // 転がり摩擦
    } else {
      circle.div_y += 0.98;
    }
    // 壁に当たったとき
    if(circle.x < 0) {
      circle.x = 0;
      circle.div_x = -(circle.div_x * 0.8);
    } else if(circle.x > canObj.w) {
      circle.x = canObj.w;
      circle.div_x = -(circle.div_x * 0.8);
    }
    context.beginPath();
    context.arc(parseInt(circle.x), parseInt(circle.y) + 5, 5, 0, Math.PI*2, false);
    context.fill();
  }
}
function addObj() {
  var newCircle = new CircleObject();
  newCircle.x = 5.0 + Math.floor( Math.random() * 495 );
  newCircle.y = canObj.h;
  newCircle.div_x = -10.0 + Math.floor( Math.random() * 20 );
  objects.push(newCircle);
}
function clearObj() {
  objects = [];
}
-->
</script>

</head>

<body>
<div style="border:1px solid #666;width:500px;height:500px;">
<canvas id="canvas_1" width="500" height="500"></canvas>
</div>
<input type="button" onclick="addObj();" value="追加" />
<input type="button" onclick="clearObj();" value="クリア" />
<div id="debug"></div>
</body>

</html>

コメント(1)続きを読む

swfmillでActionScriptを書いてみるテスト

<?xml version="1.0" encoding="UTF-8"?>
<swf version="10" compressed="1">
  <Header framerate="1" frames="3">
    <size>
      <Rectangle left="0" right="11000" top="0" bottom="8000"/>
    </size>
    <tags>
      <SetBackgroundColor>
        <color>
          <Color red="80" green="128" blue="255"/>
        </color>
      </SetBackgroundColor>
      <ShowFrame/>
      <DoAction>
        <actions>
         <GetURL url="javascript:console.log('Frame 1_1');" target=""/>
         <GetURL url="javascript:console.log('Frame 1_2');" target=""/>
         <GetURL url="javascript:console.log('Frame 1_3');" target=""/>
          <EndAction/>
        </actions>
      </DoAction>
      <ShowFrame/>
      <DoAction>
        <actions>
         <GetURL url="javascript:console.log('Frame 2_1');" target=""/>
          <EndAction/>
        </actions>
        <actions>
         <GetURL url="javascript:console.log('Frame 2_2');" target=""/>
          <EndAction/>
        </actions>
        <actions>
         <GetURL url="javascript:console.log('Frame 2_3');" target=""/>
          <EndAction/>
        </actions>
      </DoAction>
      <ShowFrame/>
      <DoAction>
        <actions>
         <GetURL url="javascript:console.log('Frame 3');" target=""/>
          <EndAction/>
        </actions>
      </DoAction>
      <ShowFrame/>
      <End/>
    </tags>
  </Header>
</swf>

上記XMLをtest1.xmlで保存しswfに変換します。

$ swfmill xml2swf test1.xml test1.swf

<object width="200" height="200">
  <embed src="test1.swf"
  loop="false"
  pluginspage="http://www.macromedia.com/go/getflashplayer"
  type="application/x-shockwave-flash"
  width="200"
  height="200"></embed>
</object>

上記タグで表示します。

青背景の領域が表示されます。またconsole.logを実行しています。これはframerate[fps]で指定した間隔でActionScriptが実行されます。

ひとつのactionsタグの中に複数のGetURLを記述すると最後の値が評価されます。

またactionsタグを複数記述すると最初のactionsだけが評価されます。

コメント(0)続きを読む

各社Android携帯のソースコードリンク集

HTC, 730 uploadと書かれているのでそれなりに種類があるようです。

http://htcdev.com/devcenter/downloads

LG, “LGP970″等の型番を入力して検索する必要があります。

http://www.lg.com/global/support/opensource/opensource-detail.jsp

SHARP, 上からdocomo, SoftBank, auの順になっているようです。

https://sh-dev.sharp.co.jp/android/modules/oss/

Fujitsu

http://spf.fmworld.net/fujitsu/c/develop/sp/android/

Asus(TF101), インデックスページは見つからなかったので、各製品のDownloadからいくと思います。

http://www.asus.com/Eee/Eee_Pad/Eee_Pad_Transformer_TF101/#download

Sony mobile

http://developer.sonymobile.com/wportal/devworld/search-downloads/android

 

コメント(0)続きを読む

swfmillをインストールしてみる

ホームページはこちら。

http://swfmill.org/

またGithubのページは以下になります。

https://github.com/djcsdy/swfmill/

0.3.2が最新だったため0.3.2を使用します。

CentOSの場合

# yum install libxslt-devel freetype-devel libpng-devel

# wget http://swfmill.org/releases/swfmill-0.3.2.tar.gz

# tar xvf swfmill-0.3.2.tar.gz

# cd swfmill-0.3.2

# ./configure

# make && make install

Ubuntuの場合

# sudo apt-get install libpng-dev xsltproc libxml2 libxml2-dev libxslt-dev

・freetypeのインストール

# wget http://download.savannah.gnu.org/releases/freetype/freetype-2.4.10.tar.gz

# tar xvf freetype-2.4.10.tar.gz

# cd freetype-2.4.10/

# ./configure

# make

# sudo make install

・swfmillのインストール

# wget http://swfmill.org/releases/swfmill-0.3.2.tar.gz

# tar xvf swfmill-0.3.2.tar.gz

# cd swfmill-0.3.2

# ./configure

# make

# sudo make install

次回以降使用方法を書いていきたいと思います。

コメント(0)続きを読む

Google V8 Engineを試す

環境はUbuntu12.04

V8のビルドにはSCONSが必要とかかれていますが、今後SCONSはサポートされなくなるようなのでmakeを使います。

$ svn co http://v8.googlecode.com/svn/trunk/ v8
$ make dependencies
$ make ia32

ビルドは完了しました。サンプルを動かしてみます。まずはshellを作成します。

g++ -o shell -m32 -O2 -m32 obj/sample/shell/release/shell.o -L. -lv8 -lpthread

<test.js>

print("test");

実行する。
$ ./shell test.js
もう一つのサンプルを動かしてみます。
$ g++ -o process -m32 -O2 -m32 obj/sample/process/release/process.o -L. -lv8 -lpthread
$ ./process samples/count-hosts.js verbose=true

Logged: Processing google.com/process.cc from localhost@firefox
Logged: Processing google.net/ from localhost@firefox
Logged: Processing google.org/ from localhost@safari
Logged: Processing yahoo.com/ from localhost@ie
Logged: Processing yahoo.com/ from localhost@safari
Logged: Processing yahoo.com/ from localhost@firefox
google.com: 1
google.net: 1
google.org: 1
yahoo.com: 3

結果が何のかはよく分かっていないんですが・・・
自前のC++ソースに組み込む場合も説明します。

https://developers.google.com/v8/get_started#hello

Hello Worldの2個目のサンプルを使用します。上記ページではx64でビルド指定してますが、ia32でコンパイルします。
$ g++ -Iinclude hello_world.cc -o hello_world out/ia32.release/obj.target/tools/gyp/libv8_{base,snapshot}.a -lpthread
$ ./hello_world
で実行します。

参考ページ

Google Chrome の JavaScript エンジン V8 を試す – IT戦記

Building V8

コメント(0)続きを読む

Windowsでもアセンブラ

環境はWindows7 + Cygwinを使いました。

gccは3.4.4、nasmは2.08.02が入っています。

<asmtest.s>

    global      _main
    extern      _printf

    section .text
_main:
    push        message
    call        _printf
    add         esp, 4
    ret
message:
    db  'AsmTest.', 10, 0

$ nasm -f win32 asmtest.s

$ gcc -o asmtest asmtest.obj

$ ./asmtest

AsmTest.

この状態では45,314バイトのexeファイルが生成されました。-sコマンドで同時にstripを行います。

$ gcc -o asmtest -s asmtest.obj

ファイルサイズは4096バイトに減らせました。

コメント(0)続きを読む

Rustがdebianでコンパイルできない

先日Rust-compilerが0.2になっていました。そして最近debianを使い始めたのですが0.1/0.2ともmakeに失敗します。

ただいま原因を調査しています。どなたかご存知の方がいれば一報いただけますと幸いです。

0.1のmake結果
compile: rustllvm/x86_64-unknown-linux-gnu/RustGCMetadataPrinter.o
compile: rustllvm/x86_64-unknown-linux-gnu/RustGCStrategy.o
compile: rustllvm/x86_64-unknown-linux-gnu/RustWrapper.o
def: rustllvm/rustllvm.linux.def
link: rustllvm/x86_64-unknown-linux-gnu/librustllvm.so
cp: x86_64-unknown-linux-gnu/stage0/lib/rustc/x86_64-unknown-linux-gnu/lib/librustllvm.so
compile_and_link: x86_64-unknown-linux-gnu/stage0/lib/rustc/x86_64-unknown-linux-gnu/lib/libcore.so
compile_and_link: x86_64-unknown-linux-gnu/stage0/lib/rustc/x86_64-unknown-linux-gnu/lib/libstd.so
compile_and_link: x86_64-unknown-linux-gnu/stage0/lib/rustc/x86_64-unknown-linux-gnu/lib/librustc.so
error: internal compiler error unexpected failure
note: The compiler hit an unexpected failure path. This is a bug. Try running with RUST_LOG=rustc=0,::rt::backtrace to get further details and report the results to github.com/mozilla/rust/issues
make: *** [x86_64-unknown-linux-gnu/stage0/lib/rustc/x86_64-unknown-linux-gnu/lib/librustc.so] Error 101

0.2のmake結果

make: *** [x86_64-unknown-linux-gnu/stage0/lib/rustc/x86_64-unknown-linux-gnu/lib/librustc.so] Error 137

 

コメント(0)続きを読む