@@ -59,12 +59,9 @@ fn byt(n int, s int) u8 {
59
59
}
60
60
61
61
fn (mut g Gen) inc (reg Register) {
62
- g.write16 (0xff49 )
63
- match reg {
64
- .rcx { g.write8 (0xc1 ) }
65
- .r12 { g.write8 (0xc4 ) }
66
- else { panic ('unhandled inc $reg ' ) }
67
- }
62
+ g.write8 (0x48 )
63
+ g.write8 (0xff )
64
+ g.write8 (0xc0 + int (reg))
68
65
g.println ('inc $reg ' )
69
66
}
70
67
@@ -138,6 +135,16 @@ fn (mut g Gen) cmp_reg(reg Register, reg2 Register) {
138
135
}
139
136
}
140
137
}
138
+ .rdi {
139
+ match reg2 {
140
+ .rsi {
141
+ g.write ([u8 (0x48 ), 0x39 , 0xf7 ])
142
+ }
143
+ else {
144
+ g.n_error ('Cannot compare $reg and $reg2 ' )
145
+ }
146
+ }
147
+ }
141
148
else {
142
149
g.n_error ('Cannot compare $reg and $reg2 ' )
143
150
}
@@ -235,14 +242,14 @@ fn abs(a i64) i64 {
235
242
fn (mut g Gen) tmp_jle (addr i64 ) {
236
243
// Calculate the relative offset to jump to
237
244
// (`addr` is absolute address)
238
- offset := 0xff - int ( abs (addr - g.buf.len)) - 1
245
+ offset := 0xff - g. abs_to_rel_addr (addr)
239
246
g.write8 (0x7e )
240
247
g.write8 (offset)
241
248
g.println ('jle' )
242
249
}
243
250
244
251
fn (mut g Gen) jl (addr i64 ) {
245
- offset := 0xff - int ( abs (addr - g.buf.len)) - 1
252
+ offset := 0xff - g. abs_to_rel_addr (addr)
246
253
g.write8 (0x7c )
247
254
g.write8 (offset)
248
255
g.println ('jl' )
@@ -381,7 +388,7 @@ fn (mut g Gen) mov_int_to_var(var_offset int, size Size, integer int) {
381
388
382
389
fn (mut g Gen) lea_var_to_reg (reg Register, var_offset int ) {
383
390
match reg {
384
- .rax, .rbx, .rsi {
391
+ .rax, .rbx, .rsi, .rdi {
385
392
g.write8 (0x48 )
386
393
}
387
394
else {}
@@ -445,6 +452,11 @@ fn (mut g Gen) syscall() {
445
452
g.println ('syscall' )
446
453
}
447
454
455
+ fn (mut g Gen) cdq () {
456
+ g.write8 (0x99 )
457
+ g.println ('cdq' )
458
+ }
459
+
448
460
pub fn (mut g Gen) ret () {
449
461
g.write8 (0xc3 )
450
462
g.println ('ret' )
@@ -509,8 +521,7 @@ pub fn (mut g Gen) add(reg Register, val int) {
509
521
pub fn (mut g Gen) add8 (reg Register, val int ) {
510
522
g.write8 (0x48 )
511
523
g.write8 (0x83 )
512
- // g.write8(0xe8 + reg) // TODO rax is different?
513
- g.write8 (0xc4 )
524
+ g.write8 (0xc0 + int (reg))
514
525
g.write8 (val)
515
526
g.println ('add8 $reg ,$val.hex2 ()' )
516
527
}
@@ -595,9 +606,18 @@ pub fn (mut g Gen) rep_stosb() {
595
606
g.println ('rep stosb' )
596
607
}
597
608
598
- pub fn (mut g Gen) cld_repne_scasb () {
609
+ pub fn (mut g Gen) std () {
610
+ g.write8 (0xfd )
611
+ g.println ('std' )
612
+ }
613
+
614
+ pub fn (mut g Gen) cld () {
599
615
g.write8 (0xfc )
600
616
g.println ('cld' )
617
+ }
618
+
619
+ pub fn (mut g Gen) cld_repne_scasb () {
620
+ g.cld ()
601
621
g.write8 (0xf2 )
602
622
g.write8 (0xae )
603
623
g.println ('repne scasb' )
@@ -931,6 +951,9 @@ fn (mut g Gen) mov(reg Register, val int) {
931
951
g.write8 (0x41 )
932
952
g.write8 (0xbc ) // r11 is 0xbb etc
933
953
}
954
+ .rbx {
955
+ g.write8 (0xbb )
956
+ }
934
957
else {
935
958
g.n_error ('unhandled mov $reg ' )
936
959
}
@@ -1084,6 +1107,18 @@ fn (mut g Gen) mov_reg(a Register, b Register) {
1084
1107
g.write8 (0x48 )
1085
1108
g.write8 (0x89 )
1086
1109
g.write8 (0xc7 )
1110
+ } else if a == .r12 && b == .rdi {
1111
+ g.write8 (0x49 )
1112
+ g.write8 (0x89 )
1113
+ g.write8 (0xfc )
1114
+ } else if a == .rdi && b == .r12 {
1115
+ g.write8 (0x4c )
1116
+ g.write8 (0x89 )
1117
+ g.write8 (0xe7 )
1118
+ } else if a == .rsi && b == .rdi {
1119
+ g.write8 (0x48 )
1120
+ g.write8 (0x89 )
1121
+ g.write8 (0xfe )
1087
1122
} else {
1088
1123
g.n_error ('unhandled mov_reg combination for $a $b ' )
1089
1124
}
@@ -1988,6 +2023,9 @@ fn (mut g Gen) convert_int_to_string(r Register, buffer int) {
1988
2023
g.labels.addrs[skip_zero_label] = g.pos ()
1989
2024
g.println ('; label $skip_zero_label ' )
1990
2025
2026
+ // load a pointer to the string to rdi
2027
+ g.lea_var_to_reg (.rdi, buffer)
2028
+
1991
2029
// detect if value in rax is negative
1992
2030
g.cmp_zero (.rax)
1993
2031
skip_minus_label := g.labels.new_label ()
@@ -2000,11 +2038,103 @@ fn (mut g Gen) convert_int_to_string(r Register, buffer int) {
2000
2038
2001
2039
// add a `-` sign as the first character
2002
2040
g.mov_int_to_var (buffer, ._8 , '-' [0 ])
2003
- g.neg (.rax)
2041
+ g.neg (.rax) // negate our integer to make it positive
2042
+ g.inc (.rdi) // increment rdi to skip the `-` character
2004
2043
g.labels.addrs[skip_minus_label] = g.pos ()
2044
+ g.println ('; label $skip_minus_label ' )
2045
+
2046
+ g.mov_reg (.r12 , .rdi) // copy the buffer position to rcx
2047
+
2048
+ loop_label := g.labels.new_label ()
2049
+ loop_start := g.pos ()
2050
+ g.println ('; label $loop_label ' )
2051
+
2052
+ g.push (.rax)
2053
+
2054
+ g.mov (.rdx, 0 )
2055
+ g.mov (.rbx, 10 )
2056
+ g.div_reg (.rax, .rbx)
2057
+ g.add8 (.rdx, '0' [0 ])
2005
2058
2006
- // TODO: convert non-zero integer to string
2059
+ g.write8 (0x66 )
2060
+ g.write8 (0x89 )
2061
+ g.write8 (0x17 )
2062
+ g.println ('mov BYTE PTR [rdi], rdx' )
2063
+
2064
+ // divide the integer in rax by 10 for next iteration
2065
+ g.pop (.rax)
2066
+ g.mov (.rbx, 10 )
2067
+ g.cdq ()
2068
+ g.write8 (0x48 )
2069
+ g.write8 (0xf7 )
2070
+ g.write8 (0xfb )
2071
+ g.println ('idiv rbx' )
2072
+
2073
+ // go to the next character
2074
+ g.inc (.rdi)
2075
+
2076
+ // if the number in rax still isn't zero, repeat
2077
+ g.cmp_zero (.rax)
2078
+ loop_cjmp_addr := g.cjmp (.jg)
2079
+ g.labels.patches << LabelPatch{
2080
+ id: loop_label
2081
+ pos: loop_cjmp_addr
2082
+ }
2083
+ g.println ('; jump to label $skip_minus_label ' )
2084
+ g.labels.addrs[loop_label] = loop_start
2085
+
2086
+ // after all was converted, reverse the string
2087
+ g.reverse_string (.r12 )
2007
2088
2008
2089
g.labels.addrs[end_label] = g.pos ()
2009
2090
g.println ('; label $end_label ' )
2010
2091
}
2092
+
2093
+ fn (mut g Gen) reverse_string (reg Register) {
2094
+ if reg != .rdi {
2095
+ g.mov_reg (.rdi, reg)
2096
+ }
2097
+
2098
+ g.mov (.eax, 0 )
2099
+
2100
+ g.write8 (0x48 )
2101
+ g.write8 (0x8d )
2102
+ g.write8 (0x48 )
2103
+ g.write8 (0xff )
2104
+ g.println ('lea rcx, [rax-0x1]' )
2105
+
2106
+ g.mov_reg (.rsi, .rdi)
2107
+
2108
+ g.write8 (0xf2 )
2109
+ g.write8 (0xae )
2110
+ g.println ('repnz scas al, BYTE PTR es:[rdi]' )
2111
+
2112
+ g.sub8 (.rdi, 0x2 )
2113
+ g.cmp_reg (.rdi, .rsi)
2114
+
2115
+ g.write8 (0x7e )
2116
+ g.write8 (0x0a )
2117
+ g.println ('jle 0x1e' )
2118
+
2119
+ g.write8 (0x86 )
2120
+ g.write8 (0x07 )
2121
+ g.println ('xchg BYTE PTR [rdi], al' )
2122
+
2123
+ g.write8 (0x86 )
2124
+ g.write8 (0x06 )
2125
+ g.println ('xchg BYTE PTR [rsi], al' )
2126
+
2127
+ g.std ()
2128
+
2129
+ g.write8 (0xaa )
2130
+ g.println ('stos BYTE PTR es:[rdi], al' )
2131
+
2132
+ g.cld ()
2133
+
2134
+ g.write8 (0xac )
2135
+ g.println ('lods al, BYTE PTR ds:[rsi]' )
2136
+
2137
+ g.write8 (0xeb )
2138
+ g.write8 (0xf1 )
2139
+ g.println ('jmp 0xf' )
2140
+ }
0 commit comments