mirror of
https://github.com/samsonjs/compiler.git
synced 2026-04-27 14:57:45 +00:00
[NEW] Encode [esp] and [ebp] as [esp+0] and [ebp+0] using SIB and disp8 respectively.
This commit is contained in:
parent
99ad11f724
commit
0fbb366e9c
2 changed files with 33 additions and 9 deletions
|
|
@ -13,7 +13,7 @@ module Assembler
|
||||||
|
|
||||||
include Registers
|
include Registers
|
||||||
|
|
||||||
DEBUG_OUTPUT = false
|
DEBUG_OUTPUT = true
|
||||||
|
|
||||||
# 0.size gives the real answer, we only do x86-32 though
|
# 0.size gives the real answer, we only do x86-32 though
|
||||||
MachineBytes = 4
|
MachineBytes = 4
|
||||||
|
|
@ -202,18 +202,36 @@ module Assembler
|
||||||
disp32 = nil
|
disp32 = nil
|
||||||
sib = nil
|
sib = nil
|
||||||
|
|
||||||
# memory location / pointer
|
# effective address
|
||||||
if addr.is_a?(Array)
|
if addr.is_a?(Array)
|
||||||
eff_addr = addr[1] || addr[0] # works with or without size prefix
|
eff_addr = addr[1] || addr[0] # works with or without size prefix
|
||||||
raise "invalid effective address: #{addr.inspect}" unless eff_addr
|
raise "invalid effective address: #{addr.inspect}" unless eff_addr
|
||||||
case eff_addr
|
case eff_addr
|
||||||
when RegisterProxy
|
when RegisterProxy
|
||||||
|
|
||||||
|
# Simple register addressing, e.g. [ESI].
|
||||||
|
#
|
||||||
# mod == 00
|
# mod == 00
|
||||||
if eff_addr.register?
|
if eff_addr.register?
|
||||||
|
mod = 0
|
||||||
|
|
||||||
# TODO check for ebp / disp32 special case and use [ebp+0]
|
# [ESP] and [EBP] can't be encoded directly. The
|
||||||
rm = eff_addr.regnum
|
# workaround is to use SIB to emit the code for [ESP+0]
|
||||||
|
# and [EBP+0] instead.
|
||||||
|
#
|
||||||
|
# To emit [ESP+0] we use SIB with scale=1 index=0 base=ESP.
|
||||||
|
if eff_addr == ESP
|
||||||
|
rm = 4 # SIB
|
||||||
|
sib = mk_sib(1, 0, eff_addr)
|
||||||
|
|
||||||
|
# For [EBP+0] we can encode [EBP]+disp8 directly.
|
||||||
|
elsif eff_addr == EBP
|
||||||
|
mod = 1
|
||||||
|
rm = eff_addr.regnum
|
||||||
|
disp8 = 0
|
||||||
|
else
|
||||||
|
rm = eff_addr.regnum
|
||||||
|
end
|
||||||
|
|
||||||
elsif eff_addr.index? && eff_addr.index.is_a?(Numeric)
|
elsif eff_addr.index? && eff_addr.index.is_a?(Numeric)
|
||||||
|
|
||||||
|
|
@ -241,8 +259,9 @@ module Assembler
|
||||||
raise "unsupported effective address: #{addr.inspect}"
|
raise "unsupported effective address: #{addr.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# disp32, mod == 0
|
# disp32, mod == 00
|
||||||
when Numeric
|
when Numeric
|
||||||
|
mod = 0
|
||||||
rm = 5 # 101
|
rm = 5 # 101
|
||||||
disp32 = eff_addr
|
disp32 = eff_addr
|
||||||
|
|
||||||
|
|
@ -270,9 +289,15 @@ module Assembler
|
||||||
if [1,2,4,8].include?(scale)
|
if [1,2,4,8].include?(scale)
|
||||||
scale = log2(scale).to_i
|
scale = log2(scale).to_i
|
||||||
else
|
else
|
||||||
raise "unsupported SIB scale: #{scale}, should be [1, 2, 4, 8]"
|
raise "unsupported SIB scale: #{scale}, should be 1, 2, 4, or 8"
|
||||||
end
|
end
|
||||||
(scale << 6) | (index.regnum << 3) | base.regnum
|
if index == 0
|
||||||
|
index = 4
|
||||||
|
elsif index.respond_to?(:regnum)
|
||||||
|
index = index.regnum
|
||||||
|
end
|
||||||
|
base = base.regnum if base.respond_to?(:regnum)
|
||||||
|
return (scale << 6) | (index << 3) | base
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -512,8 +512,7 @@ class Compiler
|
||||||
boolean_expression # final value
|
boolean_expression # final value
|
||||||
skip_any_whitespace
|
skip_any_whitespace
|
||||||
asm.push(EAX) # stash final value on stack
|
asm.push(EAX) # stash final value on stack
|
||||||
asm.mov(EDX, ESP)
|
final = [ESP]
|
||||||
final = [EDX]
|
|
||||||
|
|
||||||
simple_loop('for') do |end_label|
|
simple_loop('for') do |end_label|
|
||||||
asm.mov(ECX, [asm.var(counter)]) # get the counter
|
asm.mov(ECX, [asm.var(counter)]) # get the counter
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue