#!/bin/perl -w
#
# Generate 12-bit immediate ARM constants

use strict;

my ($lang) = @ARGV;

if ($lang eq 'c') {
    gen_c();
} elsif ($lang eq 's') {
    gen_s();
} else {
    die "Usage: $0 {c|s}\n";
}

# Convert an ARM 12-bit immediate field to the 32-bit binary value
sub i12tobin {
    my ($i) = @_;
    my $b = $i & 0xff;
    my $x = 2 * (($i >> 8) & 0xf);
    if ($x == 0) {
        return $b;
    } elsif ($x < 8) {
        my $l = $b >> $x;
        my $h = ($b & ((1 << $x) - 1)) << (32 - $x);
        return ($h | $l);
    } else {
        return ($b << (32 - $x));
    }
}

sub gen_c {
    printf "typedef unsigned int u32;\n";
    for (my $i = 0; $i < 4096; $i++) {
        printf "u32 x%03x() { return %dU; }\n", $i, i12tobin($i);
    }
    for (my $i = 0; $i < 4096; $i++) {
        printf "u32 b%03x() { return %dU; }\n", $i, $i;
    }
}


sub gen_s {
    printf ".global xvals\n.type xvals,function\n.align 5\nxvals:\n";
    for (my $i = 0; $i < 4096; $i++) {
        printf " sub r2,r1,#%d\n", i12tobin($i);
    }
    printf ".size xvals,.-xvals\n";
#    printf ".global bvals\n.type bvals,function\n.align 5\nbvals:\n";
#    for (my $i = 0; $i < 4096; $i++) {
#       printf " sub r1,r2,#%d\n", $i;
#    }
#    printf ".size bvals,.-bvals\n";
}
