require '_h2ph_pre.ph';

no warnings qw(redefine misc);

if(defined(&__OpenBSD__)) {
    require 'machine/atomic.ph';
}
if(defined(&__FreeBSD__)) {
    eval 'sub atomic_set {
        my($p, $v) = @_;
	    eval q((*($p) = ($v)));
    }' unless defined(&atomic_set);
    eval 'sub atomic_read {
        my($p) = @_;
	    eval q((*($p)));
    }' unless defined(&atomic_read);
    eval 'sub atomic_inc {
        my($p) = @_;
	    eval q( &atomic_add_int($p, 1));
    }' unless defined(&atomic_inc);
    eval 'sub atomic_dec {
        my($p) = @_;
	    eval q( &atomic_subtract_int($p, 1));
    }' unless defined(&atomic_dec);
    eval 'sub atomic_add {
        my($n, $p) = @_;
	    eval q( &atomic_add_int($p, $n));
    }' unless defined(&atomic_add);
    eval 'sub atomic_sub {
        my($n, $p) = @_;
	    eval q( &atomic_subtract_int($p, $n));
    }' unless defined(&atomic_sub);
} else {
    eval 'sub atomic_set {
        my($p, $v) = @_;
	    eval q((*($p) = ($v)));
    }' unless defined(&atomic_set);
    eval 'sub atomic_read {
        my($p) = @_;
	    eval q((*($p)));
    }' unless defined(&atomic_read);
    eval 'sub atomic_inc {
        my($p) = @_;
	    eval q((*($p) += 1));
    }' unless defined(&atomic_inc);
    eval 'sub atomic_dec {
        my($p) = @_;
	    eval q((*($p) -= 1));
    }' unless defined(&atomic_dec);
    eval 'sub atomic_add {
        my($n, $p) = @_;
	    eval q((*($p) += ($n)));
    }' unless defined(&atomic_add);
    eval 'sub atomic_sub {
        my($n, $p) = @_;
	    eval q((*($p) -= ($n)));
    }' unless defined(&atomic_sub);
    eval 'sub atomic_add_int {
        my($p, $v) = @_;
	    eval q(*($p) += $v);
    }' unless defined(&atomic_add_int);
    eval 'sub atomic_subtract_int {
        my($p, $v) = @_;
	    eval q(*($p) -= $v);
    }' unless defined(&atomic_subtract_int);
    if(defined(&__OpenBSD__)) {
	eval 'sub atomic_set_int {
	    my($p, $bits) = @_;
    	    eval q( &atomic_setbits_int($p,$bits));
	}' unless defined(&atomic_set_int);
	eval 'sub atomic_clear_int {
	    my($p, $bits) = @_;
    	    eval q( &atomic_clearbits_int($p,$bits));
	}' unless defined(&atomic_clear_int);
    } else {
	eval 'sub atomic_set_int {
	    my($p, $bits) = @_;
    	    eval q(*($p) |= ($bits));
	}' unless defined(&atomic_set_int);
	eval 'sub atomic_clear_int {
	    my($p, $bits) = @_;
    	    eval q(*($p) &= ~($bits));
	}' unless defined(&atomic_clear_int);
    }
}
if(!defined( &__FreeBSD_version) || ((defined(&__FreeBSD_version) ? &__FreeBSD_version : undef) < 500000)) {
    if(defined( &__i386__) || defined( &__amd64__)) {
    } else {
	eval 'sub atomic_cmpset_int {
	    my($dst,$old,$new) = @_;
    	    eval q({ \'int\'  &s =  &splhigh();  &if (*$dst==$old) { *$dst = $new;  &splx( &s); 1; }  &splx( &s); 0; });
	}' unless defined(&atomic_cmpset_int);
    }
}
unless(defined(&test_and_set_bit)) {
    sub test_and_set_bit {
	my($b,$p) = @_;
	eval q({ 'int'  &s =  &splhigh(); my $m = 1<<$b; my $r = *( &volatile 'int' *)$p &  $m; *( &volatile 'int' *)$p |=  $m;  &splx( &s);  $r; });
    }
}
unless(defined(&clear_bit)) {
    sub clear_bit {
	my($b,$p) = @_;
	eval q({  &atomic_clear_int((( &volatile 'int' *)$p) + ($b >> 5), 1<< ($b & 0x1f)); });
    }
}
unless(defined(&set_bit)) {
    sub set_bit {
	my($b,$p) = @_;
	eval q({  &atomic_set_int((( &volatile 'int' *)$p) + ($b >> 5), 1<< ($b & 0x1f)); });
    }
}
unless(defined(&test_bit)) {
    sub test_bit {
	my($b,$p) = @_;
	eval q({ (( &volatile 'int' *)$p)[$b >> 5] & (1<< ($b & 0x1f)); });
    }
}
unless(defined(&find_first_zero_bit)) {
    sub find_first_zero_bit {
	my($p,$max) = @_;
	eval q({ 'int'  &b;  &volatile 'int' * &ptr = ( &volatile 'int' *)$p;  &for ( &b = 0;  &b < $max;  &b += 32) {  &if ( $ptr[ &b >> 5] != ~0) {  &for (;;) {  &if (( $ptr[ &b >> 5] & (1<< ( &b & 0x1f))) == 0)  &b;  &b++; } } } $max; });
    }
}
1;
