Implemented bit shifts
This commit is contained in:
parent
d1a8f0d66c
commit
f0bc5039ee
@ -152,10 +152,10 @@ This is what generates expressions from tokens.
|
|||||||
- [x] `+=`, `-=`, `*=`, `/=`, `%=`
|
- [x] `+=`, `-=`, `*=`, `/=`, `%=`
|
||||||
- [x] `&`, `|`, `^`
|
- [x] `&`, `|`, `^`
|
||||||
- [x] `&=`, `|=`, `^=`
|
- [x] `&=`, `|=`, `^=`
|
||||||
|
- [x] `<<`, `>>`
|
||||||
|
- [x] `<<=`, `>>=`
|
||||||
- [x] `==`, `!=`, `<`, `<=`, `>`, `>=`
|
- [x] `==`, `!=`, `<`, `<=`, `>`, `>=`
|
||||||
- [x] `&&`, `||`
|
- [x] `&&`, `||`
|
||||||
- [ ] `<<`, `>>`
|
|
||||||
- [ ] `<<=`, `>>=`
|
|
||||||
|
|
||||||
### Architecture
|
### Architecture
|
||||||
|
|
||||||
|
17
src/build/arch/x64/Shift.go
Normal file
17
src/build/arch/x64/Shift.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package x64
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.akyoto.dev/cli/q/src/build/cpu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ShiftLeftNumber shifts the register value by `bitCount` bits to the left.
|
||||||
|
func ShiftLeftNumber(code []byte, register cpu.Register, bitCount byte) []byte {
|
||||||
|
code = encode(code, AddressDirect, 0b100, register, 8, 0xC1)
|
||||||
|
return append(code, bitCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShiftRightSignedNumber shifts the signed register value by `bitCount` bits to the right.
|
||||||
|
func ShiftRightSignedNumber(code []byte, register cpu.Register, bitCount byte) []byte {
|
||||||
|
code = encode(code, AddressDirect, 0b111, register, 8, 0xC1)
|
||||||
|
return append(code, bitCount)
|
||||||
|
}
|
@ -184,6 +184,18 @@ func (a Assembler) Finalize() ([]byte, []byte) {
|
|||||||
case RETURN:
|
case RETURN:
|
||||||
code = x64.Return(code)
|
code = x64.Return(code)
|
||||||
|
|
||||||
|
case SHIFTL:
|
||||||
|
switch operands := x.Data.(type) {
|
||||||
|
case *RegisterNumber:
|
||||||
|
code = x64.ShiftLeftNumber(code, operands.Register, byte(operands.Number)&0b111111)
|
||||||
|
}
|
||||||
|
|
||||||
|
case SHIFTRS:
|
||||||
|
switch operands := x.Data.(type) {
|
||||||
|
case *RegisterNumber:
|
||||||
|
code = x64.ShiftRightSignedNumber(code, operands.Register, byte(operands.Number)&0b111111)
|
||||||
|
}
|
||||||
|
|
||||||
case STORE:
|
case STORE:
|
||||||
switch operands := x.Data.(type) {
|
switch operands := x.Data.(type) {
|
||||||
case *MemoryNumber:
|
case *MemoryNumber:
|
||||||
|
@ -26,6 +26,8 @@ const (
|
|||||||
POP
|
POP
|
||||||
PUSH
|
PUSH
|
||||||
RETURN
|
RETURN
|
||||||
|
SHIFTL
|
||||||
|
SHIFTRS
|
||||||
STORE
|
STORE
|
||||||
SUB
|
SUB
|
||||||
SYSCALL
|
SYSCALL
|
||||||
@ -79,6 +81,10 @@ func (m Mnemonic) String() string {
|
|||||||
return "push"
|
return "push"
|
||||||
case RETURN:
|
case RETURN:
|
||||||
return "return"
|
return "return"
|
||||||
|
case SHIFTL:
|
||||||
|
return "shift l"
|
||||||
|
case SHIFTRS:
|
||||||
|
return "shift rs"
|
||||||
case SUB:
|
case SUB:
|
||||||
return "sub"
|
return "sub"
|
||||||
case STORE:
|
case STORE:
|
||||||
|
@ -34,6 +34,12 @@ func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Reg
|
|||||||
case token.Xor, token.XorAssign:
|
case token.Xor, token.XorAssign:
|
||||||
f.RegisterNumber(asm.XOR, register, number)
|
f.RegisterNumber(asm.XOR, register, number)
|
||||||
|
|
||||||
|
case token.Shl, token.ShlAssign:
|
||||||
|
f.RegisterNumber(asm.SHIFTL, register, number)
|
||||||
|
|
||||||
|
case token.Shr, token.ShrAssign:
|
||||||
|
f.RegisterNumber(asm.SHIFTRS, register, number)
|
||||||
|
|
||||||
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
|
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
|
||||||
f.RegisterNumber(asm.COMPARE, register, number)
|
f.RegisterNumber(asm.COMPARE, register, number)
|
||||||
|
|
||||||
|
57
tests/programs/shift.q
Normal file
57
tests/programs/shift.q
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
main() {
|
||||||
|
if 0 << 0 != 0 {
|
||||||
|
sys.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 >> 0 != 0 {
|
||||||
|
sys.exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 << 0 != 1 {
|
||||||
|
sys.exit(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 >> 0 != 1 {
|
||||||
|
sys.exit(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 >> 1 != 0 {
|
||||||
|
sys.exit(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 << 1 != 2 {
|
||||||
|
sys.exit(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 << 2 != 4 {
|
||||||
|
sys.exit(7)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 << 3 != 8 {
|
||||||
|
sys.exit(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 1 << 4 != 16 {
|
||||||
|
sys.exit(9)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 16 >> 1 != 8 {
|
||||||
|
sys.exit(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 16 >> 2 != 4 {
|
||||||
|
sys.exit(11)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 16 >> 3 != 2 {
|
||||||
|
sys.exit(12)
|
||||||
|
}
|
||||||
|
|
||||||
|
if 16 >> 4 != 1 {
|
||||||
|
sys.exit(13)
|
||||||
|
}
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
}
|
@ -35,6 +35,7 @@ var programs = []struct {
|
|||||||
{"bitwise-and", "", "", 0},
|
{"bitwise-and", "", "", 0},
|
||||||
{"bitwise-or", "", "", 0},
|
{"bitwise-or", "", "", 0},
|
||||||
{"bitwise-xor", "", "", 0},
|
{"bitwise-xor", "", "", 0},
|
||||||
|
{"shift", "", "", 0},
|
||||||
{"remainder", "", "", 0},
|
{"remainder", "", "", 0},
|
||||||
{"jump-near", "", "", 0},
|
{"jump-near", "", "", 0},
|
||||||
{"loop", "", "", 0},
|
{"loop", "", "", 0},
|
||||||
|
Loading…
Reference in New Issue
Block a user