231 lines
5.1 KiB
Bash
Executable File
231 lines
5.1 KiB
Bash
Executable File
#!/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
|