asm_backend.rs 22.1 KB
Newer Older
1 2
#![allow(unused_variables)]

3
use compiler::backend;
4
use compiler::backend::x86_64;
5
use compiler::backend::x86_64::CodeGenerator;
6
use vm::machine_code::MachineCode;
7

8 9
use utils::string_utils;

10 11
use ast::ptr::P;
use ast::ir::*;
qinsoon's avatar
qinsoon committed
12
use ast::inst::*;
13

14 15
use std::collections::HashMap;
use std::str;
16
use std::usize;
17
use std::slice::Iter;
18 19 20

struct ASMCode {
    name: MuTag, 
21 22
    code: Vec<ASM>,
    reg_defines: HashMap<MuID, Vec<ASMLocation>>,
23 24 25 26 27 28 29 30 31
    reg_uses: HashMap<MuID, Vec<ASMLocation>>,
    
    preds: Vec<Vec<usize>>,
    succs: Vec<Vec<usize>>,
    
    idx_to_blk: HashMap<usize, MuTag>,
    blk_to_idx: HashMap<MuTag, usize>,
    cond_branches: HashMap<usize, MuTag>,
    branches: HashMap<usize, MuTag>
32 33
}

34 35 36 37
impl MachineCode for ASMCode {
    fn number_of_insts(&self) -> usize {
        self.code.len()
    }
38
    
39 40 41 42 43 44 45 46
    fn is_move(&self, index: usize) -> bool {
        let inst = self.code.get(index);
        match inst {
            Some(inst) => inst.code.starts_with("mov"),
            None => false
        }
    }
    
qinsoon's avatar
qinsoon committed
47 48 49 50 51 52 53 54
    fn get_succs(&self, index: usize) -> &Vec<usize> {
        &self.succs[index]
    }
    
    fn get_preds(&self, index: usize) -> &Vec<usize> {
        &self.preds[index]
    }
    
55
    fn get_inst_reg_uses(&self, index: usize) -> &Vec<MuID> {
qinsoon's avatar
qinsoon committed
56
        &self.code[index].uses
57 58
    }
    
59
    fn get_inst_reg_defines(&self, index: usize) -> &Vec<MuID> {
qinsoon's avatar
qinsoon committed
60
        &self.code[index].defines
61
    }
62
    
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    fn replace_reg(&mut self, from: MuID, to: MuID) {
        let to_reg_tag : MuTag = backend::all_regs()[to].tag;
        let to_reg_string = "%".to_string() + to_reg_tag;
        
        match self.reg_defines.get(&from) {
            Some(defines) => {
                for loc in defines {
                    let ref mut inst_to_patch = self.code[loc.line];
                    for i in 0..loc.len {
                        string_utils::replace(&mut inst_to_patch.code, loc.index, &to_reg_string, to_reg_string.len());
                    }
                }
            },
            None => {}
        }
        
        match self.reg_uses.get(&from) {
            Some(uses) => {
                for loc in uses {
                    let ref mut inst_to_patch = self.code[loc.line];
                    for i in 0..loc.len {
                        string_utils::replace(&mut inst_to_patch.code, loc.index, &to_reg_string, to_reg_string.len());
                    }   
                }
            },
            None => {}
        }
    }
    
92 93 94 95 96 97 98
    fn print(&self) {
        println!("");

        println!("code for {}: ", self.name);
        let n_insts = self.code.len();
        for i in 0..n_insts {
            let ref line = self.code[i];
99 100 101
            println!("#{}\t{:30}\t\tdefine: {:?}\tuses: {:?}\tpred: {:?}\tsucc: {:?}", 
                i, line.code, self.get_inst_reg_defines(i), self.get_inst_reg_uses(i),
                self.preds[i], self.succs[i]);
102 103 104
        }
        
        println!("");        
105 106 107 108 109 110 111
    }
}

struct ASM {
    code: String,
    defines: Vec<MuID>,
    uses: Vec<MuID>
112 113
}

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
impl ASM {
    fn symbolic(line: String) -> ASM {
        ASM {
            code: line,
            defines: vec![],
            uses: vec![]
        }
    }
    
    fn inst(inst: String, defines: Vec<MuID>, uses: Vec<MuID>) -> ASM {
        ASM {
            code: inst,
            defines: defines,
            uses: uses
        }
    }
    
    fn branch(line: String) -> ASM {
        ASM {
            code: line,
            defines: vec![],
            uses: vec![]
        }
    }
138 139
}

140
#[derive(Clone, Debug)]
141 142 143 144 145 146 147
struct ASMLocation {
    line: usize,
    index: usize,
    len: usize
}

impl ASMLocation {
148 149
    /// the 'line' field will be updated later
    fn new(index: usize, len: usize) -> ASMLocation {
150
        ASMLocation{
151
            line: usize::MAX,
152 153 154 155 156 157
            index: index,
            len: len
        }
    }
}

158
pub struct ASMCodeGen {
159
    cur: Option<Box<ASMCode>>
160 161
}

162
const REG_PLACEHOLDER_LEN : usize = 5;
163 164 165 166 167 168
lazy_static! {
    pub static ref REG_PLACEHOLDER : String = {
        let blank_spaces = [' ' as u8; REG_PLACEHOLDER_LEN];
        
        format!("%{}", str::from_utf8(&blank_spaces).unwrap())
    };
169 170 171
}

impl ASMCodeGen {
172 173

        
174
    pub fn new() -> ASMCodeGen {
175
        ASMCodeGen {
176
            cur: None
177 178 179 180 181 182 183 184 185 186 187
        }
    }
    
    fn cur(&self) -> &ASMCode {
        self.cur.as_ref().unwrap()
    }
    
    fn cur_mut(&mut self) -> &mut ASMCode {
        self.cur.as_mut().unwrap()
    }
    
188 189 190 191 192 193 194 195 196 197 198 199
    fn line(&self) -> usize {
        self.cur().code.len()
    }
    
    fn add_asm_block_label(&mut self, code: String, block_name: &'static str) {
        let l = self.line();
        self.cur_mut().code.push(ASM::symbolic(code));
        
        self.cur_mut().idx_to_blk.insert(l, block_name);
        self.cur_mut().blk_to_idx.insert(block_name, l);
    }
    
200 201 202 203
    fn add_asm_symbolic(&mut self, code: String){
        self.cur_mut().code.push(ASM::symbolic(code));
    }
    
204 205 206 207
    fn prepare_machine_regs(&self, regs: Iter<P<Value>>) -> Vec<MuID> {
        regs.map(|x| self.prepare_machine_reg(x)).collect()
    } 
    
208
    fn add_asm_call(&mut self, code: String) {
209 210 211 212 213 214 215
        let mut uses : Vec<MuID> = self.prepare_machine_regs(x86_64::ARGUMENT_GPRs.iter());
        uses.append(&mut self.prepare_machine_regs(x86_64::ARGUMENT_FPRs.iter()));
        
        let mut defines : Vec<MuID> = self.prepare_machine_regs(x86_64::RETURN_GPRs.iter());
        defines.append(&mut self.prepare_machine_regs(x86_64::RETURN_FPRs.iter()));
          
        self.add_asm_inst(code, defines, vec![], uses, vec![]);
216 217 218
    }
    
    fn add_asm_ret(&mut self, code: String) {
219 220 221 222
        let mut uses : Vec<MuID> = self.prepare_machine_regs(x86_64::RETURN_GPRs.iter());
        uses.append(&mut self.prepare_machine_regs(x86_64::RETURN_FPRs.iter()));
        
        self.add_asm_inst(code, vec![], vec![], uses, vec![]);
223 224 225 226
    }
    
    fn add_asm_branch(&mut self, code: String, target: &'static str) {
        let l = self.line();
227
        self.cur_mut().code.push(ASM::branch(code));
228 229 230 231 232 233 234 235 236
        
        self.cur_mut().branches.insert(l, target);
    }
    
    fn add_asm_branch2(&mut self, code: String, target: &'static str) {
        let l = self.line();
        self.cur_mut().code.push(ASM::branch(code));
        
        self.cur_mut().cond_branches.insert(l, target);
237 238 239 240 241 242
    }
    
    fn add_asm_inst(
        &mut self, 
        code: String, 
        defines: Vec<MuID>,
243
        mut define_locs: Vec<ASMLocation>, 
244
        uses: Vec<MuID>,
245
        mut use_locs: Vec<ASMLocation>) 
246
    {
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
        let line = self.line();
        
        trace!("asm: {}", code);
        trace!("     defines: {:?}, def_locs: {:?}", defines, define_locs);
        trace!("     uses: {:?}, use_locs: {:?}", uses, use_locs);
        let mc = self.cur_mut();
       
        // add locations of defined registers
        for i in 0..define_locs.len() {
            let id = defines[i];
            
            // update line in location
            let ref mut loc = define_locs[i];
            loc.line = line;
            
            if mc.reg_defines.contains_key(&id) {
                mc.reg_defines.get_mut(&id).unwrap().push(loc.clone());
            } else {
                mc.reg_defines.insert(id, vec![loc.clone()]);
            }
        }
       
        for i in 0..use_locs.len() {
            let id = uses[i];
            
            // update line in location
            let ref mut loc = use_locs[i];
            loc.line = line;
            
            if mc.reg_uses.contains_key(&id) {
277
                mc.reg_uses.get_mut(&id).unwrap().push(loc.clone());
278
            } else {
279
                mc.reg_uses.insert(id, vec![loc.clone()]);
280 281
            }
        }
282
       
283 284
        // put the instruction
        mc.code.push(ASM::inst(code, defines, uses));
285 286 287 288
    }
    
    fn define_reg(&mut self, reg: &P<Value>, loc: ASMLocation) {
        let id = reg.extract_ssa_id().unwrap();
289
        
290 291 292 293 294 295 296
        let code = self.cur_mut();
        if code.reg_defines.contains_key(&id) {
            let regs = code.reg_defines.get_mut(&id).unwrap();
            regs.push(loc);
        } else {
            code.reg_defines.insert(id, vec![loc]);
        } 
297 298 299 300 301 302
    }
    
    fn use_reg(&mut self, reg: &P<Value>, loc: ASMLocation) {
        let id = reg.extract_ssa_id().unwrap();
        
        let code = self.cur_mut();
303 304 305
        if code.reg_uses.contains_key(&id) {
            let reg_uses = code.reg_uses.get_mut(&id).unwrap();
            reg_uses.push(loc);
306
        } else {
307
            code.reg_uses.insert(id, vec![loc]);
308 309 310
        } 
    }
    
311 312 313 314 315 316 317 318
    fn prepare_op(&self, op: &P<Value>, loc: usize) -> (String, MuID, ASMLocation) {
        let str = self.asm_reg_op(op);
        let len = str.len();
        (str, op.extract_ssa_id().unwrap(), ASMLocation::new(loc, len)) 
    }
    
    fn prepare_machine_reg(&self, op: &P<Value>) -> MuID {
        op.extract_ssa_id().unwrap()
319
    }
320
    
321 322 323 324 325 326 327 328 329 330 331 332 333
    fn asm_reg_op(&self, op: &P<Value>) -> String {
        let id = op.extract_ssa_id().unwrap();
        if id < RESERVED_NODE_IDS_FOR_MACHINE {
            // machine reg
            format!("%{}", op.tag)
        } else {
            // virtual register, use place holder
            REG_PLACEHOLDER.clone()
        }
    }
    
    fn asm_block_label(&self, label: MuTag) -> String {
        format!("{}_{}", self.cur().name, label)
334
    }
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
    
    fn control_flow_analysis(&mut self) {
        // control flow analysis
        let n_insts = self.line();
        
        let code = self.cur_mut();
        code.preds = vec![vec![]; n_insts];
        code.succs = vec![vec![]; n_insts];
        
        for i in 0..n_insts {
            // determine predecessor - if cur is not block start, its predecessor is previous insts
            let is_block_start = code.idx_to_blk.get(&i);
            if is_block_start.is_none() {
                if i > 0 {
                    code.preds[i].push(i - 1);
                }
            } else {
                // if cur is a branch target, we already set its predecessor
                // if cur is a fall-through block, we set it in a sanity check pass
            }
            
            // determine successor
            let is_branch = code.branches.get(&i);
            if is_branch.is_some() {
                // branch to target
                let target = is_branch.unwrap();
                let target_n = code.blk_to_idx.get(target).unwrap();
                
                // cur inst's succ is target
                code.succs[i].push(*target_n);
                
                // target's pred is cur
                code.preds[*target_n].push(i);
            } else {
                let is_cond_branch = code.cond_branches.get(&i);
                if is_cond_branch.is_some() {
                    // branch to target
                    let target = is_cond_branch.unwrap();
                    let target_n = code.blk_to_idx.get(target).unwrap();
                    
                    // cur insts' succ is target and next inst
                    code.succs[i].push(*target_n);
                    if i < n_insts - 1 {
                        code.succs[i].push(i + 1);
                    }
                    
                    // target's pred is cur
                    code.preds[*target_n].push(i);
                } else {
                    // not branch nor cond branch, succ is next inst
                    if i < n_insts - 1 {
                        code.succs[i].push(i + 1);
                    }
                }
            } 
        }
        
        // a sanity check for fallthrough blocks
        for i in 0..n_insts {
            if i != 0 && code.preds[i].len() == 0 {
                code.preds[i].push(i - 1);
            }
        }        
    }
399 400 401
}

impl CodeGenerator for ASMCodeGen {
402
    fn start_code(&mut self, func_name: MuTag) {
403
        self.cur = Some(Box::new(ASMCode {
404 405
                name: func_name,
                code: vec![],
406
                reg_defines: HashMap::new(),
407 408 409 410 411 412 413 414 415 416
                reg_uses: HashMap::new(),
                
                preds: vec![],
                succs: vec![],
                
                idx_to_blk: HashMap::new(),
                blk_to_idx: HashMap::new(),
                cond_branches: HashMap::new(),
                branches: HashMap::new()
            }));
417
        
418
        self.add_asm_symbolic(format!(".globl {}", func_name));
419 420
    }
    
421 422 423
    fn finish_code(&mut self) -> Box<MachineCode> {
        self.control_flow_analysis();
        self.cur.take().unwrap()
424 425 426 427 428 429 430 431 432
    }
    
    fn print_cur_code(&self) {
        println!("");
        
        if self.cur.is_some() {
            let code = self.cur.as_ref().unwrap();
            
            println!("code for {}: ", code.name);
433 434 435 436
            let n_insts = code.code.len();
            for i in 0..n_insts {
                let ref line = code.code[i];
                println!("#{}\t{}", i, line.code);
437 438 439 440 441 442 443 444 445
            }
        } else {
            println!("no current code");
        }
        
        println!("");
    }
    
    fn start_block(&mut self, block_name: MuTag) {
446 447
        let label = format!("{}:", self.asm_block_label(block_name));        
        self.add_asm_block_label(label, block_name);
448 449
    }
    
450
    fn emit_cmp_r64_r64(&mut self, op1: &P<Value>, op2: &P<Value>) {
qinsoon's avatar
qinsoon committed
451
        trace!("emit: cmp {} {}", op1, op2);
452
        
453 454
        let (reg1, id1, loc1) = self.prepare_op(op1, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(op2, 4 + 1 + reg1.len() + 1);
455 456 457
        
        let asm = format!("cmpq {} {}", reg1, reg2);
        
458 459 460 461 462 463 464
        self.add_asm_inst(
            asm,
            vec![],
            vec![],
            vec![id1, id2],
            vec![loc1, loc2]
        );
465 466
    }
    
qinsoon's avatar
qinsoon committed
467 468
    fn emit_cmp_r64_imm32(&mut self, op1: &P<Value>, op2: u32) {
        trace!("emit: cmp {} {}", op1, op2);
469
        
470
        let (reg1, id1, loc1) = self.prepare_op(op1, 4 + 1);
471 472 473
        
        let asm = format!("cmpq {} ${}", reg1, op2);
        
474 475 476 477 478 479 480
        self.add_asm_inst(
            asm,
            vec![],
            vec![],
            vec![id1],
            vec![loc1]
        )
481 482 483
    }
    
    fn emit_cmp_r64_mem64(&mut self, op1: &P<Value>, op2: &P<Value>) {
qinsoon's avatar
qinsoon committed
484
        trace!("emit: cmp {} {}", op1, op2);
485
        unimplemented!()
486 487
    }
    
qinsoon's avatar
qinsoon committed
488 489
    fn emit_mov_r64_imm32(&mut self, dest: &P<Value>, src: u32) {
        trace!("emit: mov {} -> {}", src, dest);
490
        
491
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1 + 1 + src.to_string().len() + 1);
492
        
493
        let asm = format!("movq ${} {}", src, reg1);
494
        
495 496 497
        self.add_asm_inst(
            asm,
            vec![id1],
498 499 500
            vec![loc1],
            vec![],
            vec![]
501
        )
502 503 504
    }
    
    fn emit_mov_r64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
qinsoon's avatar
qinsoon committed
505
        trace!("emit: mov {} -> {}", src, dest);
506
        unimplemented!()
qinsoon's avatar
qinsoon committed
507 508 509 510
    }
    
    fn emit_mov_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: mov {} -> {}", src, dest);
511
        
512 513
        let (reg1, id1, loc1) = self.prepare_op(src, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(dest, 4 + 1 + reg1.len() + 1);
514
        
515
        let asm = format!("movq {} {}", reg1, reg2);
516
        
517 518 519
        self.add_asm_inst(
            asm,
            vec![id2],
520 521 522
            vec![loc2],
            vec![id1],
            vec![loc1]
523
        )
qinsoon's avatar
qinsoon committed
524 525 526 527
    }
    
    fn emit_add_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: add {}, {} -> {}", dest, src, dest);
528
        
529 530
        let (reg1, id1, loc1) = self.prepare_op(src, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(dest, 4 + 1 + reg1.len() + 1);
531
        
532
        let asm = format!("addq {} {}", reg1, reg2);
533
        
534 535
        self.add_asm_inst(
            asm,
536 537
            vec![id2],
            vec![loc2.clone()],
538 539 540
            vec![id1, id2],
            vec![loc1, loc2]
        )
qinsoon's avatar
qinsoon committed
541 542 543 544
    }
    
    fn emit_add_r64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: add {}, {} -> {}", dest, src, dest);
545
        unimplemented!()
qinsoon's avatar
qinsoon committed
546 547 548 549
    }
    
    fn emit_add_r64_imm32(&mut self, dest: &P<Value>, src: u32) {
        trace!("emit: add {}, {} -> {}", dest, src, dest);
550
        
551
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
552 553 554
        
        let asm = format!("addq {} ${}", src, reg1);
        
555 556 557 558 559 560 561
        self.add_asm_inst(
            asm,
            vec![id1],
            vec![loc1.clone()],
            vec![id1],
            vec![loc1]
        )
qinsoon's avatar
qinsoon committed
562 563 564 565
    }
    
    fn emit_sub_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: sub {}, {} -> {}", dest, src, dest);
566
        
567 568
        let (reg1, id1, loc1) = self.prepare_op(src, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(dest, 4 + 1 + reg1.len() + 1);
569
        
570
        let asm = format!("subq {} {}", reg1, reg2);
571
        
572 573
        self.add_asm_inst(
            asm,
574 575
            vec![id2],
            vec![loc2.clone()],
576 577 578
            vec![id1, id2],
            vec![loc1, loc2]
        )        
qinsoon's avatar
qinsoon committed
579 580 581 582
    }
    
    fn emit_sub_r64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: sub {}, {} -> {}", dest, src, dest);
583
        unimplemented!()
qinsoon's avatar
qinsoon committed
584 585 586 587
    }
    
    fn emit_sub_r64_imm32(&mut self, dest: &P<Value>, src: u32) {
        trace!("emit: sub {}, {} -> {}", dest, src, dest);
588
        
589
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1 + 1 + src.to_string().len() + 1);
590
        
591
        let asm = format!("subq ${} {}", src, reg1);
592
        
593 594 595 596 597 598 599
        self.add_asm_inst(
            asm,
            vec![id1],
            vec![loc1.clone()],
            vec![id1],
            vec![loc1]
        )        
qinsoon's avatar
qinsoon committed
600 601
    }
    
602
    fn emit_mul_r64(&mut self, src: &P<Value>) {
603
        trace!("emit: mul rax, {} -> (rdx, rax)", src);
604
        
605 606 607
        let (reg, id, loc) = self.prepare_op(src, 3 + 1);
        let rax = self.prepare_machine_reg(&x86_64::RAX);
        let rdx = self.prepare_machine_reg(&x86_64::RDX);
608 609 610
        
        let asm = format!("mul {}", reg);
        
611 612 613 614 615 616 617
        self.add_asm_inst(
            asm,
            vec![rax, rdx],
            vec![],
            vec![id, rax],
            vec![loc]
        )
618 619 620 621
    }
    
    fn emit_mul_mem64(&mut self, src: &P<Value>) {
        trace!("emit: mul rax, {} -> rax", src);
622
        unimplemented!()
623 624
    }
    
qinsoon's avatar
qinsoon committed
625 626
    fn emit_jmp(&mut self, dest: &Destination) {
        trace!("emit: jmp {}", dest.target);
627 628 629
        
        // symbolic label, we dont need to patch it
        let asm = format!("jmp {}", self.asm_block_label(dest.target));
630
        self.add_asm_branch(asm, dest.target)
qinsoon's avatar
qinsoon committed
631 632 633 634
    }
    
    fn emit_je(&mut self, dest: &Destination) {
        trace!("emit: je {}", dest.target);
635 636
        
        let asm = format!("je {}", self.asm_block_label(dest.target));
637
        self.add_asm_branch2(asm, dest.target);        
qinsoon's avatar
qinsoon committed
638 639 640 641
    }
    
    fn emit_jne(&mut self, dest: &Destination) {
        trace!("emit: jne {}", dest.target);
642 643
        
        let asm = format!("jne {}", self.asm_block_label(dest.target));
644
        self.add_asm_branch2(asm, dest.target);
qinsoon's avatar
qinsoon committed
645 646 647 648
    }
    
    fn emit_ja(&mut self, dest: &Destination) {
        trace!("emit: ja {}", dest.target);
649 650
        
        let asm = format!("ja {}", self.asm_block_label(dest.target));
651
        self.add_asm_branch2(asm, dest.target);
qinsoon's avatar
qinsoon committed
652 653 654 655
    }
    
    fn emit_jae(&mut self, dest: &Destination) {
        trace!("emit: jae {}", dest.target);
656 657
        
        let asm = format!("jae {}", self.asm_block_label(dest.target));
658
        self.add_asm_branch2(asm, dest.target);        
qinsoon's avatar
qinsoon committed
659 660 661 662
    }
    
    fn emit_jb(&mut self, dest: &Destination) {
        trace!("emit: jb {}", dest.target);
663 664
        
        let asm = format!("jb {}", self.asm_block_label(dest.target));
665
        self.add_asm_branch2(asm, dest.target);
qinsoon's avatar
qinsoon committed
666 667 668 669
    }
    
    fn emit_jbe(&mut self, dest: &Destination) {
        trace!("emit: jbe {}", dest.target);
670 671
        
        let asm = format!("jbe {}", self.asm_block_label(dest.target));
672
        self.add_asm_branch2(asm, dest.target);        
qinsoon's avatar
qinsoon committed
673 674
    }
    
675 676
    fn emit_jg(&mut self, dest: &Destination) {
        trace!("emit: jg {}", dest.target);
677 678
        
        let asm = format!("jg {}", self.asm_block_label(dest.target));
679
        self.add_asm_branch2(asm, dest.target);        
680 681 682 683
    }
    
    fn emit_jge(&mut self, dest: &Destination) {
        trace!("emit: jge {}", dest.target);
684 685
        
        let asm = format!("jge {}", self.asm_block_label(dest.target));
686
        self.add_asm_branch2(asm, dest.target);        
687 688 689 690
    }
    
    fn emit_jl(&mut self, dest: &Destination) {
        trace!("emit: jl {}", dest.target);
691 692
        
        let asm = format!("jl {}", self.asm_block_label(dest.target));
693
        self.add_asm_branch2(asm, dest.target);        
694 695 696 697
    }
    
    fn emit_jle(&mut self, dest: &Destination) {
        trace!("emit: jle {}", dest.target);
698 699
        
        let asm = format!("jle {}", self.asm_block_label(dest.target));
700
        self.add_asm_branch2(asm, dest.target);        
701 702
    }    
    
703 704
    fn emit_call_near_rel32(&mut self, func: MuTag) {
        trace!("emit: call {}", func);
705 706
        
        let asm = format!("call {}", func);
707
        self.add_asm_call(asm);
708 709
        
        // FIXME: call interferes with machine registers
710 711 712 713
    }
    
    fn emit_call_near_r64(&mut self, func: &P<Value>) {
        trace!("emit: call {}", func);
714
        unimplemented!()
715 716 717
    }
    
    fn emit_call_near_mem64(&mut self, func: &P<Value>) {
qinsoon's avatar
qinsoon committed
718
        trace!("emit: call {}", func);
719
        unimplemented!()
qinsoon's avatar
qinsoon committed
720 721 722 723
    }
    
    fn emit_ret(&mut self) {
        trace!("emit: ret");
724 725
        
        let asm = format!("ret");
726
        self.add_asm_ret(asm);
727
    }
728
    
729
    fn emit_push_r64(&mut self, src: &P<Value>) {
730
        trace!("emit: push {}", src);
731
        
732
        let (reg, id, loc) = self.prepare_op(src, 5 + 1);
733
        let rsp = self.prepare_machine_reg(&x86_64::RSP);
734 735 736
        
        let asm = format!("pushq {}", reg);
        
737 738
        self.add_asm_inst(
            asm,
739
            vec![rsp],
740 741 742
            vec![],
            vec![id, rsp],
            vec![loc]
743
        )
744 745
    }
    
746
    fn emit_pop_r64(&mut self, dest: &P<Value>) {
747
        trace!("emit: pop {}", dest);
748
        
749
        let (reg, id, loc) = self.prepare_op(dest, 4 + 1);
750
        let rsp = self.prepare_machine_reg(&x86_64::RSP);
751 752 753
        
        let asm = format!("popq {}", reg);
        
754 755
        self.add_asm_inst(
            asm,
756
            vec![id, rsp],
757
            vec![loc.clone()],
758 759
            vec![rsp],
            vec![]
760
        )        
761
    }    
762
}