X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=interpreters%2Fbocfel%2Fbranch.c;fp=interpreters%2Fbocfel%2Fbranch.c;h=2af3d29c0d0838460f4c7d3c29951e0dfc6d77fa;hb=3c59ba5eef5cb4d39c06eb7f523b9c3b026bdc9b;hp=0000000000000000000000000000000000000000;hpb=ed91d840318ed6ebfe3a5a77fa17114ddbf56640;p=projects%2Fchimara%2Fchimara.git diff --git a/interpreters/bocfel/branch.c b/interpreters/bocfel/branch.c new file mode 100644 index 0000000..2af3d29 --- /dev/null +++ b/interpreters/bocfel/branch.c @@ -0,0 +1,91 @@ +/*- + * Copyright 2010-2012 Chris Spiegel. + * + * This file is part of Bocfel. + * + * Bocfel is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version + * 2 or 3, as published by the Free Software Foundation. + * + * Bocfel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Bocfel. If not, see . + */ + +#include + +#include "branch.h" +#include "memory.h" +#include "process.h" +#include "stack.h" +#include "util.h" +#include "zterp.h" + +void branch_if(int do_branch) +{ + uint8_t branch; + uint16_t offset; + + branch = BYTE(pc++); + + if(!do_branch) branch ^= 0x80; + + offset = branch & 0x3f; + + if((branch & 0x40) == 0) + { + offset = (offset << 8) | BYTE(pc++); + + /* Get the sign right. */ + if(offset & 0x2000) offset |= 0xc000; + } + + if(branch & 0x80) + { + if(offset > 1) + { + pc += (int16_t)offset - 2; + ZASSERT(pc < memory_size, "branch to invalid address 0x%lx", (unsigned long)pc); + } + else + { + do_return(offset); + } + } +} + +void zjump(void) +{ + /* -= 2 because pc has been advanced past the jump instruction. */ + pc += (int16_t)zargs[0]; + pc -= 2; + + ZASSERT(pc < memory_size, "@jump to invalid address 0x%lx", (unsigned long)pc); +} + +void zjz(void) +{ + branch_if(zargs[0] == 0); +} + +void zje(void) +{ + if (znargs == 1) branch_if(0); + else if(znargs == 2) branch_if(zargs[0] == zargs[1]); + else if(znargs == 3) branch_if(zargs[0] == zargs[1] || zargs[0] == zargs[2]); + else branch_if(zargs[0] == zargs[1] || zargs[0] == zargs[2] || zargs[0] == zargs[3]); +} + +void zjl(void) +{ + branch_if((int16_t)zargs[0] < (int16_t)zargs[1]); +} + +void zjg(void) +{ + branch_if((int16_t)zargs[0] > (int16_t)zargs[1]); +}