perfaware/part1: Support add instructions
This commit is contained in:
parent
9f76a7d181
commit
bcd509318c
@ -8,7 +8,7 @@
|
|||||||
;
|
;
|
||||||
; Please see https://computerenhance.com for further information
|
; Please see https://computerenhance.com for further information
|
||||||
;
|
;
|
||||||
; ======================================================================== */
|
; ========================================================================
|
||||||
|
|
||||||
; ========================================================================
|
; ========================================================================
|
||||||
; LISTING 37
|
; LISTING 37
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
;
|
;
|
||||||
; Please see https://computerenhance.com for further information
|
; Please see https://computerenhance.com for further information
|
||||||
;
|
;
|
||||||
; ======================================================================== */
|
; ========================================================================
|
||||||
|
|
||||||
; ========================================================================
|
; ========================================================================
|
||||||
; LISTING 38
|
; LISTING 38
|
||||||
|
Binary file not shown.
@ -21,10 +21,12 @@ mov si, bx
|
|||||||
mov dh, al
|
mov dh, al
|
||||||
|
|
||||||
; 8-bit immediate-to-register
|
; 8-bit immediate-to-register
|
||||||
mov cx, 12
|
mov cl, 12
|
||||||
mov cx, -12
|
mov ch, -12
|
||||||
|
|
||||||
; 16-bit immediate-to-register
|
; 16-bit immediate-to-register
|
||||||
|
mov cx, 12
|
||||||
|
mov cx, -12
|
||||||
mov dx, 3948
|
mov dx, 3948
|
||||||
mov dx, -3948
|
mov dx, -3948
|
||||||
|
|
||||||
|
BIN
part1/listing_0041_add_sub_cmp_jnz
Normal file
BIN
part1/listing_0041_add_sub_cmp_jnz
Normal file
Binary file not shown.
121
part1/listing_0041_add_sub_cmp_jnz.asm
Normal file
121
part1/listing_0041_add_sub_cmp_jnz.asm
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
|
||||||
|
;
|
||||||
|
; This software is provided 'as-is', without any express or implied
|
||||||
|
; warranty. In no event will the authors be held liable for any damages
|
||||||
|
; arising from the use of this software.
|
||||||
|
;
|
||||||
|
; Please see https://computerenhance.com for further information
|
||||||
|
;
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
; ========================================================================
|
||||||
|
; LISTING 41
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
add bx, [bx+si]
|
||||||
|
add bx, [bp]
|
||||||
|
add si, 2
|
||||||
|
add bp, 2
|
||||||
|
add cx, 8
|
||||||
|
add bx, [bp + 0]
|
||||||
|
add cx, [bx + 2]
|
||||||
|
add bh, [bp + si + 4]
|
||||||
|
add di, [bp + di + 6]
|
||||||
|
add [bx+si], bx
|
||||||
|
add [bp], bx
|
||||||
|
add [bp + 0], bx
|
||||||
|
add [bx + 2], cx
|
||||||
|
add [bp + si + 4], bh
|
||||||
|
add [bp + di + 6], di
|
||||||
|
add byte [bx], 34
|
||||||
|
add word [bp + si + 1000], 29
|
||||||
|
add ax, [bp]
|
||||||
|
add al, [bx + si]
|
||||||
|
add ax, bx
|
||||||
|
add al, ah
|
||||||
|
add ax, 1000
|
||||||
|
add al, -30
|
||||||
|
add al, 9
|
||||||
|
|
||||||
|
sub bx, [bx+si]
|
||||||
|
sub bx, [bp]
|
||||||
|
sub si, 2
|
||||||
|
sub bp, 2
|
||||||
|
sub cx, 8
|
||||||
|
sub bx, [bp + 0]
|
||||||
|
sub cx, [bx + 2]
|
||||||
|
sub bh, [bp + si + 4]
|
||||||
|
sub di, [bp + di + 6]
|
||||||
|
sub [bx+si], bx
|
||||||
|
sub [bp], bx
|
||||||
|
sub [bp + 0], bx
|
||||||
|
sub [bx + 2], cx
|
||||||
|
sub [bp + si + 4], bh
|
||||||
|
sub [bp + di + 6], di
|
||||||
|
sub byte [bx], 34
|
||||||
|
sub word [bx + di], 29
|
||||||
|
sub ax, [bp]
|
||||||
|
sub al, [bx + si]
|
||||||
|
sub ax, bx
|
||||||
|
sub al, ah
|
||||||
|
sub ax, 1000
|
||||||
|
sub al, -30
|
||||||
|
sub al, 9
|
||||||
|
|
||||||
|
cmp bx, [bx+si]
|
||||||
|
cmp bx, [bp]
|
||||||
|
cmp si, 2
|
||||||
|
cmp bp, 2
|
||||||
|
cmp cx, 8
|
||||||
|
cmp bx, [bp + 0]
|
||||||
|
cmp cx, [bx + 2]
|
||||||
|
cmp bh, [bp + si + 4]
|
||||||
|
cmp di, [bp + di + 6]
|
||||||
|
cmp [bx+si], bx
|
||||||
|
cmp [bp], bx
|
||||||
|
cmp [bp + 0], bx
|
||||||
|
cmp [bx + 2], cx
|
||||||
|
cmp [bp + si + 4], bh
|
||||||
|
cmp [bp + di + 6], di
|
||||||
|
cmp byte [bx], 34
|
||||||
|
cmp word [4834], 29
|
||||||
|
cmp ax, [bp]
|
||||||
|
cmp al, [bx + si]
|
||||||
|
cmp ax, bx
|
||||||
|
cmp al, ah
|
||||||
|
cmp ax, 1000
|
||||||
|
cmp al, -30
|
||||||
|
cmp al, 9
|
||||||
|
|
||||||
|
test_label0:
|
||||||
|
jnz test_label1
|
||||||
|
jnz test_label0
|
||||||
|
test_label1:
|
||||||
|
jnz test_label0
|
||||||
|
jnz test_label1
|
||||||
|
|
||||||
|
label:
|
||||||
|
je label
|
||||||
|
jl label
|
||||||
|
jle label
|
||||||
|
jb label
|
||||||
|
jbe label
|
||||||
|
jp label
|
||||||
|
jo label
|
||||||
|
js label
|
||||||
|
jne label
|
||||||
|
jnl label
|
||||||
|
jg label
|
||||||
|
jnb label
|
||||||
|
ja label
|
||||||
|
jnp label
|
||||||
|
jno label
|
||||||
|
jns label
|
||||||
|
loop label
|
||||||
|
loopz label
|
||||||
|
loopnz label
|
||||||
|
jcxz label
|
BIN
part1/listing_0042_completionist_decode
Normal file
BIN
part1/listing_0042_completionist_decode
Normal file
Binary file not shown.
425
part1/listing_0042_completionist_decode.asm
Normal file
425
part1/listing_0042_completionist_decode.asm
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
|
||||||
|
;
|
||||||
|
; This software is provided 'as-is', without any express or implied
|
||||||
|
; warranty. In no event will the authors be held liable for any damages
|
||||||
|
; arising from the use of this software.
|
||||||
|
;
|
||||||
|
; Please see https://computerenhance.com for further information
|
||||||
|
;
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
; ========================================================================
|
||||||
|
; LISTING 42
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
;
|
||||||
|
; NOTE(casey): This is not meant to be a real compliance test for 8086
|
||||||
|
; disassemblers. It's just a reasonable selection of opcodes and patterns
|
||||||
|
; to use as a first pass in making sure a disassembler handles a large
|
||||||
|
; cross-section of the encoding. To be absolutely certain you haven't
|
||||||
|
; missed something, you would need a more exhaustive listing!
|
||||||
|
;
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
mov si, bx
|
||||||
|
mov dh, al
|
||||||
|
mov cl, 12
|
||||||
|
mov ch, -12
|
||||||
|
mov cx, 12
|
||||||
|
mov cx, -12
|
||||||
|
mov dx, 3948
|
||||||
|
mov dx, -3948
|
||||||
|
mov al, [bx + si]
|
||||||
|
mov bx, [bp + di]
|
||||||
|
mov dx, [bp]
|
||||||
|
mov ah, [bx + si + 4]
|
||||||
|
mov al, [bx + si + 4999]
|
||||||
|
mov [bx + di], cx
|
||||||
|
mov [bp + si], cl
|
||||||
|
mov [bp], ch
|
||||||
|
mov ax, [bx + di - 37]
|
||||||
|
mov [si - 300], cx
|
||||||
|
mov dx, [bx - 32]
|
||||||
|
mov [bp + di], byte 7
|
||||||
|
mov [di + 901], word 347
|
||||||
|
mov bp, [5]
|
||||||
|
mov bx, [3458]
|
||||||
|
mov ax, [2555]
|
||||||
|
mov ax, [16]
|
||||||
|
mov [2554], ax
|
||||||
|
mov [15], ax
|
||||||
|
|
||||||
|
push word [bp + si]
|
||||||
|
push word [3000]
|
||||||
|
push word [bx + di - 30]
|
||||||
|
push cx
|
||||||
|
push ax
|
||||||
|
push dx
|
||||||
|
push cs
|
||||||
|
|
||||||
|
pop word [bp + si]
|
||||||
|
pop word [3]
|
||||||
|
pop word [bx + di - 3000]
|
||||||
|
pop sp
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
xchg ax, [bp - 1000]
|
||||||
|
xchg [bx + 50], bp
|
||||||
|
|
||||||
|
xchg ax, ax
|
||||||
|
xchg ax, dx
|
||||||
|
xchg ax, sp
|
||||||
|
xchg ax, si
|
||||||
|
xchg ax, di
|
||||||
|
|
||||||
|
xchg cx, dx
|
||||||
|
xchg si, cx
|
||||||
|
xchg cl, ah
|
||||||
|
|
||||||
|
in al, 200
|
||||||
|
in al, dx
|
||||||
|
in ax, dx
|
||||||
|
|
||||||
|
out 44, ax
|
||||||
|
out dx, al
|
||||||
|
|
||||||
|
xlat
|
||||||
|
lea ax, [bx + di + 1420]
|
||||||
|
lea bx, [bp - 50]
|
||||||
|
lea sp, [bp - 1003]
|
||||||
|
lea di, [bx + si - 7]
|
||||||
|
|
||||||
|
lds ax, [bx + di + 1420]
|
||||||
|
lds bx, [bp - 50]
|
||||||
|
lds sp, [bp - 1003]
|
||||||
|
lds di, [bx + si - 7]
|
||||||
|
|
||||||
|
les ax, [bx + di + 1420]
|
||||||
|
les bx, [bp - 50]
|
||||||
|
les sp, [bp - 1003]
|
||||||
|
les di, [bx + si - 7]
|
||||||
|
|
||||||
|
lahf
|
||||||
|
sahf
|
||||||
|
pushf
|
||||||
|
popf
|
||||||
|
|
||||||
|
add cx, [bp]
|
||||||
|
add dx, [bx + si]
|
||||||
|
add [bp + di + 5000], ah
|
||||||
|
add [bx], al
|
||||||
|
add sp, 392
|
||||||
|
add si, 5
|
||||||
|
add ax, 1000
|
||||||
|
add ah, 30
|
||||||
|
add al, 9
|
||||||
|
add cx, bx
|
||||||
|
add ch, al
|
||||||
|
|
||||||
|
adc cx, [bp]
|
||||||
|
adc dx, [bx + si]
|
||||||
|
adc [bp + di + 5000], ah
|
||||||
|
adc [bx], al
|
||||||
|
adc sp, 392
|
||||||
|
adc si, 5
|
||||||
|
adc ax, 1000
|
||||||
|
adc ah, 30
|
||||||
|
adc al, 9
|
||||||
|
adc cx, bx
|
||||||
|
adc ch, al
|
||||||
|
|
||||||
|
inc ax
|
||||||
|
inc cx
|
||||||
|
inc dh
|
||||||
|
inc al
|
||||||
|
inc ah
|
||||||
|
inc sp
|
||||||
|
inc di
|
||||||
|
inc byte [bp + 1002]
|
||||||
|
inc word [bx + 39]
|
||||||
|
inc byte [bx + si + 5]
|
||||||
|
inc word [bp + di - 10044]
|
||||||
|
inc word [9349]
|
||||||
|
inc byte [bp]
|
||||||
|
|
||||||
|
aaa
|
||||||
|
daa
|
||||||
|
|
||||||
|
sub cx, [bp]
|
||||||
|
sub dx, [bx + si]
|
||||||
|
sub [bp + di + 5000], ah
|
||||||
|
sub [bx], al
|
||||||
|
sub sp, 392
|
||||||
|
sub si, 5
|
||||||
|
sub ax, 1000
|
||||||
|
sub ah, 30
|
||||||
|
sub al, 9
|
||||||
|
sub cx, bx
|
||||||
|
sub ch, al
|
||||||
|
|
||||||
|
sbb cx, [bp]
|
||||||
|
sbb dx, [bx + si]
|
||||||
|
sbb [bp + di + 5000], ah
|
||||||
|
sbb [bx], al
|
||||||
|
sbb sp, 392
|
||||||
|
sbb si, 5
|
||||||
|
sbb ax, 1000
|
||||||
|
sbb ah, 30
|
||||||
|
sbb al, 9
|
||||||
|
sbb cx, bx
|
||||||
|
sbb ch, al
|
||||||
|
|
||||||
|
dec ax
|
||||||
|
dec cx
|
||||||
|
dec dh
|
||||||
|
dec al
|
||||||
|
dec ah
|
||||||
|
dec sp
|
||||||
|
dec di
|
||||||
|
dec byte [bp + 1002]
|
||||||
|
dec word [bx + 39]
|
||||||
|
dec byte [bx + si + 5]
|
||||||
|
dec word [bp + di - 10044]
|
||||||
|
dec word [9349]
|
||||||
|
dec byte [bp]
|
||||||
|
|
||||||
|
neg ax
|
||||||
|
neg cx
|
||||||
|
neg dh
|
||||||
|
neg al
|
||||||
|
neg ah
|
||||||
|
neg sp
|
||||||
|
neg di
|
||||||
|
neg byte [bp + 1002]
|
||||||
|
neg word [bx + 39]
|
||||||
|
neg byte [bx + si + 5]
|
||||||
|
neg word [bp + di - 10044]
|
||||||
|
neg word [9349]
|
||||||
|
neg byte [bp]
|
||||||
|
|
||||||
|
cmp bx, cx
|
||||||
|
cmp dh, [bp + 390]
|
||||||
|
cmp [bp + 2], si
|
||||||
|
cmp bl, 20
|
||||||
|
cmp byte [bx], 34
|
||||||
|
cmp ax, 23909
|
||||||
|
|
||||||
|
aas
|
||||||
|
das
|
||||||
|
|
||||||
|
mul al
|
||||||
|
mul cx
|
||||||
|
mul word [bp]
|
||||||
|
mul byte [bx + di + 500]
|
||||||
|
|
||||||
|
imul ch
|
||||||
|
imul dx
|
||||||
|
imul byte [bx]
|
||||||
|
imul word [9483]
|
||||||
|
|
||||||
|
aam
|
||||||
|
|
||||||
|
div bl
|
||||||
|
div sp
|
||||||
|
div byte [bx + si + 2990]
|
||||||
|
div word [bp + di + 1000]
|
||||||
|
|
||||||
|
idiv ax
|
||||||
|
idiv si
|
||||||
|
idiv byte [bp + si]
|
||||||
|
idiv word [bx + 493]
|
||||||
|
|
||||||
|
aad
|
||||||
|
cbw
|
||||||
|
cwd
|
||||||
|
|
||||||
|
not ah
|
||||||
|
not bl
|
||||||
|
not sp
|
||||||
|
not si
|
||||||
|
not word [bp]
|
||||||
|
not byte [bp + 9905]
|
||||||
|
|
||||||
|
shl ah, 1
|
||||||
|
shr ax, 1
|
||||||
|
sar bx, 1
|
||||||
|
rol cx, 1
|
||||||
|
ror dh, 1
|
||||||
|
rcl sp, 1
|
||||||
|
rcr bp, 1
|
||||||
|
|
||||||
|
shl word [bp + 5], 1
|
||||||
|
shr byte [bx + si - 199], 1
|
||||||
|
sar byte [bx + di - 300], 1
|
||||||
|
rol word [bp], 1
|
||||||
|
ror word [4938], 1
|
||||||
|
rcl byte [3], 1
|
||||||
|
rcr word [bx], 1
|
||||||
|
|
||||||
|
shl ah, cl
|
||||||
|
shr ax, cl
|
||||||
|
sar bx, cl
|
||||||
|
rol cx, cl
|
||||||
|
ror dh, cl
|
||||||
|
rcl sp, cl
|
||||||
|
rcr bp, cl
|
||||||
|
|
||||||
|
shl word [bp + 5], cl
|
||||||
|
shr word [bx + si - 199], cl
|
||||||
|
sar byte [bx + di - 300], cl
|
||||||
|
rol byte [bp], cl
|
||||||
|
ror byte [4938], cl
|
||||||
|
rcl byte [3], cl
|
||||||
|
rcr word [bx], cl
|
||||||
|
|
||||||
|
and al, ah
|
||||||
|
and ch, cl
|
||||||
|
and bp, si
|
||||||
|
and di, sp
|
||||||
|
and al, 93
|
||||||
|
and ax, 20392
|
||||||
|
and [bp + si + 10], ch
|
||||||
|
and [bx + di + 1000], dx
|
||||||
|
and bx, [bp]
|
||||||
|
and cx, [4384]
|
||||||
|
and byte [bp - 39], 239
|
||||||
|
and word [bx + si - 4332], 10328
|
||||||
|
|
||||||
|
test bx, cx
|
||||||
|
test dh, [bp + 390]
|
||||||
|
test [bp + 2], si
|
||||||
|
test bl, 20
|
||||||
|
test byte [bx], 34
|
||||||
|
test ax, 23909
|
||||||
|
|
||||||
|
or al, ah
|
||||||
|
or ch, cl
|
||||||
|
or bp, si
|
||||||
|
or di, sp
|
||||||
|
or al, 93
|
||||||
|
or ax, 20392
|
||||||
|
or [bp + si + 10], ch
|
||||||
|
or [bx + di + 1000], dx
|
||||||
|
or bx, [bp]
|
||||||
|
or cx, [4384]
|
||||||
|
or byte [bp - 39], 239
|
||||||
|
or word [bx + si - 4332], 10328
|
||||||
|
|
||||||
|
xor al, ah
|
||||||
|
xor ch, cl
|
||||||
|
xor bp, si
|
||||||
|
xor di, sp
|
||||||
|
xor al, 93
|
||||||
|
xor ax, 20392
|
||||||
|
xor [bp + si + 10], ch
|
||||||
|
xor [bx + di + 1000], dx
|
||||||
|
xor bx, [bp]
|
||||||
|
xor cx, [4384]
|
||||||
|
xor byte [bp - 39], 239
|
||||||
|
xor word [bx + si - 4332], 10328
|
||||||
|
|
||||||
|
rep movsb
|
||||||
|
rep cmpsb
|
||||||
|
rep scasb
|
||||||
|
rep lodsb
|
||||||
|
rep movsw
|
||||||
|
rep cmpsw
|
||||||
|
rep scasw
|
||||||
|
rep lodsw
|
||||||
|
|
||||||
|
; NOTE(casey): Special thanks (as always!) to Mārtiņš Možeiko for figuring out why NASM
|
||||||
|
; wouldn't compile "rep stds" instructions. It was because it was a misprint in the 8086
|
||||||
|
; manual! It was really just "rep stos", which of course is still in x64, and NASM
|
||||||
|
; assembles it just fine.
|
||||||
|
rep stosb
|
||||||
|
rep stosw
|
||||||
|
|
||||||
|
call [39201]
|
||||||
|
call [bp - 100]
|
||||||
|
call sp
|
||||||
|
call ax
|
||||||
|
|
||||||
|
jmp ax
|
||||||
|
jmp di
|
||||||
|
jmp [12]
|
||||||
|
jmp [4395]
|
||||||
|
|
||||||
|
ret -7
|
||||||
|
ret 500
|
||||||
|
ret
|
||||||
|
|
||||||
|
label:
|
||||||
|
je label
|
||||||
|
jl label
|
||||||
|
jle label
|
||||||
|
jb label
|
||||||
|
jbe label
|
||||||
|
jp label
|
||||||
|
jo label
|
||||||
|
js label
|
||||||
|
jne label
|
||||||
|
jnl label
|
||||||
|
jg label
|
||||||
|
jnb label
|
||||||
|
ja label
|
||||||
|
jnp label
|
||||||
|
jno label
|
||||||
|
jns label
|
||||||
|
loop label
|
||||||
|
loopz label
|
||||||
|
loopnz label
|
||||||
|
jcxz label
|
||||||
|
|
||||||
|
int 13
|
||||||
|
int 3
|
||||||
|
|
||||||
|
into
|
||||||
|
iret
|
||||||
|
|
||||||
|
clc
|
||||||
|
cmc
|
||||||
|
stc
|
||||||
|
cld
|
||||||
|
std
|
||||||
|
cli
|
||||||
|
sti
|
||||||
|
hlt
|
||||||
|
wait
|
||||||
|
|
||||||
|
lock not byte [bp + 9905]
|
||||||
|
lock xchg [100], al
|
||||||
|
|
||||||
|
mov al, cs:[bx + si]
|
||||||
|
mov bx, ds:[bp + di]
|
||||||
|
mov dx, es:[bp]
|
||||||
|
mov ah, ss:[bx + si + 4]
|
||||||
|
|
||||||
|
and ss:[bp + si + 10], ch
|
||||||
|
or ds:[bx + di + 1000], dx
|
||||||
|
xor bx, es:[bp]
|
||||||
|
cmp cx, es:[4384]
|
||||||
|
test byte cs:[bp - 39], 239
|
||||||
|
sbb word cs:[bx + si - 4332], 10328
|
||||||
|
|
||||||
|
lock not byte CS:[bp + 9905]
|
||||||
|
|
||||||
|
;
|
||||||
|
; TODO(casey): I would like to uncomment this, but as far as I can tell, NASM doesn't recognize the ESC instruction :(
|
||||||
|
; so even if I just force the assembler to output the bits here, our disasm will fail to assemble because it will (correctly!)
|
||||||
|
; print the esc instruction and NASM will error because it doesn't know what that is.
|
||||||
|
;
|
||||||
|
; esc 938,ax
|
||||||
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; TODO(casey): According to NASM, "rep movsb" is "not lockable". However the 8086 manual seems to think it is, and
|
||||||
|
; even describes what happens when you you lock a rep: the lock is held for the duration of the rep operation. So...
|
||||||
|
; yeah. Not sure why this doesn't work in NASM:
|
||||||
|
;
|
||||||
|
; lock rep movsb
|
||||||
|
;
|
147
part1/sim8086.c
147
part1/sim8086.c
@ -76,6 +76,9 @@ typedef enum S86_InstructionType {
|
|||||||
S86_InstructionType_MOVAccumToMem,
|
S86_InstructionType_MOVAccumToMem,
|
||||||
S86_InstructionType_MOVRegOrMemToSegReg,
|
S86_InstructionType_MOVRegOrMemToSegReg,
|
||||||
S86_InstructionType_MOVSegRegToRegOrMem,
|
S86_InstructionType_MOVSegRegToRegOrMem,
|
||||||
|
S86_InstructionType_ADDRegOrMemToOrFromReg,
|
||||||
|
S86_InstructionType_ADDImmediateToRegOrMem,
|
||||||
|
S86_InstructionType_ADDImmediateToAccum,
|
||||||
S86_InstructionType_Count,
|
S86_InstructionType_Count,
|
||||||
} S86_InstructionType;
|
} S86_InstructionType;
|
||||||
|
|
||||||
@ -128,6 +131,21 @@ S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = {
|
|||||||
.op_bits0 = 0b1000'1100,
|
.op_bits0 = 0b1000'1100,
|
||||||
.op_mask1 = 0b0010'0000,
|
.op_mask1 = 0b0010'0000,
|
||||||
.op_bits1 = 0b0000'0000},
|
.op_bits1 = 0b0000'0000},
|
||||||
|
|
||||||
|
[S86_InstructionType_ADDRegOrMemToOrFromReg] = {.op_mask0 = 0b1111'1100,
|
||||||
|
.op_bits0 = 0b0000'0000,
|
||||||
|
.op_mask1 = 0b0000'0000,
|
||||||
|
.op_bits1 = 0b0000'0000},
|
||||||
|
|
||||||
|
[S86_InstructionType_ADDImmediateToRegOrMem] = {.op_mask0 = 0b1111'1100,
|
||||||
|
.op_bits0 = 0b1000'0000,
|
||||||
|
.op_mask1 = 0b0011'1000,
|
||||||
|
.op_bits1 = 0b0000'0000},
|
||||||
|
|
||||||
|
[S86_InstructionType_ADDImmediateToAccum] = {.op_mask0 = 0b1111'1110,
|
||||||
|
.op_bits0 = 0b0000'0100,
|
||||||
|
.op_mask1 = 0b0000'0000,
|
||||||
|
.op_bits1 = 0b0000'0000},
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct S86_EffectiveAddressStr8 {
|
typedef struct S86_EffectiveAddressStr8 {
|
||||||
@ -135,7 +153,7 @@ typedef struct S86_EffectiveAddressStr8 {
|
|||||||
size_t size;
|
size_t size;
|
||||||
} S86_EffectiveAddressStr8;
|
} S86_EffectiveAddressStr8;
|
||||||
|
|
||||||
S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it, uint8_t rm, uint8_t mod);
|
S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it, uint8_t rm, uint8_t mod, uint8_t w);
|
||||||
|
|
||||||
// NOTE: Implementation
|
// NOTE: Implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -282,7 +300,8 @@ void S86_PrintLnFmt(char const *fmt, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it, uint8_t rm, uint8_t mod)
|
S86_Str8 REGISTER_FIELD_ENCODING[2][8];
|
||||||
|
S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it, uint8_t rm, uint8_t mod, uint8_t w)
|
||||||
{
|
{
|
||||||
// NOTE: Calculate displacement
|
// NOTE: Calculate displacement
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
@ -295,12 +314,17 @@ S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it,
|
|||||||
} else if (mod == 0b01) { // Mem mode 8 bit displacement
|
} else if (mod == 0b01) { // Mem mode 8 bit displacement
|
||||||
displacement = (int8_t)S86_BufferIteratorNextByte(buffer_it);
|
displacement = (int8_t)S86_BufferIteratorNextByte(buffer_it);
|
||||||
} else {
|
} else {
|
||||||
S86_ASSERT(mod == 0b00 /*Mem mode (no displacement)*/);
|
S86_ASSERT(mod == 0b00 || mod == 0b11 /*Mem mode (no displacement)*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
S86_EffectiveAddressStr8 result = {0};
|
||||||
|
if (mod == 0b11) {
|
||||||
|
S86_Str8 register_field = REGISTER_FIELD_ENCODING[w][rm];
|
||||||
|
memcpy(result.data, register_field.data, register_field.size);
|
||||||
|
result.size = register_field.size;
|
||||||
|
} else {
|
||||||
// NOTE: Effective address calculation w/ displacement
|
// NOTE: Effective address calculation w/ displacement
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
S86_EffectiveAddressStr8 result = {0};
|
|
||||||
result.data[result.size++] = '[';
|
result.data[result.size++] = '[';
|
||||||
if (direct_address) {
|
if (direct_address) {
|
||||||
result.size += snprintf(result.data + result.size,
|
result.size += snprintf(result.data + result.size,
|
||||||
@ -332,6 +356,7 @@ S86_EffectiveAddressStr8 S86_EffectiveAddressCalc(S86_BufferIterator *buffer_it,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.data[result.size++] = ']';
|
result.data[result.size++] = ']';
|
||||||
|
}
|
||||||
|
|
||||||
S86_ASSERT(result.size < S86_ARRAY_UCOUNT(result.data));
|
S86_ASSERT(result.size < S86_ARRAY_UCOUNT(result.data));
|
||||||
return result;
|
return result;
|
||||||
@ -356,30 +381,23 @@ int main(int argc, char **argv)
|
|||||||
// NOTE: Sim8086
|
// NOTE: Sim8086
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Mapping from a 'reg' encoding to the register name.
|
// Mapping from a 'reg' encoding to the register name.
|
||||||
S86_Str8 const REGISTER_FIELD_ENCODING[2][8] = {
|
REGISTER_FIELD_ENCODING[0b0][0] = S86_STR8("al");
|
||||||
[0b0] =
|
REGISTER_FIELD_ENCODING[0b0][1] = S86_STR8("cl");
|
||||||
{
|
REGISTER_FIELD_ENCODING[0b0][2] = S86_STR8("dl");
|
||||||
S86_STR8("al"),
|
REGISTER_FIELD_ENCODING[0b0][3] = S86_STR8("bl");
|
||||||
S86_STR8("cl"),
|
REGISTER_FIELD_ENCODING[0b0][4] = S86_STR8("ah");
|
||||||
S86_STR8("dl"),
|
REGISTER_FIELD_ENCODING[0b0][5] = S86_STR8("ch");
|
||||||
S86_STR8("bl"),
|
REGISTER_FIELD_ENCODING[0b0][6] = S86_STR8("dh");
|
||||||
S86_STR8("ah"),
|
REGISTER_FIELD_ENCODING[0b0][7] = S86_STR8("bh");
|
||||||
S86_STR8("ch"),
|
|
||||||
S86_STR8("dh"),
|
REGISTER_FIELD_ENCODING[0b1][0] = S86_STR8("ax");
|
||||||
S86_STR8("bh"),
|
REGISTER_FIELD_ENCODING[0b1][1] = S86_STR8("cx");
|
||||||
},
|
REGISTER_FIELD_ENCODING[0b1][2] = S86_STR8("dx");
|
||||||
[0b1] =
|
REGISTER_FIELD_ENCODING[0b1][3] = S86_STR8("bx");
|
||||||
{
|
REGISTER_FIELD_ENCODING[0b1][4] = S86_STR8("sp");
|
||||||
S86_STR8("ax"),
|
REGISTER_FIELD_ENCODING[0b1][5] = S86_STR8("bp");
|
||||||
S86_STR8("cx"),
|
REGISTER_FIELD_ENCODING[0b1][6] = S86_STR8("si");
|
||||||
S86_STR8("dx"),
|
REGISTER_FIELD_ENCODING[0b1][7] = S86_STR8("di");
|
||||||
S86_STR8("bx"),
|
|
||||||
S86_STR8("sp"),
|
|
||||||
S86_STR8("bp"),
|
|
||||||
S86_STR8("si"),
|
|
||||||
S86_STR8("di"),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// NOTE: Decode assembly
|
// NOTE: Decode assembly
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
@ -430,6 +448,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
switch (instruction_type) {
|
switch (instruction_type) {
|
||||||
|
|
||||||
|
case S86_InstructionType_ADDRegOrMemToOrFromReg: /*FALLTHRU*/
|
||||||
case S86_InstructionType_MOVRegOrMemToOrFromReg: {
|
case S86_InstructionType_MOVRegOrMemToOrFromReg: {
|
||||||
// NOTE: Instruction does not have opcode bits in the 2nd byte
|
// NOTE: Instruction does not have opcode bits in the 2nd byte
|
||||||
S86_ASSERT(op_code_size == 1);
|
S86_ASSERT(op_code_size == 1);
|
||||||
@ -446,55 +465,90 @@ int main(int argc, char **argv)
|
|||||||
S86_ASSERT(reg < 8);
|
S86_ASSERT(reg < 8);
|
||||||
S86_ASSERT(rm < 8);
|
S86_ASSERT(rm < 8);
|
||||||
|
|
||||||
|
S86_Str8 op = {0};
|
||||||
|
if (instruction_type == S86_InstructionType_MOVRegOrMemToOrFromReg) {
|
||||||
|
op = S86_STR8("mov");
|
||||||
|
} else {
|
||||||
|
op = S86_STR8("add");
|
||||||
|
S86_ASSERT(instruction_type == S86_InstructionType_ADDRegOrMemToOrFromReg);
|
||||||
|
}
|
||||||
|
|
||||||
if (mod == 0b11) {
|
if (mod == 0b11) {
|
||||||
// NOTE: Register-to-register move
|
// NOTE: Register-to-register move
|
||||||
// =========================================================
|
// =========================================================
|
||||||
S86_Str8 src_op = REGISTER_FIELD_ENCODING[w][d ? rm : reg];
|
S86_Str8 src_op = REGISTER_FIELD_ENCODING[w][d ? rm : reg];
|
||||||
S86_Str8 dest_op = REGISTER_FIELD_ENCODING[w][d ? reg : rm];
|
S86_Str8 dest_op = REGISTER_FIELD_ENCODING[w][d ? reg : rm];
|
||||||
S86_PrintLnFmt("mov %.*s, %.*s", S86_STR8_FMT(dest_op), S86_STR8_FMT(src_op));
|
S86_PrintLnFmt("%.*s %.*s, %.*s", S86_STR8_FMT(op), S86_STR8_FMT(dest_op), S86_STR8_FMT(src_op));
|
||||||
} else {
|
} else {
|
||||||
// NOTE: Memory mode w/ effective address calculation
|
// NOTE: Memory mode w/ effective address calculation
|
||||||
// =========================================================
|
// =========================================================
|
||||||
S86_EffectiveAddressStr8 effective_address = S86_EffectiveAddressCalc(&buffer_it, rm, mod);
|
S86_EffectiveAddressStr8 effective_address = S86_EffectiveAddressCalc(&buffer_it, rm, mod, w);
|
||||||
S86_Str8 addr = { .data = effective_address.data, .size = effective_address.size };
|
S86_Str8 addr = { .data = effective_address.data, .size = effective_address.size };
|
||||||
S86_Str8 dest_op = d ? REGISTER_FIELD_ENCODING[w][reg] : addr;
|
S86_Str8 dest_op = d ? REGISTER_FIELD_ENCODING[w][reg] : addr;
|
||||||
S86_Str8 src_op = d ? addr : REGISTER_FIELD_ENCODING[w][reg];
|
S86_Str8 src_op = d ? addr : REGISTER_FIELD_ENCODING[w][reg];
|
||||||
S86_PrintLnFmt("mov %.*s, %.*s", S86_STR8_FMT(dest_op), S86_STR8_FMT(src_op));
|
S86_PrintLnFmt("%.*s %.*s, %.*s", S86_STR8_FMT(op), S86_STR8_FMT(dest_op), S86_STR8_FMT(src_op));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case S86_InstructionType_ADDImmediateToRegOrMem: /*FALLTHRU*/
|
||||||
case S86_InstructionType_MOVImmediateToRegOrMem: {
|
case S86_InstructionType_MOVImmediateToRegOrMem: {
|
||||||
S86_ASSERT(op_code_size == 2);
|
S86_ASSERT(op_code_size == 2);
|
||||||
uint8_t w = (op_code_bytes[0] & 0b0000'0001) >> 0;
|
uint8_t w = (op_code_bytes[0] & 0b0000'0001) >> 0;
|
||||||
|
uint8_t s = (op_code_bytes[0] & 0b0000'0010) >> 1;
|
||||||
uint8_t mod = (op_code_bytes[1] & 0b1100'0000) >> 6;
|
uint8_t mod = (op_code_bytes[1] & 0b1100'0000) >> 6;
|
||||||
uint8_t rm = (op_code_bytes[1] & 0b0000'0111) >> 0;
|
uint8_t rm = (op_code_bytes[1] & 0b0000'0111) >> 0;
|
||||||
S86_ASSERT(w < 2);
|
S86_ASSERT(w < 2);
|
||||||
S86_ASSERT(mod < 4);
|
S86_ASSERT(mod < 4);
|
||||||
S86_ASSERT(rm < 8);
|
S86_ASSERT(rm < 8);
|
||||||
S86_ASSERT(mod != 0b11); // NOTE: Op is IMM->Reg, register-to-register not permitted
|
|
||||||
|
|
||||||
// NOTE: Memory mode w/ effective address calculation
|
S86_EffectiveAddressStr8 effective_address = S86_EffectiveAddressCalc(&buffer_it, rm, mod, w);
|
||||||
// =========================================================
|
|
||||||
S86_EffectiveAddressStr8 effective_address = S86_EffectiveAddressCalc(&buffer_it, rm, mod);
|
|
||||||
|
|
||||||
// NOTE: Parse data payload
|
// NOTE: Parse data payload
|
||||||
// =============================================================
|
// =============================================================
|
||||||
uint16_t data = S86_BufferIteratorNextByte(&buffer_it);
|
uint16_t data = S86_BufferIteratorNextByte(&buffer_it);
|
||||||
|
bool sign_extend_8bit_data = false;
|
||||||
if (w) { // 16 bit data
|
if (w) { // 16 bit data
|
||||||
|
if (instruction_type == S86_InstructionType_ADDImmediateToRegOrMem && s) {
|
||||||
|
sign_extend_8bit_data = true;
|
||||||
|
} else {
|
||||||
uint8_t data_hi = S86_BufferIteratorNextByte(&buffer_it);
|
uint8_t data_hi = S86_BufferIteratorNextByte(&buffer_it);
|
||||||
data |= (uint16_t)(data_hi) << 8;
|
data |= (uint16_t)(data_hi) << 8;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
S86_Str8 op = {0};
|
||||||
|
if (instruction_type == S86_InstructionType_MOVImmediateToRegOrMem) {
|
||||||
|
S86_ASSERT(mod != 0b11); // NOTE: Op is IMM->Reg, register-to-register not permitted
|
||||||
|
op = S86_STR8("mov");
|
||||||
|
} else {
|
||||||
|
S86_ASSERT(instruction_type == S86_InstructionType_ADDImmediateToRegOrMem);
|
||||||
|
op = S86_STR8("add");
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Disassemble
|
// NOTE: Disassemble
|
||||||
// =========================================================
|
// =========================================================
|
||||||
S86_PrintLnFmt("mov %.*s, %s %u", effective_address.size, effective_address.data, w ? "word" : "byte", data);
|
if (instruction_type == S86_InstructionType_MOVImmediateToRegOrMem) {
|
||||||
|
S86_PrintLnFmt("%.*s %.*s, %s %u", S86_STR8_FMT(op), effective_address.size, effective_address.data, w ? "word" : "byte", data);
|
||||||
|
} else {
|
||||||
|
if (sign_extend_8bit_data) {
|
||||||
|
S86_PrintLnFmt("%.*s %.*s, %d", S86_STR8_FMT(op), effective_address.size, effective_address.data, (int16_t)data);
|
||||||
|
} else {
|
||||||
|
S86_PrintLnFmt("%.*s %.*s, %u", S86_STR8_FMT(op), effective_address.size, effective_address.data, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case S86_InstructionType_ADDImmediateToAccum: /*FALLTHRU*/
|
||||||
case S86_InstructionType_MOVImmediateToReg: {
|
case S86_InstructionType_MOVImmediateToReg: {
|
||||||
// NOTE: Parse opcode control bits
|
// NOTE: Parse opcode control bits
|
||||||
// =============================================================
|
// =============================================================
|
||||||
S86_ASSERT(op_code_size == 1);
|
S86_ASSERT(op_code_size == 1);
|
||||||
uint8_t w = (op_code_bytes[0] & 0b0000'1000) >> 3;
|
uint8_t w = 0;
|
||||||
|
if (instruction_type == S86_InstructionType_ADDImmediateToAccum) {
|
||||||
|
w = (op_code_bytes[0] & 0b0000'0001) >> 0;
|
||||||
|
} else {
|
||||||
|
w = (op_code_bytes[0] & 0b0000'1000) >> 3;
|
||||||
|
}
|
||||||
uint8_t reg = (op_code_bytes[0] & 0b0000'0111) >> 0;
|
uint8_t reg = (op_code_bytes[0] & 0b0000'0111) >> 0;
|
||||||
|
|
||||||
// NOTE: Parse data payload
|
// NOTE: Parse data payload
|
||||||
@ -507,8 +561,23 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
// NOTE: Disassemble
|
// NOTE: Disassemble
|
||||||
// =============================================================
|
// =============================================================
|
||||||
S86_Str8 dest_register = REGISTER_FIELD_ENCODING[w][reg];
|
S86_Str8 op = {0};
|
||||||
S86_PrintLnFmt("mov %.*s, %d", S86_STR8_FMT(dest_register), (int16_t)data);
|
S86_Str8 dest_register = {0};
|
||||||
|
if (instruction_type == S86_InstructionType_MOVImmediateToReg) {
|
||||||
|
op = S86_STR8("mov");
|
||||||
|
dest_register = REGISTER_FIELD_ENCODING[w][reg];
|
||||||
|
} else {
|
||||||
|
S86_ASSERT(instruction_type == S86_InstructionType_ADDImmediateToAccum);
|
||||||
|
op = S86_STR8("add");
|
||||||
|
if (w) {
|
||||||
|
dest_register = S86_STR8("ax");
|
||||||
|
} else {
|
||||||
|
data = (uint16_t)(int8_t)data; // Sign extension
|
||||||
|
dest_register = S86_STR8("al");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
S86_PrintLnFmt("%.*s %.*s, %d", S86_STR8_FMT(op), S86_STR8_FMT(dest_register), (int16_t)data);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case S86_InstructionType_MOVAccumToMem: /*FALLTHRU*/
|
case S86_InstructionType_MOVAccumToMem: /*FALLTHRU*/
|
||||||
|
BIN
project.rdbg
BIN
project.rdbg
Binary file not shown.
Loading…
Reference in New Issue
Block a user