You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
5.1 KiB
230 lines
5.1 KiB
#!/bin/sh |
|
# |
|
# OVERVIEW |
|
# |
|
# Micro-experiment assembler. |
|
# |
|
# EXAMPLES |
|
# |
|
# asmexpr 'mov $-4096,%rax' 'not %rax' 'bsr %rax,%rax' |
|
# asmexpr 'mov $0,%ecx' 'vmovd %ecx,%xmm1' 'vpbroadcastb %xmm1,%ymm1' 'mov $0x20202032489001ff,%rax' 'vmovq %rax,%xmm0' 'vpcmpgtb %ymm1,%ymm0,%ymm2' |
|
|
|
c=/tmp/asmexpr.c |
|
s1=/tmp/asmexpr1.s |
|
s2=/tmp/asmexpr2.s |
|
s3=/tmp/asmexpr3.s |
|
x=/tmp/asmexpr.exe |
|
|
|
cat <<EOF >$s1 |
|
.comm rsp,8 |
|
.globl funk |
|
funk: push %rbp |
|
mov %rsp,%rbp |
|
push %rbx |
|
push %r12 |
|
push %r13 |
|
push %r14 |
|
push %r15 |
|
mov %rsp,rsp(%rip) |
|
xor %eax,%eax |
|
xor %ebx,%ebx |
|
xor %ecx,%ecx |
|
xor %edx,%edx |
|
xor %edi,%edi |
|
xor %esi,%esi |
|
xor %r8d,%r8d |
|
xor %r9d,%r9d |
|
xor %r10d,%r10d |
|
xor %r11d,%r11d |
|
xor %r12d,%r12d |
|
xor %r13d,%r13d |
|
xor %r14d,%r14d |
|
xor %r15d,%r15d |
|
vzeroall |
|
nop |
|
nop |
|
nop |
|
nop |
|
nop |
|
nop |
|
EOF |
|
|
|
cat <<EOF >$s2 |
|
.comm a,8 |
|
.comm b,8 |
|
.comm c,8 |
|
.comm x,8 |
|
.comm y,8 |
|
.comm z,8 |
|
EOF |
|
for i; do |
|
cat <<EOF >>$s2 |
|
$i |
|
EOF |
|
done |
|
|
|
cat <<EOF >$s3 |
|
.comm rsp,8 |
|
.comm regs,14*8 |
|
.comm flags,4 |
|
nop |
|
nop |
|
nop |
|
nop |
|
nop |
|
nop |
|
cld |
|
mov rsp(%rip),%rsp |
|
push %rbx |
|
lea regs(%rip),%rbx |
|
mov %rax,0(%rbx) |
|
pop %rax |
|
mov %rax,8(%rbx) |
|
mov %rcx,16(%rbx) |
|
mov %rdx,24(%rbx) |
|
mov %rdi,32(%rbx) |
|
mov %rsi,40(%rbx) |
|
mov %r8,48(%rbx) |
|
mov %r9,56(%rbx) |
|
mov %r10,64(%rbx) |
|
mov %r11,72(%rbx) |
|
mov %r12,80(%rbx) |
|
mov %r13,88(%rbx) |
|
mov %r14,96(%rbx) |
|
mov %r15,104(%rbx) |
|
vmovaps %ymm0,0x0a0(%rbx) |
|
vmovaps %ymm1,0x0c0(%rbx) |
|
vmovaps %ymm2,0x0e0(%rbx) |
|
vmovaps %ymm3,0x100(%rbx) |
|
vmovaps %ymm4,0x120(%rbx) |
|
vmovaps %ymm5,0x140(%rbx) |
|
vmovaps %ymm6,0x160(%rbx) |
|
vmovaps %ymm7,0x180(%rbx) |
|
vmovaps %ymm8,0x1a0(%rbx) |
|
vmovaps %ymm9,0x1c0(%rbx) |
|
vmovaps %ymm10,0x1e0(%rbx) |
|
vmovaps %ymm11,0x200(%rbx) |
|
vmovaps %ymm12,0x220(%rbx) |
|
vmovaps %ymm13,0x240(%rbx) |
|
vmovaps %ymm14,0x260(%rbx) |
|
vmovaps %ymm15,0x280(%rbx) |
|
pushf |
|
pop %rax |
|
mov %eax,flags(%rip) |
|
pop %r15 |
|
pop %r14 |
|
pop %r13 |
|
pop %r12 |
|
pop %rbx |
|
pop %rbp |
|
vzeroupper |
|
ret |
|
EOF |
|
|
|
cat <<EOF >$c |
|
#include <stdio.h> |
|
#include <string.h> |
|
|
|
struct GodHatesFlags { |
|
unsigned c : 1; /* bit 0: carry flag */ |
|
unsigned v : 1; /* bit 1: V flag: was 8085 signed-number overflow */ |
|
unsigned p : 1; /* bit 2: parity flag */ |
|
unsigned r : 1; /* bit 3: always zero */ |
|
unsigned a : 1; /* bit 4: auxiliary flag (nibble carry) */ |
|
unsigned k : 1; /* bit 5: K is for Kompressor (K = V flag ⊕ sgn(result)) */ |
|
unsigned z : 1; /* bit 6: zero flag */ |
|
unsigned s : 1; /* bit 7: sign flag */ |
|
unsigned t : 1; /* bit 8: it's a trap flag */ |
|
unsigned i : 1; /* bit 9: interrupt enable flag */ |
|
unsigned d : 1; /* bit 10: direction flag */ |
|
unsigned o : 1; /* bit 11: overflow flag */ |
|
unsigned pl : 2; /* b12-13: i/o privilege level (80286+) */ |
|
unsigned nt : 1; /* bit 14: nested task flag (80286+) */ |
|
unsigned pc : 1; /* bit 15: oldskool flag */ |
|
unsigned blah : 16; |
|
unsigned blah2 : 32; |
|
}; |
|
|
|
char *DescribeFlags(struct GodHatesFlags flags) { |
|
static char buf[256]; |
|
buf[0] = 0; |
|
if (flags.c) strcat(buf, "CF "); |
|
if (flags.p) strcat(buf, "PF "); |
|
if (flags.a) strcat(buf, "AF "); |
|
if (flags.z) strcat(buf, "ZF "); |
|
if (flags.s) strcat(buf, "SF "); |
|
if (flags.t) strcat(buf, "TF "); |
|
if (flags.i) strcat(buf, "IF "); |
|
if (flags.d) strcat(buf, "DF "); |
|
if (flags.o) strcat(buf, "OF "); |
|
strcat(buf, "IOPL-"); |
|
switch (flags.pl) { |
|
case 0: |
|
strcat(buf, "0"); |
|
break; |
|
case 1: |
|
strcat(buf, "1"); |
|
break; |
|
case 2: |
|
strcat(buf, "2"); |
|
break; |
|
case 3: |
|
strcat(buf, "3"); |
|
break; |
|
default: |
|
__builtin_unreachable(); |
|
} |
|
strcat(buf, " "); |
|
if (flags.nt) strcat(buf, "NT "); |
|
if (flags.r || flags.k || flags.pc) { |
|
strcat(buf, "[WOW: "); |
|
if (flags.v) strcat(buf, "VF "); |
|
if (flags.k) strcat(buf, "KF "); |
|
if (flags.r) strcat(buf, "RF "); |
|
if (flags.pc) strcat(buf, "PC "); |
|
strcat(buf, "] "); |
|
} |
|
return &buf[0]; |
|
} |
|
|
|
void funk(); |
|
struct GodHatesFlags flags; |
|
struct { |
|
long gen[14]; |
|
long __pad[6]; |
|
unsigned long ymms[16][4]; |
|
} regs; |
|
static const char regnames[][4] = {"rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}; |
|
int main() { |
|
funk(); |
|
printf("flags %45s\n\n", DescribeFlags(flags)); |
|
for (unsigned i = 0; i < 14; ++i) { |
|
if (regs.gen[i]) { |
|
printf("%s s 0x%08x %20d\\n", regnames[i], (signed)(regs.gen[i]), (signed)(regs.gen[i])); |
|
printf(" u 0x%08x %20u\\n", (unsigned)(regs.gen[i]), (unsigned)(regs.gen[i])); |
|
printf(" sll 0x%016llx %20lld\\n", (signed long long)(regs.gen[i]), (signed long long)(regs.gen[i])); |
|
printf(" ull 0x%016llx %20llu\\n", (unsigned long long)(regs.gen[i]), (unsigned long long)(regs.gen[i])); |
|
printf("\n"); |
|
} |
|
} |
|
for (unsigned i = 0; i < 16; ++i) { |
|
if (regs.ymms[i][0] || regs.ymms[i][1] || regs.ymms[i][2] || regs.ymms[i][3]) { |
|
printf("ymm%d%s %016lx%016lx%016lx%016lx\\n", i, i < 10 ? " " : "", regs.ymms[i][3], regs.ymms[i][2], regs.ymms[i][1], regs.ymms[i][0]); |
|
} |
|
} |
|
return 0; |
|
} |
|
EOF |
|
|
|
cc -c -g -o $c.o $c && |
|
cc -c -g -o $s1.o $s1 && |
|
cc -c -g -o $s2.o $s2 && |
|
cc -c -g -o $s3.o $s3 && |
|
cc -g -o $x $c $s1.o $s2.o $s3.o && { |
|
echo |
|
objdump -d $s2.o | sed 1,7d |
|
echo |
|
$x |
|
} |
|
|
|
exit
|
|
|