Added README, licenses and copyright notices.
"{ Package: 'jv:dragonfly/asm' }"
"{ NameSpace: Smalltalk }"
TestCase subclass:#AJx86AssemblerTests
instanceVariableNames:'asm'
classVariableNames:''
poolDictionaries:'AJx86Registers'
category:'AsmJit-Tests'
!
!AJx86AssemblerTests methodsFor:'running'!
setUp
super setUp.
asm := self newAssembler.
! !
!AJx86AssemblerTests methodsFor:'tests'!
testAssembly1
asm
push: EBP;
mov: ESP -> EBP;
mov: 1024 -> EAX;
mov: EBP -> ESP;
pop: EBP;
ret.
self assert: asm bytes = #(85 139 236 184 0 4 0 0 139 229 93 195) asByteArray
!
testAssembly3
" instructions without operands.
(AJInstructionDescription instructions select: [:each | each group = #emit]) keys asSortedCollection
"
| str |
str :=
#(
#cbw 16r66 16r98
#cdq 16r99
"#cdqe 64 bit "
#clc 16rF8
#cld 16rFC
#cmc 16rF5
#cpuid 16r0F 16rA2
"#cqo 64 bit "
#cwd 16r66 16r99
#cwde 16r98
#daa 16r27
#das 16r2F
#emms 16r0F 16r77
#f2xm1 16rD9 16rF0
#fabs 16rD9 16rE1
#fchs 16rD9 16rE0
#fclex 16r9B 16rDB 16rE2
#fcompp 16rDE 16rD9
#fcos 16rD9 16rFF
#fdecstp 16rD9 16rF6
#fincstp 16rD9 16rF7
#finit 16r9B 16rDB 16rE3
#fld1 16rD9 16rE8
#fldl2e 16rD9 16rEA
#fldl2t 16rD9 16rE9
#fldlg2 16rD9 16rEC
#fldln2 16rD9 16rED
#fldpi 16rD9 16rEB
#fldz 16rD9 16rEE
#fnclex 16rDB 16rE2
#fninit 16rDB 16rE3
#fnop 16rD9 16rD0
#fpatan 16rD9 16rF3
#fprem 16rD9 16rF8
#fprem1 16rD9 16rF5
#fptan 16rD9 16rF2
#frndint 16rD9 16rFC
#fscale 16rD9 16rFD
#fsin 16rD9 16rFE
#fsincos 16rD9 16rFB
#fsqrt 16rD9 16rFA
#ftst 16rD9 16rE4
#fucompp 16rDA 16rE9
#fwait 16r9B
#fxam 16rD9 16rE5
#fxtract 16rD9 16rF4
#fyl2x 16rD9 16rF1
#fyl2xp1 16rD9 16rF9
#int3 16rCC
#leave 16rC9
#lfence 16r0F 16rAE 16rE8
#lock 16rF0 "prefix"
#mfence 16r0F 16rAE 16rF0
#monitor 16r0F 16r01 16rC8
#mwait 16r0F 16r01 16rC9
#nop 16r90
#pause 16rF3 16r90
#popad 16r61
#popfd 16r9D
" #popfq 16r48 16r9D - 64 bit "
#pushad 16r60
#pushf 16r66 16r9C
#pushfd 16r9C
" #pushfq -64 bit"
#rdtsc 16r0F 16r31
#rdtscp 16r0F 16r01 16rF9
#sahf 16r9E
#sfence 16r0F 16rAE 16rF8
#stc 16rF9
#std 16rFD
#ud2 16r0F 16r0B
#std 16rFD "dummy"
) readStream.
[ str atEnd ] whileFalse: [
| instr tst |
instr := str next.
tst := OrderedCollection new.
[ str peek isInteger ] whileTrue: [ tst add: str next ].
asm reset noStackFrame.
asm perform: instr.
self assert: (asm bytes = tst asByteArray )
].
!
testAssemblyImmAddr
"test generating immediate address,
note GDB disassembling it to:
0x1fab <instructions.1862>: 0x8b 0x05 0xef 0xbe 0xad 0xde
0x00001fab <instructions.1862+0>: mov 0xdeadbeef,%eax
which is WRONG!!
"
asm
mov: 16rdeadbeef asUImm ptr32 to: asm EAX.
" 8b05efbeadde mov eax, [deadbeef] "
self assert: asm bytes = #[139 5 239 190 173 222]
!
testAssemblyMemBase
asm
mov: EAX ptr -> EAX;
mov: ESP ptr -> EAX;
mov: EBP ptr -> EAX.
self assert: asm bytes = #(16r8B 0 16r8B 16r04 16r24 16r8B 16r45 16r00) asByteArray
!
testAssemblyMemBaseDisp
asm
mov: EAX ptr + 1 -> EAX;
mov: EBX ptr + ECX -> EAX.
self assert: asm bytes = #(16r8B 16r40 16r01 16r8B 16r04 16r0B) asByteArray
!
testAssemblyMemBaseDisp2
asm
mov: EAX ptr - 1 -> EAX;
mov: EBX ptr + ECX * 2 - 5 -> EAX.
self assert: asm bytes = #(16r8B 16r40 16rFF 16r8B 16r44 16r4B 16rFB) asByteArray
!
testAssemblyMemBytes
asm
mov: ((ESI ptr + ECX) size: 1) -> BL;
mov: BL -> ((ESI ptr + ECX) size:1).
self assert: asm bytes = #(16r8A 16r1C 16r0E 16r88 16r1C 16r0E ) asByteArray
!
testBitTest
asm
bt: EAX with: 0.
self assert: asm bytes = #(16r0F 16rBA 16rE0 16r00) asByteArray
!
testCall
asm
call: EAX;
call: EAX ptr - 4;
call: EAX ptr.
self assert: asm bytes = #(255 208 255 80 252 255 16) asByteArray
!
testForwardJumps
asm
jmp: #label1;
label: #label1.
self assert: asm bytes = #(16rEB 0 ) asByteArray.
!
testImmLabels
"test immediates with labels"
| code pos |
asm
mov: EAX ptr -> EAX;
mov: (16rFFFFFFFF asUImm label: (asm labelNamed: #foo) ) to: EAX.
code := asm generatedCode.
pos := code offsetAt: #foo.
self assert: (code bytes at: pos+1) = 255.
self assert: (code bytes at: pos+2) = 255.
self assert: (code bytes at: pos+3) = 255.
self assert: (code bytes at: pos+4) = 255.
!
testJMPRegister
self
assert: [ :assembler |
assembler jmp: assembler EAX ]
bytes: #[ 16rFF 2r11100000 ].
self
assert: [ :assembler |
assembler jmp: assembler ECX ]
bytes: #[ 16rFF 2r11100001 ].
self
assert: [ :assembler |
assembler jmp: assembler EDX ]
bytes: #[ 16rFF 2r11100010 ]
!
testJumps
asm
label: #label1;
nop;
nop;
nop;
jz: #label1.
self assert: asm bytes = #(144 144 144 116 251) asByteArray.
asm
reset; noStackFrame;
label: #label1.
126 timesRepeat: [ asm nop ].
asm jz: #label1.
self assert: (asm bytes size = 128).
asm
reset; noStackFrame;
label: #label1;
nop;
nop;
nop;
jmp: #label1.
self assert: asm bytes = #(144 144 144 235 251) asByteArray.
asm
reset; noStackFrame;
jmp: #label1;
label: #label1.
self assert: asm bytes = #(16rEB 0 ) asByteArray.
!
testMovSxZx
asm
movsx: asm AX to: asm EAX;
movzx: asm AX to: asm EAX;
movsx: asm AL to: asm EAX;
movzx: asm AH to: asm EAX.
self assert: asm bytes =
#[
16r0F 16rBF 16rC0
16r0F 16rB7 16rC0
16r0F 16rBE 16rC0
16r0F 16rB6 16rC4 ]
!
testSyscall
"Syscall instruction is only valid in 64-bit mode"
self asmShould: [ :a | a syscall ] raise: Error
!
testTest
"Special RAX opcodes"
"8bit operand opcode"
asm
test: AL with: 5.
self assert: asm bytes = #[16rA8 05].
asm reset;
test: AX with: 5.
"16bit operand Prefix byte, 16bit immediate (LSB)"
self assert: asm bytes = #[16r66 16rA9 05 0].
"32bit operand "
asm reset;
test: EAX with: 1.
self assert: asm bytes = #[16rA9 01 00 00 00].
"Need more assert for non-EAX receiver, non-immediate operands"
!
tstRegistersOf: asm
| numRegs |
numRegs := asm numGPRegisters.
0 to: numRegs-1 do: [:i |
self assert: (asm reg8: i) size = 1.
self assert: (asm reg8: i) index = i.
self assert: (asm reg16: i) size = 2.
self assert: (asm reg16: i) index = i.
self assert: (asm reg32: i) size = 4.
self assert: (asm reg32: i) index = i.
self assert: (asm isGPNRegister: (asm nReg: i)).
asm is64BitMode ifTrue: [
self assert: (asm reg64: i) size = 8.
self assert: (asm reg64: i) index = i.
]
].
"Created: / 15-12-2015 / 23:59:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AJx86AssemblerTests methodsFor:'tests-FPU'!
testFXCH
self
assert: [ :a|
a fxch "the same as: asm fxch: asm ST1" ]
bytes: #[ 2r11011001 2r11001001 ]
!
testFXCHST1
self
assert: [ :a| a fxch: asm ST1 ]
bytes: #[ 2r11011001 2r11001001 ]
! !
!AJx86AssemblerTests methodsFor:'tests-data'!
setUpDataBytes
^ self setUpDataBytesAlign: 1
!
setUpDataBytesAlign: alignToBytes
asm nop.
asm align: alignToBytes.
^ asm db: 16r12.
!
testDataBytes
|data|
data := self setUpDataBytes.
self assert: asm bytes equals: #[144 16r12].
!
testDataBytesAlignDouble
|data|
data := self setUpDataBytesAlign: 4.
self assert: asm bytes equals: #[144 0 0 0 16r12].
!
testDataBytesAlignQuad
|data|
data := self setUpDataBytesAlign: 8.
self assert: asm bytes equals: #[144 0 0 0 0 0 0 0 16r12].
!
testDataBytesAlignWord
|data|
data := self setUpDataBytesAlign: 2.
self assert: asm bytes equals: #[144 0 16r12].
!
testDataDouble
| data|
asm nop.
data := asm dd: #[16r78 16r56 16r34 16r12].
self assert: asm bytes equals: #[144 16r78 16r56 16r34 16r12].
!
testDataWord
| data|
asm nop.
data := asm dw: #[16r34 16r12].
self assert: asm bytes equals: #[144 16r34 16r12].
! !
!AJx86AssemblerTests methodsFor:'utility'!
asmShould: aBlock raise: anError
self should: [self bytes: aBlock] raise: anError.
!
assert: aBlock bytes: aByteArray
self assert: (self bytes: aBlock) equals: aByteArray .
!
bytes: aBlock
asm := self newAssembler.
aBlock value: asm.
^ asm bytes
!
newAssembler
^ AJx86Assembler new
noStackFrame;
yourself
! !