fixed prefix -- parsing; codegen for unary + - ~ !
This commit is contained in:
parent
017a70ee7e
commit
b13e16b517
5 changed files with 307 additions and 90 deletions
367
05/codegen.b
367
05/codegen.b
|
@ -80,13 +80,23 @@ function emit_mov_reg
|
||||||
|
|
||||||
function emit_mov_rax_imm64
|
function emit_mov_rax_imm64
|
||||||
argument imm64
|
argument imm64
|
||||||
|
if imm64 == 0 goto rax_imm64_0
|
||||||
; 48 b8 IMM64
|
; 48 b8 IMM64
|
||||||
*2code_output = 0xb848
|
*2code_output = 0xb848
|
||||||
code_output += 2
|
code_output += 2
|
||||||
*8code_output = imm64
|
*8code_output = imm64
|
||||||
code_output += 8
|
code_output += 8
|
||||||
return
|
return
|
||||||
|
:rax_imm64_0
|
||||||
|
emit_zero_rax()
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_zero_rax
|
||||||
|
; 31 c0
|
||||||
|
*2code_output = 0xc031
|
||||||
|
code_output += 2
|
||||||
|
return
|
||||||
|
|
||||||
function emit_movsx_rax_al
|
function emit_movsx_rax_al
|
||||||
; 48 0f be c0
|
; 48 0f be c0
|
||||||
*4code_output = 0xc0be0f48
|
*4code_output = 0xc0be0f48
|
||||||
|
@ -143,6 +153,13 @@ function emit_mov_rax_qword_rsp_plus_imm32
|
||||||
code_output += 4
|
code_output += 4
|
||||||
return
|
return
|
||||||
|
|
||||||
|
function emit_mov_rax_qword_rsp
|
||||||
|
emit_mov_rax_qword_rsp_plus_imm32(0)
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_mov_qword_rsp_rax
|
||||||
|
emit_mov_qword_rsp_plus_imm32_rax(0)
|
||||||
|
return
|
||||||
|
|
||||||
function emit_sub_rsp_imm32
|
function emit_sub_rsp_imm32
|
||||||
argument imm32
|
argument imm32
|
||||||
|
@ -224,28 +241,28 @@ function emit_movsq
|
||||||
code_output += 2
|
code_output += 2
|
||||||
return
|
return
|
||||||
|
|
||||||
function emit_movss_xmm0_dword_rax
|
function emit_movq_rax_xmm0
|
||||||
; f3 0f 10 00
|
; 66 48 0f 7e c0
|
||||||
*4code_output = 0x00100ff3
|
*4code_output = 0x7e0f4866
|
||||||
code_output += 4
|
code_output += 4
|
||||||
|
*1code_output = 0xc0
|
||||||
|
code_output += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
function emit_movsd_xmm0_qword_rax
|
function emit_movq_xmm0_rax
|
||||||
; f2 0f 10 00
|
; 66 48 0f 6e c0
|
||||||
*4code_output = 0x00100ff2
|
*4code_output = 0x6e0f4866
|
||||||
code_output += 4
|
code_output += 4
|
||||||
|
*1code_output = 0xc0
|
||||||
|
code_output += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
function emit_movss_dword_rax_xmm0
|
function emit_movq_xmm1_rax
|
||||||
; f3 0f 11 00
|
; 66 48 0f 6e c8
|
||||||
*4code_output = 0x00110ff3
|
*4code_output = 0x6e0f4866
|
||||||
code_output += 4
|
|
||||||
return
|
|
||||||
|
|
||||||
function emit_movsd_qword_rax_xmm0
|
|
||||||
; f2 0f 11 00
|
|
||||||
*4code_output = 0x00110ff2
|
|
||||||
code_output += 4
|
code_output += 4
|
||||||
|
*1code_output = 0xc8
|
||||||
|
code_output += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
function emit_cvtss2sd_xmm0_xmm0
|
function emit_cvtss2sd_xmm0_xmm0
|
||||||
|
@ -277,6 +294,143 @@ function emit_cvtsi2sd_xmm0_rax
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
function emit_neg_rax
|
||||||
|
; 48 f7 d8
|
||||||
|
*2code_output = 0xf748
|
||||||
|
code_output += 2
|
||||||
|
*1code_output = 0xd8
|
||||||
|
code_output += 1
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_not_rax
|
||||||
|
; 48 f7 d0
|
||||||
|
*2code_output = 0xf748
|
||||||
|
code_output += 2
|
||||||
|
*1code_output = 0xd0
|
||||||
|
code_output += 1
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_xor_rax_rbx
|
||||||
|
; 48 31 d8
|
||||||
|
*2code_output = 0x3148
|
||||||
|
code_output += 2
|
||||||
|
*1code_output = 0xd8
|
||||||
|
code_output += 1
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_test_rax_rax
|
||||||
|
; 48 85 c0
|
||||||
|
*2code_output = 0x8548
|
||||||
|
code_output += 2
|
||||||
|
*1code_output = 0xc0
|
||||||
|
code_output += 1
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jmp_rel32
|
||||||
|
; e9 REL32
|
||||||
|
argument rel32
|
||||||
|
*1code_output = 0xe9
|
||||||
|
code_output += 1
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_je_rel32
|
||||||
|
; 0f 84 REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x840f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jne_rel32
|
||||||
|
; 0f 85 REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x850f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jl_rel32
|
||||||
|
; 0f 8c REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x8c0f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jg_rel32
|
||||||
|
; 0f 8f REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x8f0f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jle_rel32
|
||||||
|
; 0f 8e REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x8e0f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jge_rel32
|
||||||
|
; 0f 8d REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x8d0f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jb_rel32
|
||||||
|
; 0f 82 REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x820f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_ja_rel32
|
||||||
|
; 0f 87 REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x870f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jbe_rel32
|
||||||
|
; 0f 86 REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x860f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_jae_rel32
|
||||||
|
; 0f 83 REL32
|
||||||
|
argument rel32
|
||||||
|
*2code_output = 0x830f
|
||||||
|
code_output += 2
|
||||||
|
*4code_output = rel32
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
|
function emit_comisd_xmm0_xmm1
|
||||||
|
; 66 0f 2f c1
|
||||||
|
*4code_output = 0xc12f0f66
|
||||||
|
code_output += 4
|
||||||
|
return
|
||||||
|
|
||||||
; make sure you put the return value in the proper place before calling this
|
; make sure you put the return value in the proper place before calling this
|
||||||
function generate_return
|
function generate_return
|
||||||
emit_mov_reg(REG_RSP, REG_RBP)
|
emit_mov_reg(REG_RSP, REG_RBP)
|
||||||
|
@ -350,10 +504,10 @@ function generate_cast_top_of_stack
|
||||||
c = type_sizeof(*1from)
|
c = type_sizeof(*1from)
|
||||||
d = type_sizeof(*1to)
|
d = type_sizeof(*1to)
|
||||||
if d > c goto return_0 ; casting to bigger type, so we're good
|
if d > c goto return_0 ; casting to bigger type, so we're good
|
||||||
if c == 8 goto return_0 ; casting from unsigned/signed long to unsigned/signed long, we're good
|
if d == 8 goto return_0 ; casting from unsigned/signed long to unsigned/signed long, we're good
|
||||||
|
|
||||||
; mov rax, [rsp]
|
; mov rax, [rsp]
|
||||||
emit_mov_rax_qword_rsp_plus_imm32(0)
|
emit_mov_rax_qword_rsp()
|
||||||
|
|
||||||
; now sign/zero extend the lower part of rax to the whole of rax
|
; now sign/zero extend the lower part of rax to the whole of rax
|
||||||
if *1to == TYPE_CHAR goto gen_cast_integer_to_signed_char
|
if *1to == TYPE_CHAR goto gen_cast_integer_to_signed_char
|
||||||
|
@ -367,7 +521,7 @@ function generate_cast_top_of_stack
|
||||||
|
|
||||||
:int2int_cast_cont
|
:int2int_cast_cont
|
||||||
; mov [rsp], rax
|
; mov [rsp], rax
|
||||||
emit_mov_qword_rsp_plus_imm32_rax(0)
|
emit_mov_qword_rsp_rax()
|
||||||
return
|
return
|
||||||
|
|
||||||
:gen_cast_integer_to_signed_char
|
:gen_cast_integer_to_signed_char
|
||||||
|
@ -397,71 +551,75 @@ function generate_cast_top_of_stack
|
||||||
if *8from != *8to goto bad_gen_cast
|
if *8from != *8to goto bad_gen_cast
|
||||||
return ; no casting needed; these are the same type
|
return ; no casting needed; these are the same type
|
||||||
:gen_cast_double_to_float
|
:gen_cast_double_to_float
|
||||||
; mov rax, rsp
|
; mov rax, [rsp]
|
||||||
emit_mov_reg(REG_RAX, REG_RSP)
|
emit_mov_rax_qword_rsp()
|
||||||
; movsd xmm0, [rax]
|
; movq xmm0, rax
|
||||||
emit_movsd_xmm0_qword_rax()
|
emit_movq_xmm0_rax()
|
||||||
; cvtsd2ss xmm0, xmm0
|
; cvtsd2ss xmm0, xmm0
|
||||||
emit_cvtsd2ss_xmm0_xmm0()
|
emit_cvtsd2ss_xmm0_xmm0()
|
||||||
; movsd [rax], xmm0
|
; movq rax, xmm0
|
||||||
emit_movsd_qword_rax_xmm0()
|
emit_movq_rax_xmm0()
|
||||||
|
; mov [rsp], rax
|
||||||
|
emit_mov_qword_rsp_rax()
|
||||||
return
|
return
|
||||||
:gen_cast_float_to_double
|
:gen_cast_float_to_double
|
||||||
; mov rax, rsp
|
; mov rax, [rsp]
|
||||||
emit_mov_reg(REG_RAX, REG_RSP)
|
emit_mov_rax_qword_rsp()
|
||||||
; movss xmm0, [rax]
|
; movq xmm0, rax
|
||||||
emit_movss_xmm0_dword_rax()
|
emit_movq_xmm0_rax()
|
||||||
; cvtss2sd xmm0, xmm0
|
; cvtss2sd xmm0, xmm0
|
||||||
emit_cvtss2sd_xmm0_xmm0()
|
emit_cvtss2sd_xmm0_xmm0()
|
||||||
; movss [rax], xmm0
|
; movq rax, xmm0
|
||||||
emit_movss_dword_rax_xmm0()
|
emit_movq_rax_xmm0()
|
||||||
|
; mov [rsp], rax
|
||||||
|
emit_mov_qword_rsp_rax()
|
||||||
return
|
return
|
||||||
:gen_cast_int_to_float
|
:gen_cast_int_to_float
|
||||||
; to reduce # of instructions, we first convert int to double, then double to float
|
; to reduce # of instructions, we first convert int to double, then double to float
|
||||||
; mov rax, [rsp]
|
; mov rax, [rsp]
|
||||||
emit_mov_rax_qword_rsp_plus_imm32(0)
|
emit_mov_rax_qword_rsp()
|
||||||
; cvtsi2sd xmm0, rax
|
; cvtsi2sd xmm0, rax
|
||||||
emit_cvtsi2sd_xmm0_rax()
|
emit_cvtsi2sd_xmm0_rax()
|
||||||
; cvtsd2ss xmm0, xmm0
|
; cvtsd2ss xmm0, xmm0
|
||||||
emit_cvtsd2ss_xmm0_xmm0()
|
emit_cvtsd2ss_xmm0_xmm0()
|
||||||
; mov rax, rsp
|
; movq rax, xmm0
|
||||||
emit_mov_reg(REG_RAX, REG_RSP)
|
emit_movq_rax_xmm0()
|
||||||
; movss [rax], xmm0
|
; mov [rsp], rax
|
||||||
emit_movss_dword_rax_xmm0()
|
emit_mov_qword_rsp_rax()
|
||||||
; it shouldn't matter that there's junk at [rsp+4]
|
; it shouldn't matter that there's junk at [rsp+4]
|
||||||
return
|
return
|
||||||
:gen_cast_int_to_double
|
:gen_cast_int_to_double
|
||||||
; mov rax, [rsp]
|
; mov rax, [rsp]
|
||||||
emit_mov_rax_qword_rsp_plus_imm32(0)
|
emit_mov_rax_qword_rsp()
|
||||||
; cvtsi2sd xmm0, rax
|
; cvtsi2sd xmm0, rax
|
||||||
emit_cvtsi2sd_xmm0_rax()
|
emit_cvtsi2sd_xmm0_rax()
|
||||||
; mov rax, rsp
|
; movq rax, xmm0
|
||||||
emit_mov_reg(REG_RAX, REG_RSP)
|
emit_movq_rax_xmm0()
|
||||||
; movsd [rax], xmm0
|
; mov [rsp], rax
|
||||||
emit_movsd_qword_rax_xmm0()
|
emit_mov_qword_rsp_rax()
|
||||||
return
|
return
|
||||||
:gen_cast_float_to_int
|
:gen_cast_float_to_int
|
||||||
; mov rax, rsp
|
; mov rax, [rsp]
|
||||||
emit_mov_reg(REG_RAX, REG_RSP)
|
emit_mov_rax_qword_rsp()
|
||||||
; movss xmm0, [rax]
|
; movq xmm0, rax
|
||||||
emit_movss_xmm0_dword_rax()
|
emit_movq_xmm0_rax()
|
||||||
; convert float to double, then double to int
|
; convert float to double, then double to int
|
||||||
; cvtss2sd xmm0, xmm0
|
; cvtss2sd xmm0, xmm0
|
||||||
emit_cvtss2sd_xmm0_xmm0()
|
emit_cvtss2sd_xmm0_xmm0()
|
||||||
; cvttsd2si rax, xmm0
|
; cvttsd2si rax, xmm0
|
||||||
emit_cvttsd2si_rax_xmm0()
|
emit_cvttsd2si_rax_xmm0()
|
||||||
; mov [rsp], rax
|
; mov [rsp], rax
|
||||||
emit_mov_qword_rsp_plus_imm32_rax(0)
|
emit_mov_qword_rsp_rax()
|
||||||
return
|
return
|
||||||
:gen_cast_double_to_int
|
:gen_cast_double_to_int
|
||||||
; mov rax, rsp
|
; mov rax, [rsp]
|
||||||
emit_mov_reg(REG_RAX, REG_RSP)
|
emit_mov_rax_qword_rsp()
|
||||||
; movsd xmm0, [rax]
|
; movq xmm0, rax
|
||||||
emit_movsd_xmm0_qword_rax()
|
emit_movq_xmm0_rax()
|
||||||
; cvttsd2si rax, xmm0
|
; cvttsd2si rax, xmm0
|
||||||
emit_cvttsd2si_rax_xmm0()
|
emit_cvttsd2si_rax_xmm0()
|
||||||
; mov [rsp], rax
|
; mov [rsp], rax
|
||||||
emit_mov_qword_rsp_plus_imm32_rax(0)
|
emit_mov_qword_rsp_rax()
|
||||||
return
|
return
|
||||||
|
|
||||||
:bad_gen_cast
|
:bad_gen_cast
|
||||||
|
@ -480,43 +638,120 @@ function generate_cast_top_of_stack
|
||||||
string to type
|
string to type
|
||||||
byte 32
|
byte 32
|
||||||
byte 0
|
byte 0
|
||||||
|
|
||||||
|
; push expr, casted to to_type, onto the stack
|
||||||
|
; returns pointer to end of expr
|
||||||
|
function generate_push_expression_casted
|
||||||
|
argument statement
|
||||||
|
argument expr
|
||||||
|
argument to_type
|
||||||
|
|
||||||
|
local from_type
|
||||||
|
|
||||||
|
from_type = expr + 4
|
||||||
|
from_type = *4from_type
|
||||||
|
|
||||||
|
|
||||||
|
expr = generate_push_expression(statement, expr)
|
||||||
|
generate_cast_top_of_stack(statement, from_type, to_type)
|
||||||
|
return expr
|
||||||
|
|
||||||
; `statement` is used for errors
|
; `statement` is used for errors
|
||||||
; returns pointer to end of expression
|
; returns pointer to end of expression
|
||||||
function generate_push_expression
|
function generate_push_expression
|
||||||
argument statement
|
argument statement
|
||||||
argument expr
|
argument expr
|
||||||
local b
|
|
||||||
local c
|
local c
|
||||||
|
local p
|
||||||
local type
|
local type
|
||||||
type = expr + 4
|
type = expr + 4
|
||||||
type = *4type
|
type = *4type
|
||||||
|
|
||||||
c = *1expr
|
c = *1expr
|
||||||
if c == EXPRESSION_CONSTANT_INT goto generate_push_int
|
if c == EXPRESSION_CONSTANT_INT goto generate_int
|
||||||
if c == EXPRESSION_CONSTANT_FLOAT goto generate_push_float
|
if c == EXPRESSION_CONSTANT_FLOAT goto generate_float
|
||||||
if c == EXPRESSION_CAST goto generate_cast
|
if c == EXPRESSION_CAST goto generate_cast
|
||||||
|
if c == EXPRESSION_UNARY_PLUS goto generate_cast ; the unary plus operator just casts to the promoted type
|
||||||
|
if c == EXPRESSION_UNARY_MINUS goto generate_unary_minus
|
||||||
|
if c == EXPRESSION_BITWISE_NOT goto generate_unary_bitwise_not
|
||||||
|
if c == EXPRESSION_LOGICAL_NOT goto generate_unary_logical_not
|
||||||
|
|
||||||
die(.str_genpushexprNI)
|
die(.str_genpushexprNI)
|
||||||
:str_genpushexprNI
|
:str_genpushexprNI
|
||||||
string generate_push_expression not implemented.
|
string generate_push_expression not implemented.
|
||||||
byte 0
|
byte 0
|
||||||
:generate_cast
|
:generate_cast
|
||||||
expr += 4
|
|
||||||
c = *4expr ; cast type
|
|
||||||
expr += 8
|
expr += 8
|
||||||
b = *4expr ; original type
|
expr = generate_push_expression_casted(statement, expr, type)
|
||||||
expr -= 4
|
|
||||||
expr = generate_push_expression(statement, expr)
|
|
||||||
generate_cast_top_of_stack(statement, b, c)
|
|
||||||
return expr
|
return expr
|
||||||
:generate_push_float
|
:generate_unary_minus
|
||||||
|
expr += 8
|
||||||
|
expr = generate_push_expression_casted(statement, expr, type)
|
||||||
|
p = types + type
|
||||||
|
if *1p == TYPE_FLOAT goto generate_unary_minus_float
|
||||||
|
if *1p == TYPE_DOUBLE goto generate_unary_minus_double
|
||||||
|
; it's just an integer
|
||||||
|
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
|
||||||
|
emit_neg_rax() ; neg rax
|
||||||
|
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
||||||
|
return expr
|
||||||
|
; "negate(x) copies a floating-point operand x to a destination in the same format, reversing the sign bit." IEEE 754 § 5.5.1
|
||||||
|
:generate_unary_minus_float
|
||||||
|
c = 1 < 31 ; sign bit for floats
|
||||||
|
goto generate_unary_minus_floating
|
||||||
|
:generate_unary_minus_double
|
||||||
|
c = 1 < 63 ; sign bit for doubles
|
||||||
|
:generate_unary_minus_floating
|
||||||
|
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
|
||||||
|
emit_mov_reg(REG_RBX, REG_RAX) ; mov rbx, rax
|
||||||
|
emit_mov_rax_imm64(c) ; mov rax, (sign bit)
|
||||||
|
emit_xor_rax_rbx() ; xor rax, rbx
|
||||||
|
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
||||||
|
return expr
|
||||||
|
:generate_unary_bitwise_not
|
||||||
|
expr += 8
|
||||||
|
expr = generate_push_expression(statement, expr) ; we'll cast after we take the bitwise not.
|
||||||
|
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
|
||||||
|
emit_not_rax() ; not rax
|
||||||
|
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
||||||
|
generate_cast_top_of_stack(statement, TYPE_UNSIGNED_LONG, type)
|
||||||
|
return expr
|
||||||
|
:generate_unary_logical_not
|
||||||
|
expr += 8
|
||||||
|
p = expr + 4
|
||||||
|
p = types + *4p
|
||||||
|
if *1p == TYPE_FLOAT goto generate_logical_not_floating
|
||||||
|
if *1p == TYPE_DOUBLE goto generate_logical_not_floating
|
||||||
|
|
||||||
|
expr = generate_push_expression(statement, expr)
|
||||||
|
|
||||||
|
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
|
||||||
|
emit_test_rax_rax() ; test rax, rax
|
||||||
|
:generate_logical_not_cont
|
||||||
|
emit_je_rel32(7) ; je +7 (2 bytes for xor eax, eax; 5 bytes for jmp +10)
|
||||||
|
emit_zero_rax() ; xor eax, eax
|
||||||
|
emit_jmp_rel32(10) ; jmp +10 (10 bytes for mov rax, 1)
|
||||||
|
emit_mov_rax_imm64(1) ; mov rax, 1
|
||||||
|
emit_mov_qword_rsp_rax() ; mov [rsp], rax
|
||||||
|
return expr
|
||||||
|
|
||||||
|
:generate_logical_not_floating
|
||||||
|
; we want !-0.0 to be 1, so this needs to be a separate case
|
||||||
|
expr = generate_push_expression_casted(statement, expr, TYPE_DOUBLE) ; cast floats to doubles when comparing
|
||||||
|
emit_zero_rax() ; xor eax, eax
|
||||||
|
emit_movq_xmm1_rax() ; movq xmm1, rax
|
||||||
|
emit_mov_rax_qword_rsp() ; mov rax, [rsp]
|
||||||
|
emit_movq_xmm0_rax() ; movq xmm0, rax
|
||||||
|
emit_comisd_xmm0_xmm1() ; comisd xmm0, xmm1
|
||||||
|
goto generate_logical_not_cont
|
||||||
|
:generate_float
|
||||||
expr += 8
|
expr += 8
|
||||||
emit_mov_rax_imm64(*8expr)
|
emit_mov_rax_imm64(*8expr)
|
||||||
emit_push_rax()
|
emit_push_rax()
|
||||||
generate_cast_top_of_stack(statement, TYPE_DOUBLE, type)
|
generate_cast_top_of_stack(statement, TYPE_DOUBLE, type)
|
||||||
expr += 8
|
expr += 8
|
||||||
return expr
|
return expr
|
||||||
:generate_push_int
|
:generate_int
|
||||||
expr += 8
|
expr += 8
|
||||||
emit_mov_rax_imm64(*8expr)
|
emit_mov_rax_imm64(*8expr)
|
||||||
emit_push_rax()
|
emit_push_rax()
|
||||||
|
@ -561,14 +796,12 @@ function generate_statement
|
||||||
return
|
return
|
||||||
:gen_return
|
:gen_return
|
||||||
if dat1 == 0 goto gen_return_noexpr
|
if dat1 == 0 goto gen_return_noexpr
|
||||||
generate_push_expression(statement, dat1)
|
generate_push_expression_casted(statement, dat1, curr_function_return_type)
|
||||||
p = dat1 + 4 ; pointer to dat1 type
|
|
||||||
generate_cast_top_of_stack(statement, *4p, curr_function_return_type)
|
|
||||||
; copy sizeof(return expression) rounded up to 8 bytes from [rsp] to [rbp+16]
|
; copy sizeof(return expression) rounded up to 8 bytes from [rsp] to [rbp+16]
|
||||||
emit_mov_reg(REG_RSI, REG_RSP)
|
emit_mov_reg(REG_RSI, REG_RSP)
|
||||||
emit_lea_rax_rbp_plus_imm32(16)
|
emit_lea_rax_rbp_plus_imm32(16)
|
||||||
emit_mov_reg(REG_RDI, REG_RAX)
|
emit_mov_reg(REG_RDI, REG_RAX)
|
||||||
generate_copy_rsi_to_rdi_qwords(*4p)
|
generate_copy_rsi_to_rdi_qwords(curr_function_return_type)
|
||||||
|
|
||||||
:gen_return_noexpr
|
:gen_return_noexpr
|
||||||
generate_return()
|
generate_return()
|
||||||
|
@ -732,7 +965,7 @@ function generate_code
|
||||||
; call rax
|
; call rax
|
||||||
emit_call_rax()
|
emit_call_rax()
|
||||||
; mov rax, [rsp]
|
; mov rax, [rsp]
|
||||||
emit_mov_rax_qword_rsp_plus_imm32(0)
|
emit_mov_rax_qword_rsp()
|
||||||
; mov rdi, rax
|
; mov rdi, rax
|
||||||
emit_mov_reg(REG_RDI, REG_RAX)
|
emit_mov_reg(REG_RDI, REG_RAX)
|
||||||
; mov rax, 0x3c (SYS_exit)
|
; mov rax, 0x3c (SYS_exit)
|
||||||
|
|
|
@ -185,7 +185,6 @@
|
||||||
#define EXPRESSION_UNARY_MINUS 215
|
#define EXPRESSION_UNARY_MINUS 215
|
||||||
#define EXPRESSION_BITWISE_NOT 216
|
#define EXPRESSION_BITWISE_NOT 216
|
||||||
#define EXPRESSION_LOGICAL_NOT 217
|
#define EXPRESSION_LOGICAL_NOT 217
|
||||||
#define EXPRESSION_SIZEOF 218
|
|
||||||
#define EXPRESSION_CAST 219
|
#define EXPRESSION_CAST 219
|
||||||
#define EXPRESSION_MUL 220
|
#define EXPRESSION_MUL 220
|
||||||
#define EXPRESSION_DIV 221
|
#define EXPRESSION_DIV 221
|
||||||
|
|
19
05/main.c
19
05/main.c
|
@ -1,18 +1,3 @@
|
||||||
/*
|
long main(int argc, char **argv) {
|
||||||
; @NONSTANDARD:
|
return !1e-100;
|
||||||
; the following does not work:
|
|
||||||
; typedef struct T Type;
|
|
||||||
; struct T{
|
|
||||||
; int m;
|
|
||||||
; };
|
|
||||||
; ...
|
|
||||||
; Type *x = ...;
|
|
||||||
; x->m; *trying to access member of incomplete struct
|
|
||||||
This needs to be fixed because otherwise you can't do:
|
|
||||||
struct A { struct B *blah; }
|
|
||||||
struct B { struct A *blah; }
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
return (float)(long)"hello";
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3887,7 +3887,7 @@ function unary_op_to_expression_type
|
||||||
:return_EXPRESSION_PRE_INCREMENT
|
:return_EXPRESSION_PRE_INCREMENT
|
||||||
return EXPRESSION_PRE_INCREMENT
|
return EXPRESSION_PRE_INCREMENT
|
||||||
:return_EXPRESSION_PRE_DECREMENT
|
:return_EXPRESSION_PRE_DECREMENT
|
||||||
return EXPRESSION_PRE_INCREMENT
|
return EXPRESSION_PRE_DECREMENT
|
||||||
:return_EXPRESSION_ADDRESS_OF
|
:return_EXPRESSION_ADDRESS_OF
|
||||||
return EXPRESSION_ADDRESS_OF
|
return EXPRESSION_ADDRESS_OF
|
||||||
:return_EXPRESSION_DEREFERENCE
|
:return_EXPRESSION_DEREFERENCE
|
||||||
|
|
|
@ -181,14 +181,14 @@ ax bx cx dx sp bp si di
|
||||||
│ ja IMM32 │ 0f 87 IMM32 │ jump if "above" (like jg but unsigned) │
|
│ ja IMM32 │ 0f 87 IMM32 │ jump if "above" (like jg but unsigned) │
|
||||||
│ jbe IMM32 │ 0f 86 IMM32 │ jump if below or equal to │
|
│ jbe IMM32 │ 0f 86 IMM32 │ jump if below or equal to │
|
||||||
│ jae IMM32 │ 0f 83 IMM32 │ jump if above or equal to │
|
│ jae IMM32 │ 0f 83 IMM32 │ jump if above or equal to │
|
||||||
│ movss xmm0, [rax] │ f3 0f 10 00 │ load the float at *rax into xmm0 │
|
| movq rax, xmm0 | 66 48 0f 7e c0 | set rax to xmm0 |
|
||||||
│ movsd xmm0, [rax] │ f2 0f 10 00 │ load the double at *rax into xmm0 │
|
| movq xmm0, rax | 66 48 0f 6e c0 | set xmm0 to rax |
|
||||||
│ movss [rax], xmm0 │ f3 0f 11 00 │ store the float in xmm0 at *rax │
|
| movq xmm1, rax | 66 48 0f 6e c8 | set xmm1 to rax |
|
||||||
│ movsd [rax], xmm0 │ f2 0f 11 00 │ store the double in xmm0 at *rax │
|
|
||||||
| cvtss2sd xmm0, xmm0 | f3 0f 5a c0 | convert xmm0 from float to double |
|
| cvtss2sd xmm0, xmm0 | f3 0f 5a c0 | convert xmm0 from float to double |
|
||||||
| cvtsd2ss xmm0, xmm0 | f2 0f 5a c0 | convert xmm0 from double to float |
|
| cvtsd2ss xmm0, xmm0 | f2 0f 5a c0 | convert xmm0 from double to float |
|
||||||
| cvttsd2si rax, xmm0 | f2 48 0f 2c c0 | convert double in xmm0 to int in rax |
|
| cvttsd2si rax, xmm0 | f2 48 0f 2c c0 | convert double in xmm0 to int in rax |
|
||||||
| cvtsi2sd xmm0, rax | f2 48 0f 2a c0 | convert int in rax to double in xmm0 |
|
| cvtsi2sd xmm0, rax | f2 48 0f 2a c0 | convert int in rax to double in xmm0 |
|
||||||
|
| comisd xmm0, xmm1 | 66 0f 2f c1 | compare xmm0 and xmm1 |
|
||||||
│ call rax │ ff d0 │ call the function at address rax │
|
│ call rax │ ff d0 │ call the function at address rax │
|
||||||
│ ret │ c3 │ return from function │
|
│ ret │ c3 │ return from function │
|
||||||
│ syscall │ 0f 05 │ execute a system call │
|
│ syscall │ 0f 05 │ execute a system call │
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue