CPU

8 bit CPU

2009年7月21日

紆余曲折の結果、結局 8 bit のオーソドックスなCPUに落ち着きそう。

仕様は、次のとおり。

version 0.0.6.1
data line: 8 bits
address line: 14 bits (8 bits + 6 bits; 256 x 64)

registors X(8), Y(8), F(8), PC(12), SP(8)
F: Z, C, S5, S4, S3, S2, S1, S0 (Z, C: zero and carry flags; S: segment registor)
stack segment is always 0x3f
program can be written from 0x0000 to 0x0fff


All 2 byte commands

0x00, 0x01, ... , 0x0f: goto, operand: 12 bits.
0x10, 0x11, ... , 0x1f: call, operand: 12 bits.
0x20, 0x21, ... , 0x27: X=XX, [X]=XX, X=(XX), (XX)=X, Y=XX, [Y]=XX, X=(XX), (XX)=X
0x28, 0x29, ... , 0x2f: (see below)
0x2800 - 0x280f: X=X (NOP), X=Y, X=F, X=SP, reserved, X=[Y],
0x2810 - 0x281f: Y=X, Y=Y, Y=F, Y=SP, Y=[X], reserved,
0x2820 - 0x282f: F=X, F=Y, F=F, SP=SP, F=[X], F=[Y],
0x2830 - 0x283f: SP=X, SP=Y, SP=F, SP=SP, SP=[X], SP=[Y],
0x2880 - 0x288f: [X]=X, [X]=Y, [X]=F, [X]=SP, reserved, reserved,
0x2890 - 0x289f: [Y]=X, [Y]=Y, [Y]=F, [Y]=SP, reserved, reserved,
0x2900 - 0x290f: [SP]=X, [SP]=Y, [SP]=F,
0x2920 - 0x292f: push X, push Y, push F, SP--
0x2940 - 0x294f: [++SP]=X, [++SP]=Y, [++SP]=F,
0x2960 - 0x296f: [SP+1]=X, [SP+1]=Y, [SP+1]=F,
0x2980 - 0x298f: X=[SP], Y=[SP], F=[SP],
0x29a0 - 0x29af: X=[SP--], Y=[SP--], F=[SP--],
0x29c0 - 0x29cf: pop X, pop Y, pop F, SP++
0x29e0 - 0x29ef: X=[SP+1], Y=[SP+1], F=[SP+1],
0x30, 0x31, ... , 0x38: (XX)=X+Y, (XX)=X-Y, (XX)=X&Y, (XX)=X|Y, (XX)=X+Y+C, (XX)=X-Y-C, (XX)=X^Y, (XX)=~X
0x38, 0x31, ... , 0x3f: X=++(XX), X=--(XX), reserved x2, Y=++(XX), Y=--(XX), reservedx2
0x40, 0x41, ... , 0x4f: jz, operand: 12 bits.
0x50, 0x51, ... , 0x5f: jc, operand: 12 bits.
0x60, 0x61, ... , 0x6f: jnz, operand: 12 bits.
0x70, 0x71, ... , 0x7f: jnc, operand: 12 bits.
0x80, 0x81, ... , 0x8f: reserved
0x90, 0x91, ... , 0x9f: reserved
0xa0, 0xa1, ... , 0xaf: reserved
0xb0, 0xb1, ... , 0xbf: reserved
0xc0, 0xc1, ... , 0xcf: reserved
0xd0, 0xd1, ... , 0xdf: reserved
0xe0, 0xe1, ... , 0xef: reserved
0xf0, 0xf1, ... , 0xff: reserved

(XX) = [3Fh:XX]; used as registors; genelary, F0-FF (16 registors) are used.


特徴としては、すべての命令を2バイトとしたこと。これで、回路の簡略化が見込める。

汎用レジスタは、X, Y の2つ。フラグレジスタの下位6ビットは、データ読み書きのセグメントとして用いる。

例によって、スタック領域は256バイトのみ。ただし、この領域の一部(16バイトの予定)は、レジスタ操作の補助に用いる。

アドレスラインは、14ビット。ただし、プログラム可能なアドレス領域は、12ビット(4Kバイト)。これにより、すべてのジャンプ命令がきれいに2バイトに収まった。この大きさのアドレス領域でも円周率計算プログラムが書ける事は、PICに組み込んだプログラムで実証済み。

push/pop命令を適当に散らばらせることで、たぶん、この部分の回路の簡略化が見込める。

PHPで、シミュレーションを行いながら設計している。現在のところ、以下のようなスクリプト。
<?php

define('_DISPLAY_EVERY',1);
//define('_SHOW_MODE','hex');
define('_SHOW_MODE','dec');

// begin global code
code::init();

while (true) {
    $line=code::get_line();
    if (strlen($line)==0 || $line{0}=='#') {
        reg::$msg=$line;
        display();
        continue;
    }
    if ($line=='EXIT') break;
    code::execute($line);
    display();
}
display(true);
exit('The program ended normally');

// end global code

class code{
    static public $code=array();
    static public $label=array();
    static public $namespace=array();
    static public $linenum=0;
    static public function init(){
        $rawcode=raw_code($start);
        reg::$pc=$start;
        self::$linenum=$start+count($rawcode);
        $namespace='';
        for ($n=$start;$n<self::$linenum;$n++) {
            $line=$rawcode[$n-$start];
            $line=preg_replace('#//.*#','',$line);
            $line=trim($line);
            if (preg_match('/^[0-9a-zA-Z_]+\:$/',$line,$m)) {
                $lbl=strlen($namespace) ? $namespace.'_':'';
                $lbl=strtoupper($lbl.$m[0]);
                if (isset(self::$label[$lbl])) {
                    exit("The same label exists more than twice: '$lbl'.");
                }
                self::$label[$lbl]=$n;
                $line='#['.$line.']';
            } else if (preg_match('/^namespace($|\s.+$)/',$line,$m)){
                $namespace=strtoupper(trim($m[1]));
                $line='#['.$line.']';
            } else $line=strtoupper($line);
            self::$code[$n]=$line;
            self::$namespace[$n]=$namespace;
        }
    }
    static public function get_line(){
        if (self::$linenum<=reg::$pc) error('PC reached the end');
        self::current_namespace(self::$namespace[reg::$pc]);
        if (!isset(self::$code[reg::$pc])) error('PC is out of range');
        return self::$code[reg::$pc++];
    }
    static public function current_namespace($ns=false){
        static $namespace='';
        if ($ns===false) return $namespace;
        $namespace=$ns;
    }
    static public function jump($lbl){
        if (substr($lbl,-1)!=':') $lbl.=':';
        if (isset(self::$label[$lbl])) $lbl=$lbl;
        elseif (isset(self::$label[self::current_namespace().'_'.$lbl])) $lbl=self::current_namespace().'_'.$lbl;
        elseif (isset(self::$label[substr($lbl,0,-1).'_'.$lbl])) $lbl=substr($lbl,0,-1).'_'.$lbl;
        //elseif (isset(self::$label['_'.$lbl])) $lbl='_'.$lbl;
        else {
            print_r(self::$label);
            error("Label doesn't exist: $lbl");
        }
        reg::$pc=self::$label[$lbl];
    }
    static public function execute($line){
        reg::$msg=$line;
        if (!preg_match('/^(.+)(\=|\s)(.+)$/',$line,$c)) $c=array($line,$line,'','');
        if (method_exists(__CLASS__,"do_$c[1]_$c[3]")) $err=call_user_func_array(array(__CLASS__,"do_$c[1]_$c[3]"),$c);
        else if (method_exists(__CLASS__,"do_$c[1]")) $err=call_user_func_array(array(__CLASS__,"do_$c[1]"),$c);
        else {
            $err='error';
            switch ($c[1]) {
                case 'SP++':
                    $err=pop();
                    break;
                case 'SP--':
                    $err=push();
                    break;
                case '[X]':
                    $err=call_user_func_array(array(__CLASS__,'do__X_'),$c);
                    break;
                case '[Y]':
                    $err=call_user_func_array(array(__CLASS__,'do__Y_'),$c);
                    break;
                case '[SP]':
                case '[++SP]':
                case '[SP+1]':
                    $err=call_user_func_array(array(__CLASS__,'do__SP_'),$c);
                    break;
                default:
                    if (preg_match('/^\(([0-9A-F][0-9A-F])\)$/',$c[1])) {
                        $err=call_user_func_array(array(__CLASS__,'do_XX_'),$c);
                    }
                    break;
            }
        }
        if ($err==='error') error("Syntax error: $line");
    }
    static private function do_NOP(){
    }
    static private function do_X($line,$c1,$c2,$c3){
        reg::$x=byte(self::_XYFSP($c3));
    }
    static private function do_Y($line,$c1,$c2,$c3){
        reg::$y=byte(self::_XYFSP($c3));
    }
    static private function do_F($line,$c1,$c2,$c3){
        reg::set_f(byte(self::_XYFSP($c3)));
    }
    static private function do_SP($line,$c1,$c2,$c3){
        reg::$sp=byte(self::_XYFSP($c3));
    }
    static private function do__X_($line,$c1,$c2,$c3){
        write(reg::$ds*256+reg::$x,self::_XYFSP($c3));
    }
    static private function do__Y_($line,$c1,$c2,$c3){
        write(reg::$ds*256+reg::$y,self::_XYFSP($c3));
    }
    static private function do__SP_($line,$c1,$c2,$c3){
        switch($c1){
            case '[SP]':
                $addr=reg::$sp;
                break;
            case '[++SP]':
                pop();
                $addr=reg::$sp;
                break;
            case '[SP+1]':
                $addr=(reg::$sp+1) % 256;
                break;
            default:
                return 'error';
        }
        write_ss($addr,self::_XYFSP($c3));
    }
    static private function _XYFSP($c3){
        switch ($c3) {
            case 'X':
                return reg::$x;
            case '[X]':
                return read(reg::$ds*256+reg::$x);
            case 'Y':
                return reg::$y;
            case '[Y]':
                return read(reg::$ds*256+reg::$y);
            case 'F':
                return reg::get_f();
            case 'SP':
                return reg::$sp % 256;
            case '[SP]':
                return read_ss(reg::$sp);
            case '[SP--]':
                $data=read_ss(reg::$sp);
                reg::$sp=(reg::$sp+255)%256;
                return $data;
            case '[SP+1]':
                return read_ss((reg::$sp+1)%256);
            default: 
                if (preg_match('/^(.*)\(([0-9A-F][0-9A-F])\)$/',$c3,$m)) {
                    switch($m[1]){
                        case '++':
                            $data=set_flags(read_ss(hexdec($m[2]))+1);
                            write_ss(hexdec($m[2]),$data);
                            return $data;
                        case '--':
                            $data=set_flags(read_ss(hexdec($m[2]))-1);
                            write_ss(hexdec($m[2]),$data);
                            return $data;
                        case '':
                            return read_ss(hexdec($m[2]));
                        default:
                            break;
                    }
                }
                return byte($c3);
        }
    }
    static private function _GOTO($c3){
        code::jump($c3);
    }
    static private function do_GOTO($line,$c1,$c2,$c3){
        self::_GOTO($c3);
    }
    static private function do_JMP($line,$c1,$c2,$c3){
        self::_GOTO($c3);
    }
    static private function do_CALL($line,$c1,$c2,$c3){
        push((int)(reg::$pc/256));
        push(reg::$pc%256);
        self::_GOTO($c3);
    }
    static private function do_RETURN($line,$c1,$c2,$c3){
        reg::$pc=pop();
        reg::$pc+=pop()*256;
    }
    static private function do_RET($line,$c1,$c2,$c3){
        self::do_RETURN($line,$c1,$c2,$c3);
    }
    static private function do_JZ($line,$c1,$c2,$c3){
        if (reg::$z==1) self::_GOTO($c3);
    }
    static private function do_JNZ($line,$c1,$c2,$c3){
        if (reg::$z==0) self::_GOTO($c3);
    }
    static private function do_JC($line,$c1,$c2,$c3){
        if (reg::$c==1) self::_GOTO($c3);
    }
    static private function do_JNC($line,$c1,$c2,$c3){
        if (reg::$c==0) self::_GOTO($c3);
    }
    static private function do_XX_($line,$c1,$c2,$c3){
        switch($c3){
            case 'X':
                $data=reg::$x;
                break;
            case 'Y':
                $data=reg::$y;
                break;
            case 'X+Y':
                $data=set_flags(reg::$x+reg::$y);
                break;
            case 'X-Y':
                $data=set_flags(reg::$x-reg::$y);
                break;
            case 'X&Y':
                $data=set_flags(reg::$x&reg::$y);
                break;
            case 'X|Y':
                $data=set_flags(reg::$x|reg::$y);
                break;
            case 'X+Y+C':
                $data=set_flags(reg::$x+reg::$y+reg::$c);
                break;
            case 'X-Y-C':
                $data=set_flags(reg::$x-reg::$y-reg::$c);
                break;
            case 'X^Y':
                $data=set_flags(reg::$x^reg::$y);
                break;
            case '~X':
                $data=set_flags(~reg::$x);
                break;
            default:
                return 'error';
        }
        write_ss(hexdec(substr($c1,1,-1)),$data);
    }
    static private function do_PUSH($line,$c1,$c2,$c3){
        switch($c3) {
            case 'X':
                return push(reg::$x);
            case 'Y':
                return push(reg::$y);
            case 'F':
                return push(reg::get_f());
            case 'SP':
                return push(reg::$sp);
            default:
                /*if (preg_match('/^\(([0-9A-F][0-9A-F])\)$/',$c3,$m)) {
                    return push(read_ss(hexdec($m[1])));
                }*/
                return 'error';
        }
    }
    static private function do_POP($line,$c1,$c2,$c3){
        switch($c3) {
            case 'X':
                return reg::$x=pop();
            case 'Y':
                return reg::$y=pop();
            case 'F':
                return reg::set_f(pop());
            case 'SP':
                return reg::$sp=pop();
            default:
                /*if (preg_match('/^\(([0-9A-F][0-9A-F])\)$/',$c3,$m)) {
                    return write_ss(hexdec($m[1]),pop());
                }*/
                return 'error';
        }
    }
}

class reg{
    static public $x=0;  // X registor
    static public $y=0;  // Y registor
    static public $c=0;  // carry flag
    static public $z=0;  // zero flag
    static public $ds=0;  // data segment
    static public $sp=0; // stack pointer
    static public $pc=0; // program counter (line number of code array)
    static public $msg=''; // message string being shown
    static public function get_f(){
        return self::$c*128+self::$z*64+self::$ds;
    }
    static public function set_f($data){
        $data=byte($data);
        reg::$z=($data & 0x80) ? 1:0;
        reg::$c=($data & 0x40) ? 1:0;
        reg::$ds=$data % 64;
    }
}
function push($data='none'){
    if ($data!=='none') write_ss(reg::$sp,$data);
    reg::$sp=(255+reg::$sp) % 256;
}
function pop(){
    reg::$sp=(1+reg::$sp) % 256;
    return read_ss(reg::$sp);
}
function set_flags($data){
    reg::$c=1;
    if ($data<0) $data=$data+256;
    elseif (255<$data) $data=$data-256;
    else reg::$c=0;
    if ($data==0) reg::$z=1;
    else reg::$z=0;
    return byte($data);
}

function display($force=false){
    static $counter=0;
    $counter++;
    if ($counter<_DISPLAY_EVERY && !$force) return;
    $counter=0;
    $msg=reg::$msg;
    ob_start();
    if (_SHOW_MODE=='dec') {
        // decimal mode; address 0x00 - 0x07
        for ($x=0;$x<8;$x++) {
            $d=read($x);
            if (31<$d) {
                echo '_';
            } elseif (0<=$d && $d<=9) {
                echo $d;
            } elseif (16<=$d && $d<=25) {
                echo ($d-16).'.';
            } else {
                echo '?';
            }
        }
    } else {
        // hex mode; address 0x10 - 0x13
        for ($x=0x13;0x10<=$x;$x--) show_hex(read($x),2);
    }
    echo ' ';
    echo 'X:',show_hex(reg::$x,2).' ';
    echo 'Y:',show_hex(reg::$y,2).' ';
    echo 'C:',show_hex(reg::$c,1).' ';
    echo 'Z:',show_hex(reg::$z,1).' ';
    echo 'S:',show_hex(reg::$ds,2).' ';
    echo 'SP:',show_hex(reg::$sp,2).' ';
    echo 'PC:'.reg::$pc.'  ';
    $msg=ob_get_clean().$msg;
    if (strlen($msg)<80) echo "$msg\n";
    else substr($msg,0,80);
    reg::$msg='';
}
function show_hex($dec,$f){
    $val=str_repeat('0',$f).strtoupper(dechex($dec));
    echo substr($val,-$f);
}

function read($addr){
    $data=memory($addr);
    reg::$msg.=' '.dechex($addr).':'.dechex($data);
    return $data;
}
function write($addr,$data){
    $org=memory($addr);
    memory($addr,$data);
    reg::$msg.=' '.dechex($addr).':'.dechex($org).'->'.dechex(byte($data));
}
function read_ss($addr){
    return read(0x3f00+byte($addr));
}
function write_ss($addr,$data){
    write(0x3f00+byte($addr),$data);
}
function memory($addr,$data='read'){
    static $m;
    if (!isset($m)) $m=array_fill(0,0x4000,0x55);
    if ($data==='read') return $m[$addr];
    $data=byte($data);
    $m[$addr]=$data;
}
function byte($data){
    return check_value($data,8);
}
function check_value($data,$bit){
    $max=pow(2,$bit);
    if (preg_match('/^0x([0-9A-F]+)$/',$data,$m)) $data=hexdec($m[1]);
    elseif (preg_match('/^([0-9A-F]+)H$/',$data,$m)) $data=hexdec($m[1]);
    elseif (!is_numeric($data)) error("Data must be numeric: $data");
    if (0<=$data && $data<=$max) return (int)$data;
    error("Data must be between 0 and $max: $data");
}
function error($text=''){
    $linenum=reg::$pc;
    $db='';
    foreach(debug_backtrace() as $d){
        $db.=$d['line'].',';
    }
    echo "Error occured at line $linenum (PHP:$db)\n$text\n";
    exit;
}

function raw_code(&$ret){
    ob_start();
$ret=__LINE__; ?>
# initialize
    nop
    X=efH // Use 0x3ff0 - 0x3fff for registors
    SP=X
    X=1h  // Use 0x0100 - 0x01ff for data strage
    F=X
    
# start main
    call main
    exit
namespace main
main:
    X=FFh
    (F0)=X
loop:
    X=(F0)
    [X]=6
    X=--(F0)
    jnc loop

    // test add
    X=10h
    Y=20h
    (F0)=X
    (F1)=Y
    X=8
    Y=0h
    call add

    // test mul8
#    X=16
#    Y=50
#    call mul8
#    push Y
#    Y=0
#    [Y]=X
#    pop Y
#    X=4
#    [X]=Y

    // test mul4
#    X=0
#    Y=5
#    call mul4
#    Y=0
#    [Y]=X
    

    // carry check
    X=8
    Y=0h
#    call carry_check

    X=0h
    (F0)=X
    X=8
    Y=80h
    call copy
    
    X=80h
    call show

    // test push routines
    X=12h
    (F0)=X
    X=13h
    call push_f0
    X=(F0)
    X=0h
    (F0)=X
    X=14h
    Y=15h
    call pop_f0
    X=(F0)
end:
    return
#############################
# decimal mode show routine #
# 8 bytes from X will be    #
# moved to 0x0000 to 0x0007 #
#############################
namespace show
show:
    (F0)=X
    X=7
    (F1)=X // counter

loop:
    X=(F0) // original address
    Y=[X] // data
    X=++(F0)
    push F
    X=0
    F=X
    X=(F1)
    [X]=Y
    pop F
    X=--(F1)
    jnc loop

    return
#######################
# Carry check routine #
# X: byte length      #
# Y: pointer to data  #
#######################
namespace carry_check
carry_check:
    (F0)=X
    (F1)=Y
    X=0
    (F2)=X // carry
loop:
    Y=(F1)
    X=[Y]
    Y=(F2)
    (F3)=X+Y // value temporary
    X=--(F0)
    jz end
    X=0
    (F2)=X
loop2:
    X=(F3)
    Y=10
    (F3)=X-Y
    jc next
    X=++(F2)
    goto loop2
next:
    Y=(F1)
    [Y]=X
    X=++(F1)
    goto carry_check_loop

end:
    return
##################
# copy routine   #
# X: byte length #
# Y: destination #
# (F0): origin   #
##################
namespace copy
copy:
    (F1)=X // byte length
    (F2)=Y // destination

loop:
    Y=(F0)
    X=++(F0)
    X=[Y]
    Y=(F2)
    [Y]=X
    Y=++(F2)
    Y=--(F1)
    jnz loop

    return

##################
# add routine    #
# X: byte length #
# Y: &result     #
# (F0): &value 1 #
# (F1): &value 2 #
##################
namespace add
add:
    push X
    push Y
    (F2)=X // byte length
    (F3)=Y // &result

loop:
    Y=(F0)
    X=++(F0)
    X=[Y]
    (F4)=X // temporary space
    Y=(F1)
    X=++(F1)
    X=[Y]
    Y=(F4)
    (F4)=X+Y
    X=(F4)
    Y=(F3)
    [Y]=X
    X=++(F3)

    Y=--(F2)
    jnz loop

    pop Y
    pop X
    call carry_check
    return
    
######################
# 8 bit multiply     #
# X value 1          #
# Y value 2          #
# result will be in  #
# X and Y,           #
# low and high bytes #
# respectively       #
######################
namespace mul8
mul8:
    (F4)=Y // keeps value 2
    (F2)=X // temp value lower byte
    X=0
    (F3)=X // temp value higher byte
    (F0)=X // result lower byte
    (F1)=X // result higher byte
    X=1
    (F5)=X

loop:
    X=(F4)
    Y=(F5)
    (F6)=X&Y
    jz next
    X=(F0)
    Y=(F2)
    (F0)=X+Y
    X=(F1)
    Y=(F3)
    (F1)=X+Y+C
next:
    X=(F2)
    Y=(F2)
    (F2)=X+Y
    X=(F3)
    Y=(F3)
    (F3)=X+Y+C
    X=(F5)
    Y=(F5)
    (F5)=X+Y
    jnz loop

    X=(F0)
    Y=(F1)
    return
######################
# 4 bit multiply     #
# X value 1          #
# Y value 2          #
# result will be in  #
# X                  #
######################
namespace mul4
mul4:
    (F0)=X // counter
    X=0
    (F1)=X // result
    X=++(F0)
loop:
    X=--(F0)
    X=(F1)
    jz end
    (F1)=X+Y
    goto loop
end:
    return

#################
# push routines #
#################
namespace push
f0:
    SP--
    push X
    X=(F0)
push_main:
    [SP]=Y
    SP++
    SP++
    Y=[SP+1] // get PCL
    [SP]=Y // set PCL
    SP++
    pop Y // get PCH
    push X // set (F0)
    push Y // set PCH
    SP--
    SP--
    Y=[SP]
    pop X
    return

f1:
    SP--
    push X
    X=(F1)
    goto push_main:
f2:
    SP--
    push X
    X=(F1)
    goto push_main:
f3:
    SP--
    push X
    X=(F1)
    goto push_main:

################
# pop routines #
################
namespace pop
f0:
    call pop_main
    (F0)=X
    pop X
    return
pop_main:
    [SP]=Y
    SP++
    SP++
    pop Y // get PCL
    [SP]=X
    pop X // get PCH
    push Y // set PCL
    SP++
    pop Y // get (F0)
    push X // set PCH
    X=Y // get (F0)
    SP--
    SP--
    SP--
    SP--
    Y=[SP]
    return

f1:
    call pop_main
    (F1)=X
    pop X
    return
f2:
    call pop_main
    (F2)=X
    pop X
    return
f3:
    call pop_main
    (F3)=X
    pop X
    return

#########################
# several calc routines #
#########################
namespace calc
rol:
    Y=(F0)
    push Y
    Y=X
    (F0)=X+Y+C
    X=(F0)
    pop Y
    (F0)=Y
    return
rol_x:
    push Y
    call rol
    pop Y
    return
rol_y:
    push X
    X=Y
    call rol
    Y=X
    pop X
    return
ror:
    Y=(F0)
    push Y
    Y=X
    (F0)=X+Y+C
    (F0)=X+Y+C
    (F0)=X+Y+C
    (F0)=X+Y+C
    (F0)=X+Y+C
    (F0)=X+Y+C
    (F0)=X+Y+C
    (F0)=X+Y+C
    X=(F0)
    pop Y
    (F0)=Y
    return
ror_x:
    push Y
    call ror
    pop Y
    return
ror_y:
    push X
    X=Y
    call ror
    Y=X
    pop X
    return
clear_carry:
    X=(F0)
    push X
    (F0)=~X
    pop X
    (F0)=X
    return
shl_x:
    call clear_carry
    goto rol_x:
shl_y:
    call clear_carry
    goto rol_y:
xpp:
    push Y
    Y=(F0)
    push Y
    (F0)=X
    X=++(F0)
    pop Y
    (F0)=Y
    pop Y
    return
ypp:
    push X
    X=(F0)
    push X
    (F0)=Y
    Y=++(F0)
    pop X
    (F0)=X
    pop X
    return

<?php
    return preg_split('/(\r\n|\r|\n)/',ob_get_clean());

}

<%media(20090722-old versions.zip|紆余曲折の過程は、このとおり。)%>

コメント

コメントはありません

コメント送信